From e9f729a66403f37e94c6aa01028b7a1f282d754d Mon Sep 17 00:00:00 2001 From: Dieter Stinglhamber Date: Mon, 8 Nov 2021 10:27:23 +0100 Subject: [PATCH] add the content-type generator to the API generator --- .../generators/generators/lib/plops/api.js | 128 +++++++++------- .../generators/lib/plops/content-type.js | 143 ++++++++++-------- 2 files changed, 154 insertions(+), 117 deletions(-) diff --git a/packages/generators/generators/lib/plops/api.js b/packages/generators/generators/lib/plops/api.js index 965f167d93..da82327245 100644 --- a/packages/generators/generators/lib/plops/api.js +++ b/packages/generators/generators/lib/plops/api.js @@ -3,63 +3,85 @@ const { join } = require('path'); const fs = require('fs-extra'); const validateInput = require('./utils/validate-input'); +const contentTypePrompts = require('./content-type').prompts; +const contentTypeActions = require('./content-type').actions; module.exports = plop => { // API generator plop.setGenerator('api', { description: 'Generate a basic API', - prompts: [ - { - type: 'input', - name: 'id', - 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; + async prompts(inquirer) { + const api = await inquirer.prompt([ + { + type: 'input', + name: 'id', + message: 'API name', + validate: input => validateInput(input), }, - }, - { - type: 'list', - name: 'kind', - message: 'Please choose the model type', - default: 'collectionType', - choices: [ - { name: 'Collection Type', value: 'collectionType' }, - { name: 'Singe Type', value: 'singleType' }, - ], - }, - { - type: 'confirm', - name: 'useDraftAndPublish', - default: false, - message: 'Use draft and publish?', - }, - ], + { + 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: '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) { let filePath; if (answers.isPluginApi && answers.plugin) { @@ -91,7 +113,7 @@ module.exports = plop => { } const routeType = - answers.kind === 'singleType' + answers.modelType === 'singleType' ? 'single-type-routes.js.hbs' : 'collection-type-routes.js.hbs'; @@ -102,6 +124,8 @@ module.exports = plop => { templateFile: `templates/${routeType}`, }, ...baseActions, + // TODO: make prompts and actions more re-usable and composable + ...(answers.createContentType ? contentTypeActions(answers) : []), ]; }, }); diff --git a/packages/generators/generators/lib/plops/content-type.js b/packages/generators/generators/lib/plops/content-type.js index b66a9ccc9f..418c672cb6 100644 --- a/packages/generators/generators/lib/plops/content-type.js +++ b/packages/generators/generators/lib/plops/content-type.js @@ -76,7 +76,7 @@ const promptConfigQuestions = (plop, inquirer) => { default: 'collectionType', choices: [ { name: 'Collection Type', value: 'collectionType' }, - { name: 'Singe Type', value: 'singleType' }, + { name: 'Single Type', value: 'singleType' }, ], 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 => { // Model generator plop.setGenerator('content-type', { description: 'Generate a content type for an API', async prompts(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, - }; + return prompts(plop, inquirer); }, 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); - }, - }, - ]; + return actions(answers); }, }); }; + +module.exports.prompts = prompts; +module.exports.actions = actions;