mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
Merge pull request #10783 from strapi/v4/plop-generators
V4/plop generators
This commit is contained in:
commit
45100abdf7
@ -5,15 +5,11 @@
|
||||
testApp/**
|
||||
examples/**
|
||||
cypress/**
|
||||
packages/generators/plugin/files/admin/src/**
|
||||
packages/generators/generators/lib/files/
|
||||
packages/core/helper-plugin/build/**
|
||||
packages/core/helper-plugin/lib/src/components/**
|
||||
packages/core/helper-plugin/lib/src/testUtils/**
|
||||
packages/core/helper-plugin/lib/src/utils/**
|
||||
packages/plugins/users-permissions/admin/OLD/**
|
||||
.eslintrc.js
|
||||
.eslintrc.front.js
|
||||
.eslintrc.back.js
|
||||
|
||||
bookshelf.old
|
||||
database.old
|
||||
|
||||
@ -40,4 +40,4 @@
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE"
|
||||
}
|
||||
}
|
||||
@ -11,8 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@strapi/generate": "3.6.8",
|
||||
"@strapi/generate-api": "3.6.8",
|
||||
"@strapi/generators": "3.6.8",
|
||||
"@strapi/helper-plugin": "3.6.8",
|
||||
"@strapi/utils": "3.6.8",
|
||||
"fs-extra": "^9.1.0",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
const { getOr } = require('lodash/fp');
|
||||
const generator = require('@strapi/generate');
|
||||
const strapiGenerators = require('@strapi/generators');
|
||||
|
||||
const { nameToSlug, contentTypes: contentTypesUtils } = require('@strapi/utils');
|
||||
const { formatAttributes, replaceTemporaryUIDs } = require('../utils/attributes');
|
||||
@ -127,23 +127,7 @@ const createContentType = async ({ contentType, components = [] }, options = {})
|
||||
* @param {string} name
|
||||
*/
|
||||
const generateAPI = ({ name, kind = 'collectionType' }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const scope = {
|
||||
generatorType: 'api',
|
||||
id: nameToSlug(name),
|
||||
name: nameToSlug(name),
|
||||
rootPath: strapi.dir,
|
||||
args: {
|
||||
attributes: {},
|
||||
kind,
|
||||
},
|
||||
};
|
||||
|
||||
generator(scope, {
|
||||
success: () => resolve(),
|
||||
error: err => reject(err),
|
||||
});
|
||||
});
|
||||
return strapiGenerators.generate('api', { id: nameToSlug(name), kind }, { dir: strapi.dir });
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -118,68 +118,22 @@ program
|
||||
.description('Start your Strapi application in development mode')
|
||||
.action(getLocalScript('develop'));
|
||||
|
||||
// `$ strapi generate:api`
|
||||
// $ strapi generate
|
||||
program
|
||||
.command('generate:api <id> [attributes...]')
|
||||
.option('-a, --api <api>', 'API name to generate the files in')
|
||||
.option('-p, --plugin <api>', 'Name of the local plugin')
|
||||
.option('-e, --extend <api>', 'Name of the plugin to extend')
|
||||
.option('--draft-and-publish', 'Enable draft/publish', false)
|
||||
.description('Generate a basic API')
|
||||
.action((id, attributes, cliArguments) => {
|
||||
cliArguments.attributes = attributes;
|
||||
getLocalScript('generate')(id, cliArguments);
|
||||
.command('generate')
|
||||
.description('Launch interactive API generator')
|
||||
.action(() => {
|
||||
checkCwdIsStrapiApp('generate');
|
||||
process.argv.splice(2, 1);
|
||||
require('@strapi/generators').runCLI();
|
||||
});
|
||||
|
||||
// `$ strapi generate:controller`
|
||||
program
|
||||
.command('generate:controller <id>')
|
||||
.option('-a, --api <api>', 'API name to generate the files in')
|
||||
.option('-p, --plugin <api>', 'Name of the local plugin')
|
||||
.option('-e, --extend <api>', 'Name of the plugin to extend')
|
||||
.description('Generate a controller for an API')
|
||||
.action(getLocalScript('generate'));
|
||||
|
||||
// `$ strapi generate:model`
|
||||
program
|
||||
.command('generate:model <id> [attributes...]')
|
||||
.option('-a, --api <api>', 'API name to generate a sub API')
|
||||
.option('-p, --plugin <api>', 'plugin name')
|
||||
.option('--draft-and-publish', 'Enable draft/publish', false)
|
||||
.description('Generate a model for an API')
|
||||
.action((id, attributes, cliArguments) => {
|
||||
cliArguments.attributes = attributes;
|
||||
getLocalScript('generate')(id, cliArguments);
|
||||
});
|
||||
|
||||
// `$ strapi generate:policy`
|
||||
program
|
||||
.command('generate:policy <id>')
|
||||
.option('-a, --api <api>', 'API name')
|
||||
.option('-p, --plugin <api>', 'plugin name')
|
||||
.description('Generate a policy for an API')
|
||||
.action(getLocalScript('generate'));
|
||||
|
||||
// `$ strapi generate:service`
|
||||
program
|
||||
.command('generate:service <id>')
|
||||
.option('-a, --api <api>', 'API name')
|
||||
.option('-p, --plugin <api>', 'plugin name')
|
||||
.description('Generate a service for an API')
|
||||
.action(getLocalScript('generate'));
|
||||
|
||||
// `$ strapi generate:plugin`
|
||||
program
|
||||
.command('generate:plugin <id>')
|
||||
.option('-n, --name <name>', 'Plugin name')
|
||||
.description('Generate a basic plugin')
|
||||
.action(getLocalScript('generate'));
|
||||
|
||||
// `$ strapi generate:template <directory>`
|
||||
program
|
||||
.command('generate:template <directory>')
|
||||
.description('Generate template from Strapi project')
|
||||
.action(getLocalScript('generate-template'));
|
||||
|
||||
program
|
||||
.command('build')
|
||||
.option('--clean', 'Remove the build and .cache folders', false)
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// FIXME
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Master of ceremonies for generators.
|
||||
const generate = require('@strapi/generate');
|
||||
|
||||
// Logger.
|
||||
const { createLogger } = require('@strapi/logger');
|
||||
|
||||
// Configuration
|
||||
const loadConfiguration = require('../core/app-configuration');
|
||||
|
||||
// Local Strapi dependencies.
|
||||
const packageJSON = require('../../package.json');
|
||||
|
||||
/**
|
||||
* `$ strapi generate`
|
||||
*
|
||||
* Scaffolding for the application in our working directory.
|
||||
*/
|
||||
|
||||
module.exports = function(id, cliArguments) {
|
||||
const dir = process.cwd();
|
||||
const config = loadConfiguration(dir);
|
||||
const logger = createLogger(config.get('logger', {}));
|
||||
|
||||
// Build initial scope.
|
||||
const scope = {
|
||||
rootPath: process.cwd(),
|
||||
strapiRoot: path.resolve(__dirname, '..'),
|
||||
id: id,
|
||||
args: cliArguments,
|
||||
strapiPackageJSON: packageJSON,
|
||||
};
|
||||
|
||||
scope.generatorType = process.argv[2].split(':')[1];
|
||||
|
||||
// Show usage if no generator type is defined.
|
||||
if (!scope.generatorType) {
|
||||
return logger.error('Write `$ strapi generate:something` instead.');
|
||||
}
|
||||
|
||||
return generate(scope, {
|
||||
// Log and exit the REPL in case there is an error
|
||||
// while we were trying to generate the requested generator.
|
||||
error(msg) {
|
||||
logger.error(msg);
|
||||
process.exit(1);
|
||||
},
|
||||
|
||||
// Log and exit the REPL in case of success
|
||||
// but first make sure we have all the info we need.
|
||||
success() {
|
||||
if (!scope.outputPath && scope.filename && scope.destDir) {
|
||||
scope.outputPath = scope.destDir + scope.filename;
|
||||
}
|
||||
|
||||
if (scope.generatorType !== 'new') {
|
||||
logger.info(
|
||||
`Generated a new ${scope.generatorType} \`${scope.name}\` at \`${scope.filePath}\`.`
|
||||
);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -16,14 +16,8 @@
|
||||
"@koa/cors": "^3.0.0",
|
||||
"@strapi/admin": "3.6.8",
|
||||
"@strapi/database": "3.6.8",
|
||||
"@strapi/generate": "3.6.8",
|
||||
"@strapi/generate-api": "3.6.8",
|
||||
"@strapi/generate-controller": "3.6.8",
|
||||
"@strapi/generate-model": "3.6.8",
|
||||
"@strapi/generators": "3.6.8",
|
||||
"@strapi/generate-new": "3.6.8",
|
||||
"@strapi/generate-plugin": "3.6.8",
|
||||
"@strapi/generate-policy": "3.6.8",
|
||||
"@strapi/generate-service": "3.6.8",
|
||||
"@strapi/logger": "3.6.8",
|
||||
"@strapi/utils": "3.6.8",
|
||||
"async": "^2.1.2",
|
||||
@ -64,6 +58,7 @@
|
||||
"open": "8.2.1",
|
||||
"ora": "^5.4.0",
|
||||
"package-json": "6.5.0",
|
||||
"plop": "2.7.4",
|
||||
"pluralize": "8.0.0",
|
||||
"qs": "^6.10.1",
|
||||
"resolve-cwd": "^3.0.0",
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{package.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
102
packages/generators/api/.gitignore
vendored
102
packages/generators/api/.gitignore
vendored
@ -1,102 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
testApp
|
||||
coverage
|
||||
@ -1,109 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
.snyk
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
tests
|
||||
__tests__
|
||||
jest.config.js
|
||||
testApp
|
||||
coverage
|
||||
@ -1,9 +0,0 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.12.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
shelljs:
|
||||
- '*':
|
||||
reason: testing
|
||||
expires: 2019-01-04T14:35:54.864Z
|
||||
patch: {}
|
||||
@ -1,22 +0,0 @@
|
||||
Copyright (c) 2015-present Strapi Solutions SAS
|
||||
|
||||
Portions of the Strapi software are licensed as follows:
|
||||
|
||||
* All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
||||
|
||||
* All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
|
||||
|
||||
MIT Expat License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,25 +0,0 @@
|
||||
# strapi-generate-api
|
||||
|
||||
[](https://www.npmjs.org/package/strapi-generate-api)
|
||||
[](https://www.npmjs.org/package/strapi-generate-api)
|
||||
[](https://david-dm.org/strapi/strapi-generate-api)
|
||||
[](https://travis-ci.org/strapi/strapi-generate-api)
|
||||
[](https://slack.strapi.io)
|
||||
|
||||
This Strapi generator contains all the default files for a new API.
|
||||
|
||||
This generator can be called with:
|
||||
|
||||
```bash
|
||||
$ strapi generate:api apiName
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [License](LICENSE)
|
||||
|
||||
## Links
|
||||
|
||||
- [Strapi website](https://strapi.io/)
|
||||
- [Strapi community on Slack](https://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
@ -1,7 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
name: 'generate-api',
|
||||
displayName: 'Generated API',
|
||||
testMatch: ['**/test/?(*.)+(spec|test).js'],
|
||||
};
|
||||
@ -1,108 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const fs = require('fs');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
|
||||
function generateSingleTypeRoutes({ route, name }) {
|
||||
return [
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/' + route,
|
||||
handler: name + '.find',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'PUT',
|
||||
path: '/' + route,
|
||||
handler: name + '.update',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'DELETE',
|
||||
path: '/' + route,
|
||||
handler: name + '.delete',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function generateCollectionTypeRoutes({ route, name }) {
|
||||
return [
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/' + route,
|
||||
handler: name + '.find',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/' + route + '/:id',
|
||||
handler: name + '.findOne',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/' + route,
|
||||
handler: name + '.create',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'PUT',
|
||||
path: '/' + route + '/:id',
|
||||
handler: name + '.update',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'DELETE',
|
||||
path: '/' + route + '/:id',
|
||||
handler: name + '.delete',
|
||||
config: {
|
||||
policies: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose main routes of the generated API
|
||||
*/
|
||||
|
||||
module.exports = scope => {
|
||||
let routes = [];
|
||||
if (!scope.args.plugin) {
|
||||
routes =
|
||||
scope.contentTypeKind === 'singleType'
|
||||
? generateSingleTypeRoutes({ route: scope.route, name: scope.name })
|
||||
: generateCollectionTypeRoutes({ route: scope.route, name: scope.name });
|
||||
}
|
||||
|
||||
// if routes.json already exists, then merge
|
||||
if (fs.existsSync(scope.rootPath)) {
|
||||
let current = require(scope.rootPath);
|
||||
fs.unlinkSync(scope.rootPath);
|
||||
routes = _.concat(routes, _.differenceWith(current.routes, routes, _.isEqual));
|
||||
}
|
||||
|
||||
return { routes };
|
||||
};
|
||||
@ -1,138 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const { nameToSlug } = require('@strapi/utils');
|
||||
|
||||
/**
|
||||
* This `before` function is run before generating targets.
|
||||
* Validate, configure defaults, get extra dependencies, etc.
|
||||
*
|
||||
* @param {Object} scope
|
||||
* @param {Function} cb
|
||||
*/
|
||||
|
||||
module.exports = (scope, cb) => {
|
||||
if (!scope.rootPath || !scope.id) {
|
||||
return cb.invalid('Usage: `$ strapi generate:api apiName`');
|
||||
}
|
||||
|
||||
// Format `id`.
|
||||
const name = scope.name || nameToSlug(scope.id);
|
||||
|
||||
scope.contentTypeKind = scope.args.kind || 'collectionType';
|
||||
|
||||
// `scope.args` are the raw command line arguments.
|
||||
_.defaults(scope, {
|
||||
name,
|
||||
route:
|
||||
scope.contentTypeKind === 'singleType'
|
||||
? _.kebabCase(scope.id)
|
||||
: _.kebabCase(pluralize(scope.id)),
|
||||
});
|
||||
|
||||
let filePath;
|
||||
if (scope.args.api) {
|
||||
filePath = `./api/${scope.args.api}`;
|
||||
} else if (scope.args.plugin) {
|
||||
filePath = `./plugins/${scope.args.plugin}`;
|
||||
} else if (scope.args.extend) {
|
||||
filePath = `./extensions/${scope.args.extend}`;
|
||||
} else {
|
||||
filePath = `./api/${name}`;
|
||||
}
|
||||
|
||||
// Take another pass to take advantage of the defaults absorbed in previous passes.
|
||||
_.defaults(scope, {
|
||||
filename: `${name}.js`,
|
||||
filenameSettings: `${name}.settings.json`,
|
||||
filePath,
|
||||
});
|
||||
|
||||
// Validate optional attribute arguments.
|
||||
const invalidAttributes = [];
|
||||
|
||||
if (_.isPlainObject(scope.args.attributes)) {
|
||||
scope.attributes = scope.args.attributes;
|
||||
} else {
|
||||
// Map attributes and split them for CLI.
|
||||
scope.attributes = scope.args.attributes.map(attribute => {
|
||||
if (_.isString(attribute)) {
|
||||
const parts = attribute.split(':');
|
||||
|
||||
parts[1] = parts[1] || 'string';
|
||||
|
||||
// Handle invalid attributes.
|
||||
if (!parts[1] || !parts[0]) {
|
||||
invalidAttributes.push('Error: Invalid attribute notation `' + attribute + '`.');
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
name: _.trim(_.deburr(parts[0].toLowerCase())),
|
||||
params: {
|
||||
type: _.trim(_.deburr(parts[1].toLowerCase())),
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return _.has(attribute, 'params.type') ? attribute : undefined;
|
||||
}
|
||||
});
|
||||
|
||||
scope.attributes = _.compact(scope.attributes);
|
||||
|
||||
// Handle invalid action arguments.
|
||||
// Send back invalidActions.
|
||||
if (invalidAttributes.length) {
|
||||
return cb.invalid(invalidAttributes);
|
||||
}
|
||||
|
||||
// Make sure there aren't duplicates.
|
||||
if (
|
||||
_(scope.attributes.map(attribute => attribute.name))
|
||||
.uniq()
|
||||
.valueOf().length !== scope.attributes.length
|
||||
) {
|
||||
return cb.invalid('Duplicate attributes not allowed!');
|
||||
}
|
||||
|
||||
// Render some stringified code from the action template
|
||||
// and make it available in our scope for use later on.
|
||||
scope.attributes = scope.attributes.reduce((acc, attribute) => {
|
||||
acc[attribute.name] = attribute.params;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
// Set collectionName
|
||||
scope.collectionName = _.has(scope.args, 'collectionName')
|
||||
? scope.args.collectionName
|
||||
: _.snakeCase(pluralize(name));
|
||||
|
||||
// Set description
|
||||
scope.description = _.has(scope.args, 'description') ? scope.args.description : '';
|
||||
|
||||
scope.schema = JSON.stringify(
|
||||
{
|
||||
collectionName: scope.collectionName,
|
||||
info: {
|
||||
name: scope.args.displayName || scope.id,
|
||||
description: scope.description,
|
||||
},
|
||||
options: {
|
||||
draftAndPublish: scope.args.draftAndPublish === 'true',
|
||||
comment: '',
|
||||
},
|
||||
attributes: scope.attributes,
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
|
||||
// Trigger callback with no error to proceed.
|
||||
return cb.success();
|
||||
};
|
||||
@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// FIXME
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
// Local dependencies.
|
||||
const routesJSON = require('../json/routes.json.js');
|
||||
|
||||
/**
|
||||
* Generate a core API
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
templatesDirectory: path.resolve(__dirname, '..', 'templates'),
|
||||
before: require('./before'),
|
||||
targets: {
|
||||
// Use the default `controller` file as a template for
|
||||
// every generated controller.
|
||||
':filePath/controllers/:filename': {
|
||||
template: 'controller.template',
|
||||
},
|
||||
|
||||
// every generated controller.
|
||||
':filePath/services/:filename': {
|
||||
template: 'service.template',
|
||||
},
|
||||
|
||||
// Copy an empty JavaScript model where every functions will be.
|
||||
':filePath/models/:filename': {
|
||||
template: 'model.template',
|
||||
},
|
||||
|
||||
// Copy the generated JSON model for the connection,
|
||||
// schema and attributes.
|
||||
':filePath/models/:filenameSettings': {
|
||||
template: 'model.settings.template',
|
||||
},
|
||||
|
||||
// Generate routes.
|
||||
':filePath/config/routes.json': {
|
||||
jsonfile: routesJSON,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -1,48 +0,0 @@
|
||||
{
|
||||
"name": "@strapi/generate-api",
|
||||
"version": "3.6.8",
|
||||
"description": "Generate an API for a Strapi application.",
|
||||
"homepage": "https://strapi.io",
|
||||
"keywords": [
|
||||
"generate",
|
||||
"generator",
|
||||
"strapi"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21",
|
||||
"pluralize": "^8.0.0",
|
||||
"@strapi/utils": "3.6.8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
"name": "Strapi team",
|
||||
"url": "https://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x.x <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"gitHead": "231263a3535658bab1e9492c6aaaed8692d62a53"
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
|
||||
* to customize this controller
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -1 +0,0 @@
|
||||
<%= schema %>
|
||||
@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#lifecycle-hooks)
|
||||
* to customize this model
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-services)
|
||||
* to customize this service
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -1,16 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{package.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@ -1,109 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
.snyk
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
tests
|
||||
__tests__
|
||||
jest.config.js
|
||||
testApp
|
||||
coverage
|
||||
@ -1,9 +0,0 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.12.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
shelljs:
|
||||
- '*':
|
||||
reason: testing
|
||||
expires: 2019-01-04T14:35:57.351Z
|
||||
patch: {}
|
||||
@ -1,22 +0,0 @@
|
||||
Copyright (c) 2015-present Strapi Solutions SAS
|
||||
|
||||
Portions of the Strapi software are licensed as follows:
|
||||
|
||||
* All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
||||
|
||||
* All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
|
||||
|
||||
MIT Expat License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,31 +0,0 @@
|
||||
# strapi-generate-controller
|
||||
|
||||
[](https://www.npmjs.org/package/strapi-generate-controller)
|
||||
[](https://www.npmjs.org/package/strapi-generate-controller)
|
||||
[](https://david-dm.org/strapi/strapi-generate-controller)
|
||||
[](https://travis-ci.org/strapi/strapi-generate-controller)
|
||||
[](https://slack.strapi.io)
|
||||
|
||||
This Strapi generator contains the default files for a controller.
|
||||
|
||||
This generator can be called with:
|
||||
|
||||
```bash
|
||||
$ strapi generate:controller controllerName apiName
|
||||
```
|
||||
|
||||
For example if you want to generate a `group` controller for the `user` API:
|
||||
|
||||
```bash
|
||||
$ strapi generate:controller group user
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [License](LICENSE)
|
||||
|
||||
## Links
|
||||
|
||||
- [Strapi website](https://strapi.io/)
|
||||
- [Strapi community on Slack](https://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
@ -1,56 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const { nameToSlug } = require('@strapi/utils');
|
||||
/* eslint-disable prefer-template */
|
||||
/**
|
||||
* This `before` function is run before generating targets.
|
||||
* Validate, configure defaults, get extra dependencies, etc.
|
||||
*
|
||||
* @param {Object} scope
|
||||
* @param {Function} cb
|
||||
*/
|
||||
|
||||
module.exports = (scope, cb) => {
|
||||
if (!scope.rootPath || !scope.id) {
|
||||
return cb.invalid(
|
||||
'Usage: `$ strapi generate:controller controllerName --api apiName --plugin pluginName`'
|
||||
);
|
||||
}
|
||||
|
||||
// Format `id`.
|
||||
const name = scope.name || nameToSlug(scope.id);
|
||||
|
||||
// `scope.args` are the raw command line arguments.
|
||||
_.defaults(scope, {
|
||||
name,
|
||||
api: scope.id,
|
||||
});
|
||||
|
||||
// Determine the destination path.
|
||||
let filePath;
|
||||
if (scope.args.api) {
|
||||
filePath = `./api/${scope.args.api}/controllers`;
|
||||
} else if (scope.args.plugin) {
|
||||
filePath = `./plugins/${scope.args.plugin}/controllers`;
|
||||
} else if (scope.args.extend) {
|
||||
filePath = `./extensions/${scope.args.extend}/controllers`;
|
||||
} else {
|
||||
filePath = `./api/${name}/controllers`;
|
||||
}
|
||||
|
||||
// Take another pass to take advantage of the defaults absorbed in previous passes.
|
||||
_.defaults(scope, {
|
||||
rootPath: scope.rootPath,
|
||||
filePath,
|
||||
filename: `${name}.js`,
|
||||
});
|
||||
|
||||
// Trigger callback with no error to proceed.
|
||||
return cb();
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Generate a core API
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
templatesDirectory: path.resolve(__dirname, '..', 'templates'),
|
||||
before: require('./before'),
|
||||
targets: {
|
||||
':filePath/:filename': {
|
||||
template: 'controller.template',
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -1,48 +0,0 @@
|
||||
{
|
||||
"name": "@strapi/generate-controller",
|
||||
"version": "3.6.8",
|
||||
"description": "Generate a controller for a Strapi API.",
|
||||
"homepage": "https://strapi.io",
|
||||
"keywords": [
|
||||
"controller",
|
||||
"generate",
|
||||
"generator",
|
||||
"strapi"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21",
|
||||
"@strapi/utils": "3.6.8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
"name": "Strapi team",
|
||||
"url": "https://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x.x <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"gitHead": "231263a3535658bab1e9492c6aaaed8692d62a53"
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{package.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
104
packages/generators/generate/.gitignore
vendored
104
packages/generators/generate/.gitignore
vendored
@ -1,104 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
testApp
|
||||
coverage
|
||||
@ -1,109 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
.snyk
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
tests
|
||||
__tests__
|
||||
jest.config.js
|
||||
testApp
|
||||
coverage
|
||||
@ -1,9 +0,0 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.12.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
shelljs:
|
||||
- '*':
|
||||
reason: testing
|
||||
expires: 2019-01-04T14:35:22.585Z
|
||||
patch: {}
|
||||
@ -1,25 +0,0 @@
|
||||
# strapi-generate
|
||||
|
||||
[](https://www.npmjs.org/package/strapi-generate)
|
||||
[](https://www.npmjs.org/package/strapi-generate)
|
||||
[](https://david-dm.org/strapi/strapi-generate)
|
||||
[](https://travis-ci.org/strapi/strapi-generate)
|
||||
[](https://slack.strapi.io)
|
||||
|
||||
Master of ceremonies for generators in the Strapi CLI.
|
||||
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
$ strapi generate:something
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [License](LICENSE)
|
||||
|
||||
## Links
|
||||
|
||||
- [Strapi website](https://strapi.io/)
|
||||
- [Strapi community on Slack](https://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
@ -1,188 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
const util = require('util');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
// Local dependencies.
|
||||
const pathRegexp = require('./util').pathRegexp;
|
||||
const generateTarget = require('./target');
|
||||
|
||||
/**
|
||||
* Run a generator given an existing scope
|
||||
*
|
||||
* @param {Object} generator
|
||||
* @param {Object} scope
|
||||
* @param {Switchback} cb
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
function generate(generator, scope, cb) {
|
||||
const sb = reportback.extend(cb, {
|
||||
error: cb.error,
|
||||
invalid: cb.invalid,
|
||||
alreadyExists: 'error',
|
||||
});
|
||||
|
||||
// Resolve string shorthand for generator defs
|
||||
// to `{ generator: 'originalDef' }`.
|
||||
if (typeof generator === 'string') {
|
||||
const generatorName = generator;
|
||||
generator = {
|
||||
generator: generatorName,
|
||||
};
|
||||
}
|
||||
|
||||
// Run the generator's `before()` method proceeding.
|
||||
generator.before(
|
||||
scope,
|
||||
reportback.extend({
|
||||
error: sb.error,
|
||||
invalid: sb.invalid,
|
||||
success: () => {
|
||||
// Process all of the generator's targets concurrently.
|
||||
async.each(
|
||||
Object.keys(generator.targets),
|
||||
(keyPath, asyncEachCb) => {
|
||||
const asyncEachSb = reportback.extend(asyncEachCb);
|
||||
|
||||
// Create a new scope object for this target,
|
||||
// with references to the important bits of the original
|
||||
// (depth will be passed-by-value, but that's what we want).
|
||||
// Then generate the target, passing along a reference to
|
||||
// the base `generate` method to allow for recursive generators.
|
||||
const target = generator.targets[keyPath];
|
||||
if (!target) {
|
||||
return asyncEachSb(
|
||||
new Error(
|
||||
'Error: Invalid target: {"' + keyPath + '": ' + util.inspect(target) + '}'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Input tolerance.
|
||||
if (keyPath === '') {
|
||||
keyPath = '.';
|
||||
}
|
||||
|
||||
// Interpret `keyPath` using Express's parameterized route conventions,
|
||||
// first parsing params, then replacing them with their proper values from scope.
|
||||
const params = [];
|
||||
pathRegexp(keyPath, params);
|
||||
let err;
|
||||
const parsedKeyPath = _.reduce(
|
||||
params,
|
||||
(memoKeyPath, param) => {
|
||||
if (err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const paramMatchExpr = ':' + param.name;
|
||||
let actualParamValue = scope[param.name];
|
||||
if (!actualParamValue) {
|
||||
err = new Error(
|
||||
'generator error:\n' +
|
||||
'A scope variable (`' +
|
||||
param.name +
|
||||
'`) was referenced in target: `' +
|
||||
memoKeyPath +
|
||||
'`,\n' +
|
||||
'but `' +
|
||||
param.name +
|
||||
"` does not exist in the generator's scope."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
actualParamValue = String(actualParamValue);
|
||||
|
||||
return memoKeyPath.replace(paramMatchExpr, actualParamValue);
|
||||
} catch (e) {
|
||||
err = new Error('Error: Could not parse target key ' + memoKeyPath);
|
||||
err.message = e;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
keyPath
|
||||
);
|
||||
if (!parsedKeyPath) {
|
||||
return asyncEachSb(err);
|
||||
}
|
||||
|
||||
// Create path from `rootPath` to `keyPath` to use as the `rootPath`
|
||||
// for any generators or helpers in this target
|
||||
// (use a copy so that child generators don't mutate the scope).
|
||||
const targetScope = _.merge({}, scope, {
|
||||
rootPath: path.resolve(scope.rootPath, parsedKeyPath),
|
||||
|
||||
// Include reference to original keypath for error reporting.
|
||||
keyPath,
|
||||
});
|
||||
|
||||
// If `target` is an array, run each item.
|
||||
if (_.isArray(target)) {
|
||||
async.eachSeries(
|
||||
target,
|
||||
(targetItem, asyncEachSeriesCb) => {
|
||||
generateTarget(
|
||||
{
|
||||
target: targetItem,
|
||||
parent: generator,
|
||||
scope: _.cloneDeep(targetScope),
|
||||
recursiveGenerate: generate,
|
||||
},
|
||||
asyncEachSeriesCb
|
||||
);
|
||||
},
|
||||
asyncEachSb
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, just run the single target generator/helper.
|
||||
generateTarget(
|
||||
{
|
||||
target,
|
||||
parent: generator,
|
||||
scope: targetScope,
|
||||
recursiveGenerate: generate,
|
||||
},
|
||||
asyncEachSb
|
||||
);
|
||||
},
|
||||
|
||||
err => {
|
||||
// Expose a `error` handler in generators.
|
||||
if (err) {
|
||||
const errorFn =
|
||||
generator.error ||
|
||||
function defaultError(err, scope, _cb) {
|
||||
return _cb(err);
|
||||
};
|
||||
return errorFn(err, scope, sb);
|
||||
}
|
||||
|
||||
// Expose a `after` handler in generators (on success only).
|
||||
const afterFn =
|
||||
generator.after ||
|
||||
function defaultAfter(scope, _cb) {
|
||||
return _cb();
|
||||
};
|
||||
return afterFn(scope, sb);
|
||||
}
|
||||
);
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = generate;
|
||||
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
// Local dependencies.
|
||||
const fileHelper = require('../file');
|
||||
|
||||
/**
|
||||
* Copy file from one place to another
|
||||
*/
|
||||
|
||||
module.exports = function(options, cb) {
|
||||
cb = reportback.extend(cb, {
|
||||
alreadyExists: 'error',
|
||||
invalid: 'error',
|
||||
});
|
||||
|
||||
// Compute the canonical path to copy from
|
||||
// given its relative path from its source generator's
|
||||
// `templates` directory.
|
||||
const absSrcPath = path.resolve(options.templatesDirectory, options.templatePath);
|
||||
|
||||
fs.readFile(absSrcPath, 'utf8', (err, contents) => {
|
||||
if (err) {
|
||||
return cb.error(err);
|
||||
}
|
||||
|
||||
return fileHelper(
|
||||
_.merge(options, {
|
||||
contents,
|
||||
}),
|
||||
cb
|
||||
);
|
||||
});
|
||||
};
|
||||
@ -1,68 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const fs = require('fs-extra');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
/**
|
||||
* Generate a file using the specified string
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
module.exports = function(options, cb) {
|
||||
// Provide default values for switchback.
|
||||
cb = reportback.extend(cb, {
|
||||
alreadyExists: 'error',
|
||||
});
|
||||
|
||||
// Provide defaults and validate required options.
|
||||
_.defaults(options, {
|
||||
force: false,
|
||||
});
|
||||
|
||||
const missingOpts = _.difference(['contents', 'rootPath'], Object.keys(options));
|
||||
|
||||
if (missingOpts.length) {
|
||||
return cb.invalid(missingOpts);
|
||||
}
|
||||
|
||||
// In case we ended up here with a relative path,
|
||||
// resolve it using the process's CWD
|
||||
const rootPath = path.resolve(process.cwd(), options.rootPath);
|
||||
|
||||
// Only override an existing file if `options.force` is true.
|
||||
fs.exists(rootPath, exists => {
|
||||
if (exists && !options.force) {
|
||||
return cb.alreadyExists('Something else already exists at `' + rootPath + '`.');
|
||||
}
|
||||
|
||||
// Don't actually write the file if this is a dry run.
|
||||
if (options.dry) {
|
||||
return cb.success();
|
||||
}
|
||||
|
||||
async.series(
|
||||
[
|
||||
function deleteExistingFileIfNecessary(cb) {
|
||||
if (!exists) {
|
||||
return cb();
|
||||
}
|
||||
return fs.remove(rootPath, cb);
|
||||
},
|
||||
function writeToDisk(cb) {
|
||||
fs.outputFile(rootPath, options.contents, cb);
|
||||
},
|
||||
],
|
||||
cb
|
||||
);
|
||||
});
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
/**
|
||||
* Generate a folder
|
||||
*/
|
||||
/* eslint-disable prefer-template */
|
||||
module.exports = function(options, cb) {
|
||||
// Provide default values for cb.
|
||||
cb = reportback.extend(cb, {
|
||||
alreadyExists: 'error',
|
||||
invalid: 'error',
|
||||
});
|
||||
|
||||
// Provide defaults and validate required options.
|
||||
_.defaults(options, {
|
||||
force: false,
|
||||
gitkeep: false,
|
||||
});
|
||||
|
||||
const missingOpts = _.difference(['rootPath'], Object.keys(options));
|
||||
|
||||
if (missingOpts.length) {
|
||||
return cb.invalid(missingOpts);
|
||||
}
|
||||
|
||||
const rootPath = path.resolve(process.cwd(), options.rootPath);
|
||||
|
||||
// Only override an existing folder if `options.force` is true.
|
||||
fs.lstat(rootPath, err => {
|
||||
const exists = !(err && err.code === 'ENOENT');
|
||||
if (exists && err) {
|
||||
return cb.error(err);
|
||||
}
|
||||
|
||||
if (exists && !options.force) {
|
||||
return cb.alreadyExists('Something else already exists at `' + rootPath + '`.');
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
fs.remove(rootPath, err => {
|
||||
if (err) {
|
||||
return cb.error(err);
|
||||
}
|
||||
_afterwards_();
|
||||
});
|
||||
} else {
|
||||
_afterwards_();
|
||||
}
|
||||
|
||||
function _afterwards_() {
|
||||
// Don't actually write the directory if this is a dry run.
|
||||
if (options.dry) {
|
||||
return cb.success();
|
||||
}
|
||||
|
||||
// Create the directory.
|
||||
fs.mkdirs(rootPath, err => {
|
||||
if (err) {
|
||||
return cb.error(err);
|
||||
}
|
||||
return cb.success();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -1,66 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
/**
|
||||
* Generate a JSON file
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
module.exports = function(options, handlers) {
|
||||
// Provide default values for handlers.
|
||||
handlers = reportback.extend(handlers, {
|
||||
alreadyExists: 'error',
|
||||
});
|
||||
|
||||
// Provide defaults and validate required options.
|
||||
_.defaults(options, {
|
||||
force: false,
|
||||
});
|
||||
|
||||
const missingOpts = _.difference(['rootPath', 'data'], Object.keys(options));
|
||||
|
||||
if (missingOpts.length) {
|
||||
return handlers.invalid(missingOpts);
|
||||
}
|
||||
|
||||
const rootPath = path.resolve(process.cwd(), options.rootPath);
|
||||
|
||||
// Only override an existing file if `options.force` is true.
|
||||
fs.exists(rootPath, exists => {
|
||||
if (exists && !options.force) {
|
||||
return handlers.alreadyExists('Something else already exists at `' + rootPath + '`.');
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
fs.remove(rootPath, err => {
|
||||
if (err) {
|
||||
return handlers.error(err);
|
||||
}
|
||||
_afterwards_();
|
||||
});
|
||||
} else {
|
||||
_afterwards_();
|
||||
}
|
||||
|
||||
function _afterwards_() {
|
||||
fs.outputJSON(rootPath, options.data, { spaces: 2 }, err => {
|
||||
if (err) {
|
||||
return handlers.error(err);
|
||||
} else {
|
||||
handlers.success();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -1,72 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const reportback = require('reportback')();
|
||||
|
||||
// Local dependencies.
|
||||
const fileHelper = require('../file');
|
||||
|
||||
/**
|
||||
* Read a dynamic template, compile it using scope.
|
||||
* Then use `file` helper to write it to its destination.
|
||||
*/
|
||||
|
||||
module.exports = function(options, cb) {
|
||||
cb = reportback.extend(cb, {
|
||||
noTemplate: 'error',
|
||||
alreadyExists: 'error',
|
||||
});
|
||||
|
||||
// Compute the canonical path to a template
|
||||
// given its relative path from its source generator's
|
||||
// `templates` directory.
|
||||
if (_.isFunction(options.templatesDirectory)) {
|
||||
options.templatesDirectory = options.templatesDirectory(options);
|
||||
}
|
||||
|
||||
const absTemplatePath = path.resolve(options.templatesDirectory, options.templatePath);
|
||||
|
||||
fs.readFile(absTemplatePath, 'utf8', (err, contents) => {
|
||||
if (err) {
|
||||
err = err instanceof Error ? err : new Error(err);
|
||||
err.message = `Template error: ${err.message}`;
|
||||
err.path = absTemplatePath;
|
||||
if (err.code === 'ENOENT') {
|
||||
return cb.noTemplate(err);
|
||||
} else {
|
||||
return cb(err);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const compiled = _.template(contents, {
|
||||
interpolate: /<%=([\s\S]+?)%>/g,
|
||||
});
|
||||
contents = compiled(options);
|
||||
|
||||
// With Lodash templates, HTML entities are escaped by default.
|
||||
// Default assumption is we don't want that, so we'll reverse it.
|
||||
if (!options.escapeHTMLEntities) {
|
||||
contents = _.unescape(contents);
|
||||
}
|
||||
} catch (e) {
|
||||
return cb(e);
|
||||
}
|
||||
|
||||
return fileHelper(
|
||||
_.merge(options, {
|
||||
contents,
|
||||
}),
|
||||
cb
|
||||
);
|
||||
});
|
||||
};
|
||||
@ -1,67 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Public node modules.
|
||||
const reportback = require('reportback')();
|
||||
|
||||
// Logger.
|
||||
const logger = require('@strapi/utils').logger;
|
||||
|
||||
// Local dependencies.
|
||||
const generate = require('./generate');
|
||||
const generateTarget = require('./target');
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
/**
|
||||
* Generate module(s)
|
||||
*
|
||||
* @param {Object} scope
|
||||
* @param {Function} cb
|
||||
*
|
||||
* @return {[Type]}
|
||||
*/
|
||||
|
||||
module.exports = (scope, cb) => {
|
||||
cb = cb || {};
|
||||
cb = reportback.extend(cb, {
|
||||
error: cb.error,
|
||||
success: () => {},
|
||||
notStrapiApp: () => {},
|
||||
alreadyExists: () => {
|
||||
return cb.error();
|
||||
},
|
||||
});
|
||||
|
||||
// Use configured module name for this `generatorType` if applicable.
|
||||
const module = '@strapi/generate-' + scope.generatorType;
|
||||
let generator;
|
||||
|
||||
function throwIfModuleNotFoundError(error, module) {
|
||||
const isModuleNotFoundError =
|
||||
error && error.code === 'MODULE_NOT_FOUND' && error.message.match(new RegExp(module));
|
||||
if (!isModuleNotFoundError) {
|
||||
logger.error('Invalid `' + scope.generatorType + '` generator.');
|
||||
throw error;
|
||||
} else {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to require the module or throw if error.
|
||||
try {
|
||||
generator = require(module);
|
||||
} catch (error) {
|
||||
throwIfModuleNotFoundError(error, module);
|
||||
}
|
||||
|
||||
if (!generator) {
|
||||
return logger.error('No generator called `' + scope.generatorType + '` found.');
|
||||
}
|
||||
|
||||
generate(generator, scope, cb);
|
||||
};
|
||||
|
||||
module.exports.generateTarget = generateTarget;
|
||||
@ -1,318 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
const util = require('util');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const report = require('reportback')();
|
||||
|
||||
// Local dependencies.
|
||||
const folderHelper = require('./helpers/folder');
|
||||
const templateHelper = require('./helpers/template');
|
||||
const jsonFileHelper = require('./helpers/jsonfile');
|
||||
const copyHelper = require('./helpers/copy');
|
||||
|
||||
/**
|
||||
* generateTarget()
|
||||
*
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
function generateTarget(options, cb) {
|
||||
const sb = report.extend(cb);
|
||||
|
||||
// Options.
|
||||
let target = options.target;
|
||||
let scope = options.scope;
|
||||
const parentGenerator = options.parent;
|
||||
const recursiveGenerate = options.recursiveGenerate;
|
||||
|
||||
const maxResolves = 5;
|
||||
let _resolves = 0;
|
||||
|
||||
async.until(
|
||||
() => {
|
||||
return isValidTarget(target) || ++_resolves > maxResolves;
|
||||
},
|
||||
asyncCb => {
|
||||
parseTarget(target, scope, (err, resolvedTarget) => {
|
||||
if (err) {
|
||||
return asyncCb(err);
|
||||
}
|
||||
target = resolvedTarget;
|
||||
return asyncCb();
|
||||
});
|
||||
},
|
||||
err => {
|
||||
if (err) {
|
||||
return sb(err);
|
||||
}
|
||||
if (!isValidTarget(target)) {
|
||||
return sb(
|
||||
new Error(
|
||||
'Generator Error :: Could not resolve target `' +
|
||||
scope.rootPath +
|
||||
'` (probably a recursive loop)'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Pass down parent Generator's template directory abs path.
|
||||
scope.templatesDirectory = parentGenerator.templatesDirectory;
|
||||
|
||||
if (target.copy) {
|
||||
scope = mergeSubtargetScope(
|
||||
scope,
|
||||
typeof target.copy === 'string'
|
||||
? {
|
||||
templatePath: target.copy,
|
||||
}
|
||||
: target.copy
|
||||
);
|
||||
return copyHelper(scope, sb);
|
||||
}
|
||||
|
||||
if (target.folder) {
|
||||
scope = mergeSubtargetScope(scope, target.folder);
|
||||
return folderHelper(scope, sb);
|
||||
}
|
||||
|
||||
if (target.template) {
|
||||
scope = mergeSubtargetScope(
|
||||
scope,
|
||||
typeof target.template === 'string'
|
||||
? {
|
||||
templatePath: target.template,
|
||||
}
|
||||
: target.template
|
||||
);
|
||||
|
||||
return templateHelper(scope, sb);
|
||||
}
|
||||
|
||||
if (target.jsonfile) {
|
||||
if (typeof target.jsonfile === 'object') {
|
||||
scope = mergeSubtargetScope(scope, target.jsonfile);
|
||||
} else if (typeof target.jsonfile === 'function') {
|
||||
scope = _.merge(scope, {
|
||||
data: target.jsonfile(scope),
|
||||
});
|
||||
}
|
||||
return jsonFileHelper(scope, sb);
|
||||
}
|
||||
|
||||
// If we made it here, this must be a recursive generator.
|
||||
// Now that the generator definition has been resolved,
|
||||
// call this method recursively on it, passing along our
|
||||
// callback.
|
||||
if (++scope._depth > scope.maxHops) {
|
||||
return sb(
|
||||
new Error(
|
||||
'`maxHops` (' +
|
||||
scope.maxHops +
|
||||
') exceeded! There is probably a recursive loop in one of your generators.'
|
||||
)
|
||||
);
|
||||
}
|
||||
return recursiveGenerate(target, scope, sb);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = generateTarget;
|
||||
|
||||
/**
|
||||
* @param {[Type]} scope Description
|
||||
* @param {[Type]} subtarget Description
|
||||
* @return {[Type]} Description
|
||||
*/
|
||||
|
||||
function mergeSubtargetScope(scope, subtarget) {
|
||||
return _.merge(scope, _.isObject(subtarget) ? subtarget : {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Known helpers
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
|
||||
const knownHelpers = ['folder', 'template', 'jsonfile', 'file', 'copy'];
|
||||
|
||||
function targetIsHelper(target) {
|
||||
return _.some(target, (subTarget, key) => {
|
||||
return _.includes(knownHelpers, key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String|Object} target Description
|
||||
* @param {Object} scope Description
|
||||
* @param {Function} cb Description
|
||||
* @return {[type]} Description
|
||||
*/
|
||||
|
||||
function parseTarget(target, scope, cb) {
|
||||
if (typeof target === 'string') {
|
||||
target = {
|
||||
generator: target,
|
||||
};
|
||||
}
|
||||
|
||||
// Interpret generator definition.
|
||||
if (targetIsHelper(target)) {
|
||||
return cb(null, target);
|
||||
}
|
||||
|
||||
if (target.generator) {
|
||||
// Normalize the subgenerator reference.
|
||||
let subGeneratorRef;
|
||||
if (typeof target.generator === 'string') {
|
||||
subGeneratorRef = {
|
||||
module: target.generator,
|
||||
};
|
||||
} else if (typeof target.generator === 'object') {
|
||||
subGeneratorRef = target.generator;
|
||||
}
|
||||
|
||||
if (!subGeneratorRef) {
|
||||
return cb(
|
||||
new Error(
|
||||
'Generator Error :: Invalid subgenerator referenced for target `' + scope.rootPath + '`'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Now normalize the sub-generator.
|
||||
let subGenerator;
|
||||
|
||||
// No `module` means we'll treat this subgenerator as an inline generator definition.
|
||||
if (!subGeneratorRef.module) {
|
||||
subGenerator = subGeneratorRef;
|
||||
if (subGenerator) {
|
||||
return cb(null, subGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we'll attempt to load this subgenerator.
|
||||
if (typeof subGeneratorRef.module === 'string') {
|
||||
// Lookup the generator by name if a `module` was specified
|
||||
// This allows the module for a given generator to be
|
||||
// overridden.
|
||||
const configuredReference = scope.modules && scope.modules[subGeneratorRef.module];
|
||||
|
||||
// Refers to a configured module.
|
||||
// If this generator type is explicitly set to `false`,
|
||||
// disable the generator.
|
||||
if (configuredReference) {
|
||||
return cb(null, configuredReference);
|
||||
} else if (configuredReference === false) {
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
// If `configuredReference` is undefined, continue on
|
||||
// and try to require the module.
|
||||
}
|
||||
|
||||
// At this point, `subGeneratorRef.module` should be a string,
|
||||
// and the best guess at the generator module we're going
|
||||
// to get.
|
||||
const module = subGeneratorRef.module;
|
||||
let requireError;
|
||||
|
||||
// Try requiring it directly as a path.
|
||||
try {
|
||||
subGenerator = require(module);
|
||||
} catch (e0) {
|
||||
requireError = e0;
|
||||
}
|
||||
|
||||
// Try the scope's `rootPath`.
|
||||
if (!subGenerator) {
|
||||
try {
|
||||
const asDependencyInRootPath = path.resolve(scope.rootPath, 'node_modules', module);
|
||||
subGenerator = require(asDependencyInRootPath);
|
||||
} catch (e1) {
|
||||
requireError = e1;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the current working directory.
|
||||
if (!subGenerator) {
|
||||
try {
|
||||
subGenerator = require(path.resolve(process.cwd(), 'node_modules', module));
|
||||
} catch (e1) {
|
||||
requireError = e1;
|
||||
}
|
||||
}
|
||||
|
||||
// If we couldn't find a generator using the configured module,
|
||||
// try requiring `@strapi/generate-<module>` to get the core generator.
|
||||
if (!subGenerator && !module.match(/^@strapi\/generate-/)) {
|
||||
try {
|
||||
if (process.mainModule.filename.indexOf('yarn') !== -1) {
|
||||
subGenerator = require(path.resolve(
|
||||
process.mainModule.paths[2],
|
||||
'@strapi/generate-' + module
|
||||
));
|
||||
} else {
|
||||
subGenerator = require(path.resolve(
|
||||
process.mainModule.paths[1],
|
||||
'@strapi/generate-' + module
|
||||
));
|
||||
}
|
||||
} catch (e1) {
|
||||
requireError = e1;
|
||||
}
|
||||
}
|
||||
|
||||
// If we were able to find it, send it back!
|
||||
if (subGenerator) {
|
||||
return cb(null, subGenerator);
|
||||
}
|
||||
|
||||
// But if we still can't find it, give up.
|
||||
return cb(
|
||||
new Error(
|
||||
'Error: Failed to load `' +
|
||||
subGeneratorRef.module +
|
||||
'`...' +
|
||||
(requireError ? ' (' + requireError + ')' : '') +
|
||||
''
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return cb(
|
||||
new Error(
|
||||
'Unrecognized generator syntax in `targets["' +
|
||||
scope.keyPath +
|
||||
'"]` ::\n' +
|
||||
util.inspect(target)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {[Type]} target Description
|
||||
* @return {Boolean} Description
|
||||
*/
|
||||
|
||||
function isValidTarget(target) {
|
||||
let ok = typeof target === 'object';
|
||||
|
||||
// Is using a helper.
|
||||
// Or is another generator def.
|
||||
ok = ok && (targetIsHelper(target) || _.has(target, 'targets'));
|
||||
|
||||
return ok;
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* From Express core: (MIT License)
|
||||
*
|
||||
* Normalize the given path string,
|
||||
* returning a regular expression.
|
||||
*
|
||||
* An empty array should be passed,
|
||||
* which will contain the placeholder
|
||||
* key names. For example "/user/:id" will
|
||||
* then contain ["id"].
|
||||
*
|
||||
* @param {String|RegExp|Array} path
|
||||
* @param {Array} keys
|
||||
* @param {Boolean} sensitive
|
||||
* @param {Boolean} strict
|
||||
* @return {RegExp}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
/* eslint-disable no-useless-escape */
|
||||
const pathRegexp = (path, keys, sensitive, strict) => {
|
||||
if (toString.call(path) === '[object RegExp]') {
|
||||
return path;
|
||||
}
|
||||
if (Array.isArray(path)) {
|
||||
path = '(' + path.join('|') + ')';
|
||||
}
|
||||
path = path
|
||||
.concat(strict ? '' : '/?')
|
||||
.replace(/\/\(/g, '(?:/')
|
||||
.replace(
|
||||
/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g,
|
||||
(_, slash, format, key, capture, optional, star) => {
|
||||
keys.push({
|
||||
name: key,
|
||||
optional: !!optional,
|
||||
});
|
||||
slash = slash || '';
|
||||
return (
|
||||
'' +
|
||||
(optional ? '' : slash) +
|
||||
'(?:' +
|
||||
(optional ? slash : '') +
|
||||
(format || '') +
|
||||
(capture || (format && '([^/.]+?)') || '([^/]+?)') +
|
||||
')' +
|
||||
(optional || '') +
|
||||
(star ? '(/*)?' : '')
|
||||
);
|
||||
}
|
||||
)
|
||||
.replace(/([\/.])/g, '\\$1')
|
||||
.replace(/\*/g, '(.*)');
|
||||
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
pathRegexp,
|
||||
};
|
||||
@ -1,50 +0,0 @@
|
||||
{
|
||||
"name": "@strapi/generate",
|
||||
"version": "3.6.8",
|
||||
"description": "Master of ceremonies for the Strapi generators.",
|
||||
"homepage": "https://strapi.io",
|
||||
"keywords": [
|
||||
"generate",
|
||||
"generator",
|
||||
"strapi"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^2.6.2",
|
||||
"fs-extra": "^9.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"reportback": "^2.0.2",
|
||||
"@strapi/utils": "3.6.8"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x.x <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"gitHead": "231263a3535658bab1e9492c6aaaed8692d62a53"
|
||||
}
|
||||
@ -67,7 +67,6 @@ $RECYCLE.BIN/
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
@ -76,6 +75,8 @@ $RECYCLE.BIN/
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.gitattributes
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
@ -89,16 +90,14 @@ lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
testApp
|
||||
coverage
|
||||
@ -19,4 +19,4 @@ The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
18
packages/generators/generators/README.md
Normal file
18
packages/generators/generators/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# @strapi/generators
|
||||
|
||||
This package contains strapi code generators available through the CLI or programmatically.
|
||||
|
||||
## API Reference
|
||||
|
||||
### `runCLI()`
|
||||
|
||||
Start the generator CLI.
|
||||
|
||||
### `generate(generatorName, options, plopOptions)`
|
||||
|
||||
Execute a generator without interactive mode.
|
||||
|
||||
- `generatorName` - one of `api`, `controller`, `service`, `model`, `plugin`, `policy`.
|
||||
- `options` - options are specific to each generator
|
||||
- `plopOtions`
|
||||
- `dir`: base directory that plop will use as base directory for its actions
|
||||
@ -0,0 +1,26 @@
|
||||
/**
|
||||
*
|
||||
* Initializer
|
||||
*
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
const Initializer = ({ setPlugin }) => {
|
||||
const ref = useRef();
|
||||
ref.current = setPlugin;
|
||||
|
||||
useEffect(() => {
|
||||
ref.current(pluginId);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Initializer.propTypes = {
|
||||
setPlugin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Initializer;
|
||||
@ -2,6 +2,7 @@ import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
||||
import pluginPkg from '../../package.json';
|
||||
import pluginId from './pluginId';
|
||||
import Initializer from './components/Initializer';
|
||||
|
||||
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
||||
const icon = pluginPkg.strapi.icon;
|
||||
const name = pluginPkg.strapi.name;
|
||||
@ -38,6 +39,7 @@ export default {
|
||||
name,
|
||||
});
|
||||
},
|
||||
|
||||
bootstrap(app) {},
|
||||
async registerTrads({ locales }) {
|
||||
const importedTrads = await Promise.all(
|
||||
@ -0,0 +1,25 @@
|
||||
/**
|
||||
*
|
||||
* This component is the skeleton around the actual pages, and should only
|
||||
* contain code that should be seen on all pages. (e.g. navigation bar)
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { NotFound } from '@strapi/helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
import HomePage from '../HomePage';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<div>
|
||||
<Switch>
|
||||
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
*
|
||||
* HomePage
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
// import PropTypes from 'prop-types';
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
const HomePage = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{pluginId}'s HomePage</h1>
|
||||
<p>Happy coding</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(HomePage);
|
||||
37
packages/generators/generators/lib/index.js
Normal file
37
packages/generators/generators/lib/index.js
Normal file
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
const { join } = require('path');
|
||||
const { Plop, run } = require('plop');
|
||||
const nodePlop = require('node-plop');
|
||||
|
||||
/**
|
||||
* Starts the Plop CLI programmatically
|
||||
*/
|
||||
const runCLI = () => {
|
||||
Plop.launch({ configPath: join(__dirname, 'plopfile.js') }, env =>
|
||||
run({ ...env, dest: process.cwd() }, undefined, true)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs a generator programmatically without prompts
|
||||
* @param {string} generatorName
|
||||
* @param {Object} options generator options replacing the prompts answers
|
||||
* @param {Object} plopOptions
|
||||
* @param {string} plopOptions.dir base path for plop to generate the files from
|
||||
*/
|
||||
const generate = async (generatorName, options, { dir = process.cwd() } = {}) => {
|
||||
const plop = nodePlop(join(__dirname, 'plopfile.js'), { destBasePath: dir });
|
||||
|
||||
const generator = plop.getGenerator(generatorName);
|
||||
await generator.runActions(options, {
|
||||
onSuccess: () => {},
|
||||
onFailure: () => {},
|
||||
onComment: () => {},
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
generate,
|
||||
runCLI,
|
||||
};
|
||||
24
packages/generators/generators/lib/plopfile.js
Normal file
24
packages/generators/generators/lib/plopfile.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const pluralize = require('pluralize');
|
||||
|
||||
const generateApi = require('./plops/api');
|
||||
const generateController = require('./plops/controller');
|
||||
const generateModel = require('./plops/model');
|
||||
const generatePlugin = require('./plops/plugin');
|
||||
const generatePolicy = require('./plops/policy');
|
||||
const generateService = require('./plops/service');
|
||||
|
||||
module.exports = plop => {
|
||||
// Plop config
|
||||
plop.setWelcomeMessage('Strapi Generators');
|
||||
plop.addHelper('pluralize', text => pluralize(text));
|
||||
|
||||
// Generators
|
||||
generateApi(plop);
|
||||
generateController(plop);
|
||||
generateModel(plop);
|
||||
generatePlugin(plop);
|
||||
generatePolicy(plop);
|
||||
generateService(plop);
|
||||
};
|
||||
112
packages/generators/generators/lib/plops/api.js
Normal file
112
packages/generators/generators/lib/plops/api.js
Normal file
@ -0,0 +1,112 @@
|
||||
'use strict';
|
||||
|
||||
const { join } = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const validateInput = require('./utils/validate-input');
|
||||
|
||||
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',
|
||||
choices: async () => {
|
||||
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: 'kind',
|
||||
message: 'Please choose the model type',
|
||||
default: 'collectionType',
|
||||
choices: [
|
||||
{ name: 'Collection Type', value: 'collectionType' },
|
||||
{ name: 'Singe Type', value: 'singleType' },
|
||||
],
|
||||
},
|
||||
{
|
||||
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: `${filePath}/controllers/{{id}}.js`,
|
||||
templateFile: 'templates/controller.js.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/models/{{id}}.js`,
|
||||
templateFile: 'templates/model.js.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/models/{{id}}.settings.json`,
|
||||
templateFile: 'templates/model.settings.json.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/services/{{id}}.js`,
|
||||
templateFile: 'templates/service.js.hbs',
|
||||
},
|
||||
];
|
||||
|
||||
if (answers.isPluginApi) {
|
||||
return baseActions;
|
||||
} else {
|
||||
const routeType =
|
||||
answers.kind === 'singleType'
|
||||
? 'single-type-routes.json.hbs'
|
||||
: 'collection-type-routes.json.hbs';
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/config/routes.json`,
|
||||
templateFile: `templates/${routeType}`,
|
||||
},
|
||||
...baseActions,
|
||||
];
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
32
packages/generators/generators/lib/plops/controller.js
Normal file
32
packages/generators/generators/lib/plops/controller.js
Normal file
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const getDestinationPrompts = require('./utils/get-destination-prompts');
|
||||
const getFilePath = require('./utils/get-file-path');
|
||||
const validateInput = require('./utils/validate-input');
|
||||
|
||||
module.exports = plop => {
|
||||
// Controller generator
|
||||
plop.setGenerator('controller', {
|
||||
description: 'Generate a controller for an API',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'id',
|
||||
message: 'Controller name',
|
||||
validate: input => validateInput(input),
|
||||
},
|
||||
...getDestinationPrompts('controller', plop.getDestBasePath()),
|
||||
],
|
||||
actions: answers => {
|
||||
const filePath = getFilePath(answers.destination);
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/controllers/{{id}}.js`,
|
||||
templateFile: 'templates/controller.js.hbs',
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
};
|
||||
177
packages/generators/generators/lib/plops/model.js
Normal file
177
packages/generators/generators/lib/plops/model.js
Normal file
@ -0,0 +1,177 @@
|
||||
'use strict';
|
||||
|
||||
const getDestinationPrompts = require('./utils/get-destination-prompts');
|
||||
const getFilePath = require('./utils/get-file-path');
|
||||
const validateInput = require('./utils/validate-input');
|
||||
|
||||
const DEFAULT_TYPES = [
|
||||
// advanced types
|
||||
'media',
|
||||
|
||||
// scalar types
|
||||
'string',
|
||||
'text',
|
||||
'richtext',
|
||||
'json',
|
||||
'enumeration',
|
||||
'password',
|
||||
'email',
|
||||
'integer',
|
||||
'biginteger',
|
||||
'float',
|
||||
'decimal',
|
||||
'date',
|
||||
'time',
|
||||
'datetime',
|
||||
'timestamp',
|
||||
'boolean',
|
||||
];
|
||||
|
||||
const promptConfigQuestions = (plop, inquirer) => {
|
||||
return inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'id',
|
||||
message: 'Model name',
|
||||
validate: input => validateInput(input),
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
name: 'kind',
|
||||
message: 'Please choose the model type',
|
||||
choices: [
|
||||
{ name: 'Collection Type', value: 'collectionType' },
|
||||
{ name: 'Singe Type', value: 'singleType' },
|
||||
],
|
||||
validate: input => validateInput(input),
|
||||
},
|
||||
...getDestinationPrompts('model', plop.getDestBasePath()),
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'useDraftAndPublish',
|
||||
message: 'Use draft and publish?',
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'addAttributes',
|
||||
message: 'Do you want to add attributes?',
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const promptAttributeQuestions = inquirer => {
|
||||
return inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'attributeName',
|
||||
message: 'Name of attribute',
|
||||
validate: input => validateInput(input),
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
name: 'attributeType',
|
||||
message: 'What type of attribute',
|
||||
pageSize: DEFAULT_TYPES.length,
|
||||
choices: DEFAULT_TYPES.map(type => {
|
||||
return { name: type, value: type };
|
||||
}),
|
||||
},
|
||||
{
|
||||
when: answers => answers.attributeType === 'enumeration',
|
||||
type: 'input',
|
||||
name: 'enum',
|
||||
message: 'Add values separated by a comma',
|
||||
},
|
||||
{
|
||||
when: answers => answers.attributeType === 'media',
|
||||
type: 'list',
|
||||
name: 'multiple',
|
||||
message: 'Choose media type',
|
||||
choices: [
|
||||
{ name: 'Multiple', value: true },
|
||||
{ name: 'Single', value: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'addAttributes',
|
||||
message: 'Do you want to add another attribute?',
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
module.exports = plop => {
|
||||
// Model generator
|
||||
plop.setGenerator('model', {
|
||||
description: 'Generate a model for an API',
|
||||
prompts: async 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,
|
||||
};
|
||||
},
|
||||
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}/models/{{id}}.js`,
|
||||
templateFile: 'templates/model.js.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/models/{{id}}.settings.json`,
|
||||
templateFile: 'templates/model.settings.json.hbs',
|
||||
},
|
||||
{
|
||||
type: 'modify',
|
||||
path: `${filePath}/models/{{id}}.settings.json`,
|
||||
transform: template => {
|
||||
const parsedTemplate = JSON.parse(template);
|
||||
parsedTemplate.attributes = attributes;
|
||||
return JSON.stringify(parsedTemplate, null, 2);
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
};
|
||||
50
packages/generators/generators/lib/plops/plugin.js
Normal file
50
packages/generators/generators/lib/plops/plugin.js
Normal file
@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = plop => {
|
||||
// Plugin generator
|
||||
plop.setGenerator('plugin', {
|
||||
description: 'Generate a basic plugin',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'id',
|
||||
message: 'Plugin name',
|
||||
},
|
||||
],
|
||||
actions: () => {
|
||||
return [
|
||||
{
|
||||
type: 'addMany',
|
||||
destination: 'plugins/{{id}}/admin',
|
||||
base: 'files/plugin/admin',
|
||||
templateFiles: 'files/plugin/admin/**',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: 'plugins/{{id}}/services/{{id}}.js',
|
||||
templateFile: 'templates/service.js.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: 'plugins/{{id}}/controllers/{{id}}.js',
|
||||
templateFile: 'templates/controller.js.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: 'plugins/{{id}}/config/routes.json',
|
||||
templateFile: 'templates/plugin-routes.json.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: 'plugins/{{id}}/README.md',
|
||||
templateFile: 'templates/README.md.hbs',
|
||||
},
|
||||
{
|
||||
type: 'add',
|
||||
path: 'plugins/{{id}}/package.json',
|
||||
templateFile: 'templates/plugin-package.json.hbs',
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
};
|
||||
36
packages/generators/generators/lib/plops/policy.js
Normal file
36
packages/generators/generators/lib/plops/policy.js
Normal file
@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const getDestinationPrompts = require('./utils/get-destination-prompts');
|
||||
|
||||
module.exports = plop => {
|
||||
// Policy generator
|
||||
plop.setGenerator('policy', {
|
||||
description: 'Generate a policy for an API',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'id',
|
||||
message: 'Policy name',
|
||||
},
|
||||
...getDestinationPrompts('policy', plop.getDestBasePath()),
|
||||
],
|
||||
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: `${filePath}/config/policies/{{id}}.js`,
|
||||
templateFile: 'templates/policy.js.hbs',
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
};
|
||||
29
packages/generators/generators/lib/plops/service.js
Normal file
29
packages/generators/generators/lib/plops/service.js
Normal file
@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const getDestinationPrompts = require('./utils/get-destination-prompts');
|
||||
const getFilePath = require('./utils/get-file-path');
|
||||
|
||||
module.exports = plop => {
|
||||
// Service generator
|
||||
plop.setGenerator('service', {
|
||||
description: 'Generate a service for an API',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'id',
|
||||
message: 'Service name',
|
||||
},
|
||||
...getDestinationPrompts('service', plop.getDestBasePath()),
|
||||
],
|
||||
actions: answers => {
|
||||
const filePath = getFilePath(answers.destination);
|
||||
return [
|
||||
{
|
||||
type: 'add',
|
||||
path: `${filePath}/services/{{id}}.js`,
|
||||
templateFile: 'templates/service.js.hbs',
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
const { join } = require('path');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
module.exports = (action, basePath) => {
|
||||
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 an existing API`, value: 'api' },
|
||||
{ name: `Add ${action} to an existing plugin`, value: 'plugin' },
|
||||
],
|
||||
},
|
||||
{
|
||||
when: answers => answers.destination === 'api',
|
||||
type: 'list',
|
||||
message: 'Which API is this for?',
|
||||
name: 'api',
|
||||
choices: async () => {
|
||||
const apiPath = join(basePath, 'api');
|
||||
const exists = await fs.pathExists(apiPath);
|
||||
|
||||
if (!exists) {
|
||||
throw Error('Couldn\'t find an "api" directory');
|
||||
}
|
||||
|
||||
const apiDir = await fs.readdir(apiPath, { withFileTypes: true });
|
||||
const apiDirContent = apiDir.filter(fd => fd.isDirectory());
|
||||
|
||||
if (apiDirContent.length === 0) {
|
||||
throw Error('The "api" directory is empty');
|
||||
}
|
||||
|
||||
return apiDirContent;
|
||||
},
|
||||
},
|
||||
{
|
||||
when: answers => answers.destination === 'plugin',
|
||||
type: 'list',
|
||||
message: 'Which plugin is this for?',
|
||||
name: 'plugin',
|
||||
choices: async () => {
|
||||
const pluginsPath = join(basePath, 'plugins');
|
||||
const exists = await fs.pathExists(pluginsPath);
|
||||
|
||||
if (!exists) {
|
||||
throw Error('Couldn\'t find a "plugins" directory');
|
||||
}
|
||||
|
||||
const pluginsDir = await fs.readdir(pluginsPath);
|
||||
const pluginsDirContent = pluginsDir.filter(api =>
|
||||
fs.lstatSync(join(pluginsPath, api)).isDirectory()
|
||||
);
|
||||
|
||||
if (pluginsDirContent.length === 0) {
|
||||
throw Error('The "plugins" directory is empty');
|
||||
}
|
||||
|
||||
return pluginsDirContent;
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = destination => {
|
||||
if (destination === 'api') {
|
||||
return `api/{{api}}`;
|
||||
}
|
||||
|
||||
if (destination === 'plugin') {
|
||||
return `plugins/{{plugin}}`;
|
||||
}
|
||||
|
||||
return `api/{{id}}`;
|
||||
};
|
||||
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = input => {
|
||||
const regex = /^[A-Za-z-]+$/g;
|
||||
|
||||
if (!input) {
|
||||
return 'You must provide an input';
|
||||
}
|
||||
|
||||
return regex.test(input) || 'Please use only letters and no spaces';
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
# Strapi plugin {{id}}
|
||||
|
||||
A quick description of {{id}}.
|
||||
@ -0,0 +1,44 @@
|
||||
{
|
||||
"routes": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{{pluralize id}}",
|
||||
"handler": "{{id}}.find",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{{pluralize id}}/:id",
|
||||
"handler": "{{id}}.findOne",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/{{pluralize id}}",
|
||||
"handler": "{{id}}.create",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/{{pluralize id}}/:id",
|
||||
"handler": "{{id}}.update",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/{{pluralize id}}/:id",
|
||||
"handler": "{{id}}.delete",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* A set of functions called "actions" for `<%= name %>`
|
||||
* A set of functions called "actions" for `{{id}}`
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
@ -0,0 +1,13 @@
|
||||
|
||||
{
|
||||
"kind": "{{kind}}",
|
||||
"collectionName": "{{id}}",
|
||||
"info": {
|
||||
"name": "{{id}}"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": {{useDraftAndPublish}},
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "strapi-plugin-{{id}}",
|
||||
"version": "0.0.0",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "{{id}}",
|
||||
"icon": "plug",
|
||||
"description": "Description of {{id}} plugin."
|
||||
},
|
||||
"dependencies": {},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
"email": "",
|
||||
"url": ""
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "A Strapi developer",
|
||||
"email": "",
|
||||
"url": ""
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12.x. <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
{
|
||||
"routes": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"handler": "{{id}}.index",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* `<%= id %>` policy.
|
||||
* `{{id}}` policy.
|
||||
*/
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
// Add your own logic here.
|
||||
console.log('In <%= id %> policy.');
|
||||
console.log('In {{id}} policy.');
|
||||
|
||||
await next();
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* {{id}} service.
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"routes": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{{id}}",
|
||||
"handler": "{{id}}.find",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/{{id}}",
|
||||
"handler": "{{id}}.update",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/{{id}}/",
|
||||
"handler": "{{id}}.delete",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,28 +1,23 @@
|
||||
{
|
||||
"name": "@strapi/generate-policy",
|
||||
"name": "@strapi/generators",
|
||||
"version": "3.6.8",
|
||||
"description": "Generate a policy for a Strapi API.",
|
||||
"homepage": "https://strapi.io",
|
||||
"description": "Interactive API generator.",
|
||||
"keywords": [
|
||||
"generate",
|
||||
"generator",
|
||||
"policy",
|
||||
"strapi"
|
||||
"strapi",
|
||||
"generators"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
"homepage": "https://strapi.io",
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21",
|
||||
"@strapi/utils": "3.6.8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
@ -32,17 +27,15 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"fs-extra": "10.0.0",
|
||||
"node-plop": "0.26.2",
|
||||
"plop": "2.7.4",
|
||||
"pluralize": "8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x.x <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"gitHead": "231263a3535658bab1e9492c6aaaed8692d62a53"
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{package.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
104
packages/generators/model/.gitignore
vendored
104
packages/generators/model/.gitignore
vendored
@ -1,104 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
testApp
|
||||
coverage
|
||||
@ -1,109 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
.snyk
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
tests
|
||||
__tests__
|
||||
jest.config.js
|
||||
testApp
|
||||
coverage
|
||||
@ -1,9 +0,0 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.12.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
shelljs:
|
||||
- '*':
|
||||
reason: testing
|
||||
expires: 2019-01-04T14:35:59.679Z
|
||||
patch: {}
|
||||
@ -1,22 +0,0 @@
|
||||
Copyright (c) 2015-present Strapi Solutions SAS
|
||||
|
||||
Portions of the Strapi software are licensed as follows:
|
||||
|
||||
* All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
||||
|
||||
* All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
|
||||
|
||||
MIT Expat License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,31 +0,0 @@
|
||||
# strapi-generate-model
|
||||
|
||||
[](https://www.npmjs.org/package/strapi-generate-model)
|
||||
[](https://www.npmjs.org/package/strapi-generate-model)
|
||||
[](https://david-dm.org/strapi/strapi-generate-model)
|
||||
[](https://travis-ci.org/strapi/strapi-generate-model)
|
||||
[](https://slack.strapi.io)
|
||||
|
||||
This Strapi generator contains the default files for a model.
|
||||
|
||||
This generator can be called with:
|
||||
|
||||
```bash
|
||||
$ strapi generate:model modelName apiName
|
||||
```
|
||||
|
||||
For example if you want to generate a `group` model for the `user` API:
|
||||
|
||||
```bash
|
||||
$ strapi generate:model group user
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [License](LICENSE)
|
||||
|
||||
## Links
|
||||
|
||||
- [Strapi website](https://strapi.io/)
|
||||
- [Strapi community on Slack](https://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
@ -1,139 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const { nameToSlug, nameToCollectionName } = require('@strapi/utils');
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
|
||||
/**
|
||||
* This `before` function is run before generating targets.
|
||||
* Validate, configure defaults, get extra dependencies, etc.
|
||||
*
|
||||
* @param {Object} scope
|
||||
* @param {Function} cb
|
||||
*/
|
||||
|
||||
module.exports = (scope, cb) => {
|
||||
if (!scope.rootPath || !scope.id) {
|
||||
return cb.invalid(
|
||||
'Usage: `$ strapi generate:model modelName --api apiName --plugin pluginName`'
|
||||
);
|
||||
}
|
||||
|
||||
// Format `id`.
|
||||
const name = scope.name || nameToSlug(scope.id);
|
||||
|
||||
// `scope.args` are the raw command line arguments.
|
||||
_.defaults(scope, {
|
||||
name,
|
||||
environment: process.env.NODE_ENV || 'development',
|
||||
});
|
||||
|
||||
// Determine the destination path.
|
||||
let filePath;
|
||||
if (scope.args.api) {
|
||||
filePath = `./api/${scope.args.api}/models`;
|
||||
} else if (scope.args.plugin) {
|
||||
filePath = `./plugins/${scope.args.plugin}/models`;
|
||||
} else {
|
||||
filePath = `./api/${name}/models`;
|
||||
}
|
||||
|
||||
// Take another pass to take advantage of the defaults absorbed in previous passes.
|
||||
_.defaults(scope, {
|
||||
rootPath: scope.rootPath,
|
||||
filePath,
|
||||
filename: `${name}.js`,
|
||||
filenameSettings: `${name}.settings.json`,
|
||||
});
|
||||
|
||||
// Validate optional attribute arguments.
|
||||
const invalidAttributes = [];
|
||||
|
||||
if (_.isPlainObject(scope.args.attributes)) {
|
||||
scope.attributes = scope.args.attributes;
|
||||
} else {
|
||||
// Map attributes and split them for CLI.
|
||||
scope.attributes = scope.args.attributes.map(attribute => {
|
||||
if (_.isString(attribute)) {
|
||||
const parts = attribute.split(':');
|
||||
|
||||
parts[1] = parts[1] || 'string';
|
||||
|
||||
// Handle invalid attributes.
|
||||
if (!parts[1] || !parts[0]) {
|
||||
invalidAttributes.push('Error: Invalid attribute notation `' + attribute + '`.');
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
name: _.trim(_.deburr(parts[0].toLowerCase())),
|
||||
params: {
|
||||
type: _.trim(_.deburr(parts[1].toLowerCase())),
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return _.has(attribute, 'params.type') ? attribute : undefined;
|
||||
}
|
||||
});
|
||||
|
||||
scope.attributes = _.compact(scope.attributes);
|
||||
|
||||
// Handle invalid action arguments.
|
||||
// Send back invalidActions.
|
||||
if (invalidAttributes.length) {
|
||||
return cb.invalid(invalidAttributes);
|
||||
}
|
||||
|
||||
// Make sure there aren't duplicates.
|
||||
if (
|
||||
_(scope.attributes.map(attribute => attribute.name))
|
||||
.uniq()
|
||||
.valueOf().length !== scope.attributes.length
|
||||
) {
|
||||
return cb.invalid('Duplicate attributes not allowed!');
|
||||
}
|
||||
|
||||
// Render some stringified code from the action template
|
||||
// and make it available in our scope for use later on.
|
||||
scope.attributes = scope.attributes.reduce((acc, attribute) => {
|
||||
acc[attribute.name] = attribute.params;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
// Set collectionName
|
||||
scope.collectionName = _.has(scope.args, 'collectionName')
|
||||
? scope.args.collectionName
|
||||
: nameToCollectionName(pluralize(scope.id));
|
||||
|
||||
// Set description
|
||||
scope.description = _.has(scope.args, 'description') ? scope.args.description : undefined;
|
||||
|
||||
scope.schema = JSON.stringify(
|
||||
{
|
||||
kind: 'collectionType',
|
||||
collectionName: scope.collectionName,
|
||||
info: {
|
||||
name: scope.id,
|
||||
description: scope.description,
|
||||
},
|
||||
options: {
|
||||
draftAndPublish: scope.args.draftAndPublish === 'true',
|
||||
comment: '',
|
||||
},
|
||||
attributes: scope.attributes,
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
|
||||
// Trigger callback with no error to proceed.
|
||||
return cb();
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Generate a core API
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
templatesDirectory: path.resolve(__dirname, '..', 'templates'),
|
||||
before: require('./before'),
|
||||
targets: {
|
||||
':filePath/:filename': {
|
||||
template: 'model.template',
|
||||
},
|
||||
':filePath/:filenameSettings': {
|
||||
template: 'model.settings.template',
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -1,49 +0,0 @@
|
||||
{
|
||||
"name": "@strapi/generate-model",
|
||||
"version": "3.6.8",
|
||||
"description": "Generate a model for a Strapi API.",
|
||||
"homepage": "https://strapi.io",
|
||||
"keywords": [
|
||||
"generate",
|
||||
"generator",
|
||||
"model",
|
||||
"strapi"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21",
|
||||
"pluralize": "^8.0.0",
|
||||
"@strapi/utils": "3.6.8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
"name": "Strapi team",
|
||||
"url": "https://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x.x <=16.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"gitHead": "231263a3535658bab1e9492c6aaaed8692d62a53"
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
<%= schema %>
|
||||
@ -1,16 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{package.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
104
packages/generators/plugin/.gitignore
vendored
104
packages/generators/plugin/.gitignore
vendored
@ -1,104 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
testApp
|
||||
coverage
|
||||
@ -1,109 +0,0 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
.snyk
|
||||
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
tests
|
||||
__tests__
|
||||
jest.config.js
|
||||
testApp
|
||||
coverage
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user