add the content-type generator to the API generator

This commit is contained in:
Dieter Stinglhamber 2021-11-08 10:27:23 +01:00
parent 7f285fb755
commit e9f729a664
2 changed files with 154 additions and 117 deletions

View File

@ -3,63 +3,85 @@
const { join } = require('path'); const { join } = require('path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const validateInput = require('./utils/validate-input'); const validateInput = require('./utils/validate-input');
const contentTypePrompts = require('./content-type').prompts;
const contentTypeActions = require('./content-type').actions;
module.exports = plop => { module.exports = plop => {
// API generator // API generator
plop.setGenerator('api', { plop.setGenerator('api', {
description: 'Generate a basic API', description: 'Generate a basic API',
prompts: [ async prompts(inquirer) {
{ const api = await inquirer.prompt([
type: 'input', {
name: 'id', type: 'input',
message: 'API name', name: 'id',
validate: input => validateInput(input), message: 'API name',
}, validate: input => validateInput(input),
{
type: 'confirm',
name: 'isPluginApi',
message: 'Is this API for a plugin?',
},
{
when: answers => answers.isPluginApi,
type: 'list',
name: 'plugin',
message: 'Plugin name',
async choices() {
const pluginsPath = join(plop.getDestBasePath(), 'plugins');
const exists = await fs.pathExists(pluginsPath);
if (!exists) {
throw Error('Couldn\'t find a "plugins" directory');
}
const pluginsDir = await fs.readdir(pluginsPath, { withFileTypes: true });
const pluginsDirContent = pluginsDir.filter(fd => fd.isDirectory());
if (pluginsDirContent.length === 0) {
throw Error('The "plugins" directory is empty');
}
return pluginsDirContent;
}, },
}, {
{ type: 'confirm',
type: 'list', name: 'isPluginApi',
name: 'kind', message: 'Is this API for a plugin?',
message: 'Please choose the model type', },
default: 'collectionType', {
choices: [ when: answers => answers.isPluginApi,
{ name: 'Collection Type', value: 'collectionType' }, type: 'list',
{ name: 'Singe Type', value: 'singleType' }, name: 'plugin',
], message: 'Plugin name',
}, async choices() {
{ const pluginsPath = join(plop.getDestBasePath(), 'plugins');
type: 'confirm', const exists = await fs.pathExists(pluginsPath);
name: 'useDraftAndPublish',
default: false, if (!exists) {
message: 'Use draft and publish?', throw Error('Couldn\'t find a "plugins" directory');
}, }
],
const pluginsDir = await fs.readdir(pluginsPath, { withFileTypes: true });
const pluginsDirContent = pluginsDir.filter(fd => fd.isDirectory());
if (pluginsDirContent.length === 0) {
throw Error('The "plugins" directory is empty');
}
return pluginsDirContent;
},
},
{
type: 'list',
name: 'modelType',
message: 'Please choose the model type',
default: 'collectionType',
choices: [
{ name: 'Collection Type', value: 'collectionType' },
{ name: 'Single Type', value: 'singleType' },
],
},
{
type: 'confirm',
name: 'useDraftAndPublish',
default: false,
message: 'Use draft and publish?',
},
{
type: 'confirm',
name: 'createContentType',
default: false,
message: 'Create a content-type?',
},
]);
if (!api.createContentType) {
return api;
}
// TODO: make prompts and actions more re-usable and composable
const contentType = await contentTypePrompts(plop, inquirer);
return {
...api,
...contentType,
};
},
actions(answers) { actions(answers) {
let filePath; let filePath;
if (answers.isPluginApi && answers.plugin) { if (answers.isPluginApi && answers.plugin) {
@ -91,7 +113,7 @@ module.exports = plop => {
} }
const routeType = const routeType =
answers.kind === 'singleType' answers.modelType === 'singleType'
? 'single-type-routes.js.hbs' ? 'single-type-routes.js.hbs'
: 'collection-type-routes.js.hbs'; : 'collection-type-routes.js.hbs';
@ -102,6 +124,8 @@ module.exports = plop => {
templateFile: `templates/${routeType}`, templateFile: `templates/${routeType}`,
}, },
...baseActions, ...baseActions,
// TODO: make prompts and actions more re-usable and composable
...(answers.createContentType ? contentTypeActions(answers) : []),
]; ];
}, },
}); });

View File

@ -76,7 +76,7 @@ const promptConfigQuestions = (plop, inquirer) => {
default: 'collectionType', default: 'collectionType',
choices: [ choices: [
{ name: 'Collection Type', value: 'collectionType' }, { name: 'Collection Type', value: 'collectionType' },
{ name: 'Singe Type', value: 'singleType' }, { name: 'Single Type', value: 'singleType' },
], ],
validate: input => validateInput(input), validate: input => validateInput(input),
}, },
@ -133,77 +133,90 @@ const promptAttributeQuestions = inquirer => {
]); ]);
}; };
// TODO: make prompts and actions more re-usable and composable
const prompts = async (plop, inquirer) => {
const config = await promptConfigQuestions(plop, inquirer);
if (!config.addAttributes) {
return {
...config,
attributes: [],
};
}
const attributes = [];
const genAttribute = async () => {
const answers = await promptAttributeQuestions(inquirer);
attributes.push(answers);
if (answers.addAttributes) {
return genAttribute();
}
};
await genAttribute();
return {
...config,
attributes,
};
};
// TODO: make prompts and actions more re-usable and composable
const actions = answers => {
const attributes = answers.attributes.reduce((object, answer) => {
const val = { type: answer.attributeType };
if (answer.attributeType === 'enumeration') {
val.enum = answer.enum.split(',').map(item => item.trim());
}
if (answer.attributeType === 'media') {
val.allowedTypes = ['images', 'files', 'videos'];
val.multiple = answer.multiple;
}
return Object.assign(object, { [answer.attributeName]: val }, {});
}, {});
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: `${filePath}/content-types/{{ singularName }}/schema.json`,
templateFile: 'templates/content-type.schema.json.hbs',
data: {
id: answers.singularName,
collectionName: slugify(answers.pluralName, { separator: '_' }),
},
},
{
type: 'modify',
path: `${filePath}/content-types/{{ singularName }}/schema.json`,
transform(template) {
const parsedTemplate = JSON.parse(template);
parsedTemplate.attributes = attributes;
return JSON.stringify(parsedTemplate, null, 2);
},
},
];
};
module.exports = plop => { module.exports = plop => {
// Model generator // Model generator
plop.setGenerator('content-type', { plop.setGenerator('content-type', {
description: 'Generate a content type for an API', description: 'Generate a content type for an API',
async prompts(inquirer) { async prompts(inquirer) {
const config = await promptConfigQuestions(plop, inquirer); return prompts(plop, inquirer);
if (!config.addAttributes) {
return {
...config,
attributes: [],
};
}
const attributes = [];
const genAttribute = async () => {
const answers = await promptAttributeQuestions(inquirer);
attributes.push(answers);
if (answers.addAttributes) {
return genAttribute();
}
};
await genAttribute();
return {
...config,
attributes,
};
}, },
actions(answers) { actions(answers) {
const attributes = answers.attributes.reduce((object, answer) => { return actions(answers);
const val = { type: answer.attributeType };
if (answer.attributeType === 'enumeration') {
val.enum = answer.enum.split(',').map(item => item.trim());
}
if (answer.attributeType === 'media') {
val.allowedTypes = ['images', 'files', 'videos'];
val.multiple = answer.multiple;
}
return Object.assign(object, { [answer.attributeName]: val }, {});
}, {});
const filePath = getFilePath(answers.destination);
return [
{
type: 'add',
path: `${filePath}/content-types/{{ singularName }}/schema.json`,
templateFile: 'templates/content-type.schema.json.hbs',
data: {
id: answers.singularName,
collectionName: slugify(answers.pluralName, { separator: '_' }),
},
},
{
type: 'modify',
path: `${filePath}/content-types/{{ singularName }}/schema.json`,
transform(template) {
const parsedTemplate = JSON.parse(template);
parsedTemplate.attributes = attributes;
return JSON.stringify(parsedTemplate, null, 2);
},
},
];
}, },
}); });
}; };
module.exports.prompts = prompts;
module.exports.actions = actions;