mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
186 lines
6.3 KiB
JavaScript
186 lines
6.3 KiB
JavaScript
'use strict';
|
|
|
|
const BbPromise = require('bluebird');
|
|
const path = require('path');
|
|
const fse = require('fs-extra');
|
|
const untildify = require('untildify');
|
|
|
|
const ServerlessError = require('../../serverless-error');
|
|
const cliCommandsSchema = require('../../cli/commands-schema');
|
|
const createFromTemplate = require('../../utils/createFromTemplate');
|
|
const recommendedTemplatesList = require('../../templates/recommended-list');
|
|
const humanReadableTemplatesList = require('../../templates/recommended-list/human-readable');
|
|
const download = require('../../utils/downloadTemplateFromRepo');
|
|
const renameService = require('../../utils/renameService').renameService;
|
|
const copyDirContentsSync = require('../../utils/fs/copyDirContentsSync');
|
|
const dirExistsSync = require('../../utils/fs/dirExistsSync');
|
|
|
|
const handleServiceCreationError = (error) => {
|
|
if (error.code !== 'EACCESS') throw error;
|
|
const errorMessage = [
|
|
'Error unable to create a service in this directory. ',
|
|
'Please check that you have the required permissions to write to the directory',
|
|
].join('');
|
|
|
|
throw new ServerlessError(errorMessage, 'UNABLE_TO_CREATE_SERVICE');
|
|
};
|
|
|
|
class Create {
|
|
constructor(serverless, options) {
|
|
this.serverless = serverless;
|
|
this.options = options;
|
|
|
|
this.commands = {
|
|
create: {
|
|
...cliCommandsSchema.get('create'),
|
|
},
|
|
};
|
|
|
|
this.hooks = {
|
|
'create:create': () => BbPromise.bind(this).then(this.create),
|
|
};
|
|
}
|
|
|
|
create() {
|
|
this.serverless.cli.log('Generating boilerplate...');
|
|
|
|
if ('template' in this.options) {
|
|
return this.createFromTemplate();
|
|
} else if ('template-url' in this.options) {
|
|
return download
|
|
.downloadTemplateFromRepo(
|
|
this.options['template-url'],
|
|
this.options.name,
|
|
this.options.path
|
|
)
|
|
.then((serviceName) => {
|
|
const message = [
|
|
`Successfully installed "${serviceName}" `,
|
|
`${
|
|
this.options.name && this.options.name !== serviceName
|
|
? `as "${this.options.name}"`
|
|
: ''
|
|
}`,
|
|
].join('');
|
|
|
|
this.serverless.cli.log(message);
|
|
})
|
|
.catch((err) => {
|
|
throw new ServerlessError(err, 'BOILERPLATE_GENERATION_ERROR');
|
|
});
|
|
} else if ('template-path' in this.options) {
|
|
// Copying template from a local directory
|
|
const serviceDir = this.options.path
|
|
? path.resolve(process.cwd(), untildify(this.options.path))
|
|
: path.join(process.cwd(), this.options.name);
|
|
if (dirExistsSync(serviceDir)) {
|
|
const errorMessage = `A folder named "${serviceDir}" already exists.`;
|
|
throw new ServerlessError(errorMessage, 'TARGET_FOLDER_ALREADY_EXISTS');
|
|
}
|
|
copyDirContentsSync(untildify(this.options['template-path']), serviceDir, {
|
|
noLinks: true,
|
|
});
|
|
if (this.options.name) {
|
|
renameService(this.options.name, serviceDir);
|
|
}
|
|
} else {
|
|
const errorMessage = [
|
|
'You must either pass a template name (--template), ',
|
|
'a URL (--template-url) or a local path (--template-path).',
|
|
].join('');
|
|
throw new ServerlessError(errorMessage, 'MISSING_TEMPLATE_CLI_PARAM');
|
|
}
|
|
return BbPromise.resolve();
|
|
}
|
|
|
|
createFromTemplate() {
|
|
const notPlugin = this.options.template !== 'plugin';
|
|
|
|
if (!recommendedTemplatesList.includes(this.options.template)) {
|
|
const errorMessage = [
|
|
`Template "${this.options.template}" is not supported.`,
|
|
` Supported templates are: ${humanReadableTemplatesList}.`,
|
|
].join('');
|
|
throw new ServerlessError(errorMessage, 'NOT_SUPPORTED_TEMPLATE');
|
|
}
|
|
|
|
// store the custom options for the service if given
|
|
const boilerplatePath = this.options.path && String(this.options.path);
|
|
const serviceName = this.options.name && String(this.options.name);
|
|
const templateSrcDir = path.join(
|
|
this.serverless.config.serverlessPath,
|
|
'plugins',
|
|
'create',
|
|
'templates',
|
|
this.options.template
|
|
);
|
|
|
|
// create (if not yet present) and chdir into the directory for the service
|
|
if (boilerplatePath) {
|
|
const newPath = path.resolve(process.cwd(), untildify(boilerplatePath));
|
|
|
|
if (this.serverless.utils.dirExistsSync(newPath)) {
|
|
const errorMessage = [
|
|
`The directory "${newPath}" already exists, and serverless will not overwrite it. `,
|
|
'Rename or move the directory and try again if you want serverless to create it"',
|
|
].join('');
|
|
|
|
throw new ServerlessError(errorMessage, 'TARGET_FOLDER_ALREADY_EXISTS');
|
|
}
|
|
|
|
this.serverless.cli.log(`Generating boilerplate in "${newPath}"`);
|
|
|
|
fse.mkdirsSync(newPath);
|
|
process.chdir(newPath);
|
|
} else {
|
|
// ensure no template file already exists in cwd that we may overwrite
|
|
const templateFullFilePaths = this.serverless.utils.walkDirSync(templateSrcDir);
|
|
|
|
templateFullFilePaths.forEach((ffp) => {
|
|
const filename = path.basename(ffp);
|
|
if (this.serverless.utils.fileExistsSync(path.join(process.cwd(), filename))) {
|
|
const errorMessage = [
|
|
`The file "${filename}" already exists, and serverless will not overwrite it. `,
|
|
`Move the file and try again if you want serverless to write a new "${filename}"`,
|
|
].join('');
|
|
|
|
throw new ServerlessError(errorMessage, 'TEMPLATE_FILE_ALREADY_EXISTS');
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!notPlugin) {
|
|
return BbPromise.try(() => {
|
|
try {
|
|
fse.copySync(
|
|
path.join(__dirname, '../../../lib/plugins/create/templates', this.options.template),
|
|
process.cwd()
|
|
);
|
|
} catch (error) {
|
|
handleServiceCreationError(error);
|
|
}
|
|
});
|
|
}
|
|
|
|
this.serverless.serviceDir = process.cwd();
|
|
|
|
return createFromTemplate(this.options.template, process.cwd(), { name: serviceName }).then(
|
|
() => {
|
|
this.serverless.cli.asciiGreeting();
|
|
this.serverless.cli.log(
|
|
`Successfully generated boilerplate for template: "${this.options.template}"`
|
|
);
|
|
|
|
if (!(boilerplatePath || serviceName) && notPlugin) {
|
|
this.serverless.cli.log(
|
|
'NOTE: Please update the "service" property in serverless.yml with your service name'
|
|
);
|
|
}
|
|
},
|
|
handleServiceCreationError
|
|
);
|
|
}
|
|
}
|
|
|
|
module.exports = Create;
|