zapier-platform-cli
Version:
The CLI for apps in the Zapier Developer Platform.
115 lines (101 loc) • 5.29 kB
JavaScript
;
var path = require('path');
var _ = require('lodash');
var colors = require('colors');
var utils = require('../utils');
var scaffold = function scaffold(context, type, name) {
if (!name) {
context.line('Missing arguments. Please see `zaper help scaffold`.');
return Promise.resolve();
}
var templateContext = {
CAMEL: utils.camelCase(name),
KEY: utils.snakeCase(name),
NOUN: _.capitalize(name),
LOWER_NOUN: name.toLowerCase(),
INPUT_FIELDS: ''
};
// what is the `resources: {}` app definition point?
var typeMap = {
resource: 'resources',
trigger: 'triggers',
search: 'searches',
create: 'creates'
};
// where will we create/required the new file?
var destMap = {
resource: 'resources/' + templateContext.KEY,
trigger: 'triggers/' + templateContext.KEY,
search: 'searches/' + templateContext.KEY,
create: 'creates/' + templateContext.KEY
};
if (!typeMap[type]) {
context.line('Scaffold type "' + type + '" not found! Please see `zaper help scaffold`.');
return Promise.resolve();
}
var templateFile = path.join(__dirname, '../../scaffold/' + type + '.template.js');
var dest = global.argOpts.dest || destMap[type];
var destFile = path.join(process.cwd(), dest + '.js');
var entry = global.argOpts.entry || 'index.js';
var entryFile = path.join(process.cwd(), entry);
context.line('Adding ' + type + ' scaffold to your project.\n');
return utils.readFile(templateFile).then(function (templateBuf) {
return templateBuf.toString();
}).then(function (template) {
return _.template(template, { interpolate: /<%=([\s\S]+?)%>/g })(templateContext);
}).then(function (rendered) {
utils.printStarting('Writing new ' + dest + '.js');
return utils.ensureDir(path.dirname(destFile)).then(function () {
return utils.writeFile(destFile, rendered);
});
}).then(function () {
return utils.printDone();
}).then(function () {
return utils.readFile(entryFile);
}).then(function (entryBuf) {
return entryBuf.toString();
}).then(function (entryJs) {
utils.printStarting('Rewriting your ' + entry);
var lines = entryJs.split('\n');
// this is very dumb and will definitely break, it inserts lines of code
// we should look at jscodeshift or friends to do this instead
// insert Resource = require() line at top
var varName = '' + templateContext.CAMEL + utils.camelCase(type);
var importerLine = 'const ' + varName + ' = require(\'./' + dest + '\');';
lines.splice(0, 0, importerLine);
// insert '[Resource.key]: Resource,' after 'resources:' line
var injectAfter = typeMap[type] + ': {';
var injectorLine = '[' + varName + '.key]: ' + varName + ',';
var linesDefIndex = _.findIndex(lines, function (line) {
return _.endsWith(line, injectAfter);
});
if (linesDefIndex === -1) {
utils.printDone(false);
context.line();
context.line(colors.bold('Oops, we could not reliably rewrite your ' + entry + '.') + ' Please add:');
context.line(' * `' + importerLine + '` to the top');
context.line(' * `' + injectAfter + ' ' + injectorLine + ' },` in your app definition');
return Promise.resolve();
} else {
lines.splice(linesDefIndex + 1, 0, ' ' + injectorLine);
return utils.writeFile(entryFile, lines.join('\n')).then(function () {
return utils.printDone();
});
}
}).then(function () {
return context.line('\nFinished! We did the best we could, you might gut check your files though.');
});
};
scaffold.argsSpec = [{ name: 'type', help: 'what type of thing are you creating', required: true, choices: [
// 'index',
// 'oauth2',
'resource', 'trigger', 'search', 'create'] }, { name: 'name', help: 'the name of the new thing to create', required: true, example: 'Some Name' }];
scaffold.argOptsSpec = {
dest: { help: 'sets the new file\'s path', default: '{type}s/{name}' },
entry: { help: 'where to import the new file', default: 'index.js' }
};
scaffold.help = 'Adds a starting resource, trigger, action or search to your app.';
scaffold.usage = 'zapier scaffold {resource|trigger|search|create} "Name"';
scaffold.example = 'zapier scaffold resource "Contact"';
scaffold.docs = '\nThe scaffold command does two general things:\n\n* Creates a new destination file like `resources/contact.js`\n* (Attempts to) import and register it inside your entry `index.js`\n\nYou can mix and match several options to customize the created scaffold for your project.\n\n> Note, we may fail to rewrite your `index.js` so you may need to handle the require and registration yourself.\n\n**Arguments**\n\n' + utils.argsFragment(scaffold.argsSpec) + '\n' + utils.argOptsFragment(scaffold.argOptsSpec) + '\n\n' + '```' + 'bash\n$ ' + scaffold.example + '\n$ zapier scaffold resource "Contact" --entry=index.js\n$ zapier scaffold resource "Contag Tag" --dest=resources/tag\n$ zapier scaffold resource "Tag" --entry=index.js --dest=resources/tag\n# Adding resource scaffold to your project.\n#\n# Writing new resources/tag.js - done!\n# Rewriting your index.js - done!\n#\n# Finished! We did the best we could, you might gut check your files though.\n' + '```' + '\n';
module.exports = scaffold;