mirror of
https://github.com/strapi/strapi.git
synced 2025-11-09 22:59:14 +00:00
add the content-type generator to the API generator
This commit is contained in:
parent
7f285fb755
commit
e9f729a664
@ -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) : []),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user