massive refactor

This commit is contained in:
Mark Kaylor 2021-08-26 17:41:48 +02:00
parent b9c5595aea
commit 19a8c7676d
12 changed files with 425 additions and 341 deletions

View File

@ -6,7 +6,6 @@
"license": "MIT",
"dependencies": {
"fs-extra": "10.0.0",
"inquirer": "8.1.2",
"inquirer-recursive": "0.0.7",
"node-plop": "0.26.2",
"plop": "2.7.4",

View File

@ -1,322 +1,26 @@
'use strict';
const { join } = require('path');
const fs = require('fs-extra');
const pluralize = require('pluralize');
const rootDir = process.cwd();
const getFilePath = destination => {
if (destination === 'api') {
return `api/{{api}}`;
}
if (destination === 'plugin') {
return `plugins/{{plugin}}`;
}
return `api/{{id}}`;
};
const getDestinationPrompts = action => {
return [
{
type: 'list',
name: 'destination',
message: `Where do you want to add this ${action}?`,
choices: [
{
name: `Add ${action} to ${action === 'policy' ? 'root of project' : 'new API'}`,
value: 'new',
},
{ name: `Add ${action} to existing API`, value: 'api' },
{ name: `Add ${action} to existing plugin`, value: 'plugin' },
],
},
{
when: answers => answers.destination === 'api',
type: 'input',
message: 'Which API is this for?',
name: 'api',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `api/${input}`));
return exists || 'That api does not exist, please try again';
},
},
{
when: answers => answers.destination === 'plugin',
type: 'input',
message: 'Which plugin is this for?',
name: 'plugin',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `plugins/${input}`));
return exists || 'That plugin does not exist, please try again';
},
},
];
};
const api = require('./plops/api');
const controller = require('./plops/controller');
const model = require('./plops/model');
const plugin = require('./plops/plugin');
const policy = require('./plops/policy');
const service = require('./plops/service');
module.exports = function(plop) {
const rootDir = process.cwd();
// Plop config
plop.setWelcomeMessage('Strapi Generators');
plop.addHelper('pluralize', text => pluralize(text));
// API generator
plop.setGenerator('api', {
description: 'Generate a basic API',
prompts: [
{
type: 'input',
name: 'id',
message: 'API name',
},
{
type: 'list',
name: 'kind',
message: 'Please choose the model type',
choices: [
{ name: 'Collection Type', value: 'collectionType' },
{ name: 'Singe Type', value: 'singleType' },
],
},
{
type: 'confirm',
name: 'isPluginApi',
message: 'Is this API for a plugin?',
},
{
when: answers => answers.isPluginApi,
type: 'input',
name: 'plugin',
message: 'Plugin name',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `plugins/${input}`));
return exists || 'That plugin does not exist, please try again';
},
},
{
type: 'confirm',
name: 'useDraftAndPublish',
message: 'Use draft and publish?',
},
],
actions: answers => {
let filePath;
if (answers.isPluginApi && answers.plugin) {
filePath = `plugins/{{plugin}}`;
} else {
filePath = `api/{{id}}`;
}
const baseActions = [
{
type: 'add',
path: join(rootDir, `${filePath}/controllers/{{id}}.js`),
templateFile: 'templates/controller.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.js`),
templateFile: 'templates/model.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.settings.json`),
templateFile: 'templates/model.settings.json.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/services/{{id}}.js`),
templateFile: 'templates/service.js.hbs',
},
];
if (answers.isPluginApi) {
return baseActions;
} else {
return [
{
type: 'add',
path: join(rootDir, `${filePath}/config/routes.json`),
templateFile: 'templates/api-routes.json.hbs',
},
...baseActions,
];
}
},
});
// Controller generator
plop.setGenerator('controller', {
description: 'Generate a controller for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Controller name',
},
...getDestinationPrompts('controller'),
],
actions: answers => {
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/controllers/{{id}}.js`),
templateFile: 'templates/controller.js.hbs',
},
];
},
});
plop.setPrompt('recursive', require('inquirer-recursive'));
// Model generator
plop.setGenerator('model', {
description: 'Generate a model for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Model name',
},
{
type: 'list',
name: 'kind',
message: 'Please choose the model type',
choices: [
{ name: 'Collection Type', value: 'collectionType' },
{ name: 'Singe Type', value: 'singleType' },
],
},
...getDestinationPrompts('model'),
{
type: 'addAttributes',
name: 'attributes',
},
{
type: 'confirm',
name: 'useDraftAndPublish',
message: 'Use draft and publish?',
},
],
actions: answers => {
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.js`),
templateFile: 'templates/model.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.settings.json`),
templateFile: 'templates/model.settings.json.hbs',
},
];
},
});
const { prompts } = plop.inquirer.prompt;
console.log(prompts);
// Plugin generator
plop.setGenerator('plugin', {
description: 'Generate a basic plugin',
prompts: [
{
type: 'input',
name: 'id',
message: 'Plugin name',
},
],
actions: answers => {
fs.copySync(join(__dirname, 'files', 'plugin'), join(rootDir, 'plugins', answers.id));
return [
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/services/{{id}}.js'),
templateFile: 'templates/service.js.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/controllers/{{id}}.js'),
templateFile: 'templates/controller.js.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/config/routes.json'),
templateFile: 'templates/plugin-routes.json.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/README.md'),
templateFile: 'templates/README.md.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/package.json'),
templateFile: 'templates/plugin-package.json.hbs',
},
];
},
});
// Policy generator
plop.setGenerator('policy', {
description: 'Generate a policy for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Policy name',
},
...getDestinationPrompts('policy'),
],
actions: answers => {
let filePath;
if (answers.destination === 'api') {
filePath = `api/{{api}}`;
} else if (answers.destination === 'plugin') {
filePath = `plugins/{{plugin}}`;
} else {
filePath = ``;
}
return [
{
type: 'add',
path: join(rootDir, `${filePath}/config/policies/{{id}}.js`),
templateFile: 'templates/policy.js.hbs',
},
];
},
});
// Service generator
plop.setGenerator('service', {
description: 'Generate a service for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Service name',
},
...getDestinationPrompts('service'),
],
actions: answers => {
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/services/{{id}}.js`),
templateFile: 'templates/service.js.hbs',
},
];
},
});
// Generators
api(plop, rootDir);
controller(plop, rootDir);
model(plop, rootDir);
plugin(plop, rootDir);
policy(plop, rootDir);
service(plop, rootDir);
};

View File

@ -0,0 +1,92 @@
'use strict';
const { join } = require('path');
const fs = require('fs-extra');
module.exports = (plop, rootDir) => {
// API generator
plop.setGenerator('api', {
description: 'Generate a basic API',
prompts: [
{
type: 'input',
name: 'id',
message: 'API name',
},
{
type: 'list',
name: 'kind',
message: 'Please choose the model type',
choices: [
{ name: 'Collection Type', value: 'collectionType' },
{ name: 'Singe Type', value: 'singleType' },
],
},
{
type: 'confirm',
name: 'isPluginApi',
message: 'Is this API for a plugin?',
},
{
when: answers => answers.isPluginApi,
type: 'input',
name: 'plugin',
message: 'Plugin name',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `plugins/${input}`));
return exists || 'That plugin does not exist, please try again';
},
},
{
type: 'confirm',
name: 'useDraftAndPublish',
message: 'Use draft and publish?',
},
],
actions: answers => {
let filePath;
if (answers.isPluginApi && answers.plugin) {
filePath = `plugins/{{plugin}}`;
} else {
filePath = `api/{{id}}`;
}
const baseActions = [
{
type: 'add',
path: join(rootDir, `${filePath}/controllers/{{id}}.js`),
templateFile: 'templates/controller.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.js`),
templateFile: 'templates/model.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.settings.json`),
templateFile: 'templates/model.settings.json.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/services/{{id}}.js`),
templateFile: 'templates/service.js.hbs',
},
];
if (answers.isPluginApi) {
return baseActions;
} else {
return [
{
type: 'add',
path: join(rootDir, `${filePath}/config/routes.json`),
templateFile: 'templates/api-routes.json.hbs',
},
...baseActions,
];
}
},
});
};

View File

@ -0,0 +1,31 @@
'use strict';
const { join } = require('path');
const getDestinationPrompts = require('./utils/get-destination-prompts');
const getFilePath = require('./utils/get-file-path');
module.exports = (plop, rootDir) => {
// Controller generator
plop.setGenerator('controller', {
description: 'Generate a controller for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Controller name',
},
...getDestinationPrompts('controller'),
],
actions: answers => {
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/controllers/{{id}}.js`),
templateFile: 'templates/controller.js.hbs',
},
];
},
});
};

View File

@ -0,0 +1,115 @@
'use strict';
const { join } = require('path');
const getDestinationPrompts = require('./utils/get-destination-prompts');
const getFilePath = require('./utils/get-file-path');
const DEFAULT_TYPES = [
// advanced types
'media',
// scalar types
'string',
'text',
'richtext',
'json',
'enumeration',
'password',
'email',
'integer',
'biginteger',
'float',
'decimal',
'date',
'time',
'datetime',
'timestamp',
'boolean',
'relation',
];
module.exports = (plop, rootDir) => {
// Model generator
plop.setGenerator('model', {
description: 'Generate a model for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Model name',
},
{
type: 'list',
name: 'kind',
message: 'Please choose the model type',
choices: [
{ name: 'Collection Type', value: 'collectionType' },
{ name: 'Singe Type', value: 'singleType' },
],
},
...getDestinationPrompts('model'),
{
type: 'confirm',
name: 'useDraftAndPublish',
message: 'Use draft and publish?',
},
{
type: 'recursive',
message: 'Add attribute?',
name: 'attributes',
prompts: [
{
type: 'input',
name: 'attributeName',
message: 'Name of attribute',
},
{
type: 'list',
name: 'attributeType',
message: 'What type of attribute',
pageSize: DEFAULT_TYPES.length,
choices: DEFAULT_TYPES.map(type => {
return { name: type, value: type };
}),
},
],
},
],
actions: answers => {
const attributes = answers.attributes.reduce((object, answer) => {
// Rest/spread properties are not supported until Node.js 8.3.0.
// The configured version range is '>=8.0.0'
return Object.assign(
object,
{ [answer.attributeName]: { type: answer.attributeType } },
{}
);
}, {});
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.js`),
templateFile: 'templates/model.js.hbs',
},
{
type: 'add',
path: join(rootDir, `${filePath}/models/{{id}}.settings.json`),
templateFile: 'templates/model.settings.json.hbs',
},
{
type: 'modify',
path: join(rootDir, `${filePath}/models/{{id}}.settings.json`),
transform: template => {
const temp = JSON.parse(template);
temp.attributes = attributes;
return JSON.stringify(temp, null, 2);
},
},
];
},
});
};

View File

@ -0,0 +1,48 @@
'use strict';
const { join } = require('path');
const fs = require('fs-extra');
module.exports = (plop, rootDir) => {
// Plugin generator
plop.setGenerator('plugin', {
description: 'Generate a basic plugin',
prompts: [
{
type: 'input',
name: 'id',
message: 'Plugin name',
},
],
actions: answers => {
fs.copySync(join(__dirname, 'files', 'plugin'), join(rootDir, 'plugins', answers.id));
return [
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/services/{{id}}.js'),
templateFile: 'templates/service.js.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/controllers/{{id}}.js'),
templateFile: 'templates/controller.js.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/config/routes.json'),
templateFile: 'templates/plugin-routes.json.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/README.md'),
templateFile: 'templates/README.md.hbs',
},
{
type: 'add',
path: join(rootDir, 'plugins/{{id}}/package.json'),
templateFile: 'templates/plugin-package.json.hbs',
},
];
},
});
};

View File

@ -0,0 +1,37 @@
'use strict';
const { join } = require('path');
const getDestinationPrompts = require('./utils/get-destination-prompts');
module.exports = (plop, rootDir) => {
// Policy generator
plop.setGenerator('policy', {
description: 'Generate a policy for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Policy name',
},
...getDestinationPrompts('policy'),
],
actions: answers => {
let filePath;
if (answers.destination === 'api') {
filePath = `api/{{api}}`;
} else if (answers.destination === 'plugin') {
filePath = `plugins/{{plugin}}`;
} else {
filePath = ``;
}
return [
{
type: 'add',
path: join(rootDir, `${filePath}/config/policies/{{id}}.js`),
templateFile: 'templates/policy.js.hbs',
},
];
},
});
};

View File

@ -0,0 +1,30 @@
'use strict';
const { join } = require('path');
const getDestinationPrompts = require('./utils/get-destination-prompts');
const getFilePath = require('./utils/get-file-path');
module.exports = (plop, rootDir) => {
// Service generator
plop.setGenerator('service', {
description: 'Generate a service for an API',
prompts: [
{
type: 'input',
name: 'id',
message: 'Service name',
},
...getDestinationPrompts('service'),
],
actions: answers => {
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: join(rootDir, `${filePath}/services/{{id}}.js`),
templateFile: 'templates/service.js.hbs',
},
];
},
});
};

View File

@ -0,0 +1,43 @@
'use strict';
const { join } = require('path');
const fs = require('fs-extra');
module.exports = (action, rootDir) => {
return [
{
type: 'list',
name: 'destination',
message: `Where do you want to add this ${action}?`,
choices: [
{
name: `Add ${action} to ${action === 'policy' ? 'root of project' : 'new API'}`,
value: 'new',
},
{ name: `Add ${action} to existing API`, value: 'api' },
{ name: `Add ${action} to existing plugin`, value: 'plugin' },
],
},
{
when: answers => answers.destination === 'api',
type: 'input',
message: 'Which API is this for?',
name: 'api',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `api/${input}`));
return exists || 'That api does not exist, please try again';
},
},
{
when: answers => answers.destination === 'plugin',
type: 'input',
message: 'Which plugin is this for?',
name: 'plugin',
validate: async input => {
const exists = await fs.pathExists(join(rootDir, `plugins/${input}`));
return exists || 'That plugin does not exist, please try again';
},
},
];
};

View File

@ -0,0 +1,13 @@
'use strict';
module.exports = destination => {
if (destination === 'api') {
return `api/{{api}}`;
}
if (destination === 'plugin') {
return `plugins/{{plugin}}`;
}
return `api/{{id}}`;
};

View File

@ -8,6 +8,5 @@
"options": {
"draftAndPublish": {{useDraftAndPublish}},
"comment": ""
},
"attributes": {}
}
}

View File

@ -11187,26 +11187,6 @@ inquirer@8.1.0:
strip-ansi "^6.0.0"
through "^2.3.6"
inquirer@8.1.2:
version "8.1.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.2.tgz#65b204d2cd7fb63400edd925dfe428bafd422e3d"
integrity sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
cli-cursor "^3.1.0"
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.21"
mute-stream "0.0.8"
ora "^5.3.0"
run-async "^2.4.0"
rxjs "^7.2.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
inquirer@^6.2.0, inquirer@^6.2.1, inquirer@^6.3.1:
version "6.5.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
@ -18282,13 +18262,6 @@ rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.6, rxjs@^6.6.7:
dependencies:
tslib "^1.9.0"
rxjs@^7.2.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6"
integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==
dependencies:
tslib "~2.1.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"