UNPKG

zapier-platform-cli

Version:

The CLI for apps in the Zapier Developer Platform.

279 lines (222 loc) 8.22 kB
'use strict'; var _ = require('lodash'); var path = require('path'); var _require = require('./misc'), camelCase = _require.camelCase, snakeCase = _require.snakeCase; var _require2 = require('./files'), readFile = _require2.readFile, writeFile = _require2.writeFile, ensureDir = _require2.ensureDir; var _require3 = require('./display'), printStarting = _require3.printStarting, printDone = _require3.printDone; var MIN_HELP_TEXT_LENGTH = 10; var TEMPLATE_DIR = path.join(__dirname, '../../scaffold/convert'); // map v2 field types to v2 types var typesMap = { unicode: 'string', textarea: 'text', integer: 'integer', float: 'number', boolean: 'boolean', datetime: 'datetime', file: 'file', password: 'password' }; // map v2 step names to cli names var stepNamesMap = { triggers: 'trigger', searches: 'search', actions: 'create' }; var renderTemplate = function renderTemplate(templateFile, templateContext) { return readFile(templateFile).then(function (templateBuf) { return templateBuf.toString(); }).then(function (template) { return _.template(template, { interpolate: /<%=([\s\S]+?)%>/g })(templateContext); }); }; var createFile = function createFile(content, fileName, dir) { var destFile = path.join(dir, fileName); return ensureDir(path.dirname(destFile)).then(function () { return writeFile(destFile, content); }).then(function () { printStarting('Writing ' + fileName); printDone(); }); }; var padHelpText = function padHelpText(text) { var msg = '(help text must be at least ' + MIN_HELP_TEXT_LENGTH + ' characters)'; if (!_.isString(text)) { return msg; } if (text.length < MIN_HELP_TEXT_LENGTH) { return text + ' ' + msg; } return text; }; var renderProp = function renderProp(key, value) { return key + ': ' + value; }; var quote = function quote(s) { return '\'' + s + '\''; }; var renderField = function renderField(definition, key) { var type = definition.type && typesMap[definition.type.toLowerCase()] || 'string'; var props = []; props.push(renderProp('key', quote(key))); if (definition.label) { props.push(renderProp('label', quote(definition.label))); } props.push(renderProp('helpText', quote(padHelpText(definition.help_text)))); props.push(renderProp('type', quote(type))); props.push(renderProp('required', Boolean(definition.required))); if (definition.placeholder) { props.push(renderProp('placeholder', quote(definition.placeholder))); } props = props.map(function (s) { return ' '.repeat(8) + s; }); return ' {\n' + props.join(',\n') + '\n }'; }; var renderSampleField = function renderSampleField(def) { var type = typesMap[def.type] || 'string'; if (def.label) { return ' {\n key: ' + quote(def.key) + ',\n type: ' + quote(type) + ',\n label: ' + quote(def.label) + '\n }'; } return ' {\n key: ' + quote(def.key) + ',\n type: ' + quote(type) + '\n }'; }; var renderSample = function renderSample(definition) { var fields = _.map(definition.sample_result_fields, renderSampleField); if (!fields.length) { return ''; } return ' outputFields: [\n' + fields.join(',\n') + '\n ]'; }; var renderBasicAuth = function renderBasicAuth(definition) { var fields = _.map(definition.auth_fields, renderField); var auth = '{\n type: \'basic\',\n test: {\n url: \'http://www.example.com/auth\' // TODO just an example, you\'ll need to supply the real URL\n },\n fields: [\n ' + fields.join(',\n') + '\n ]\n }'; return Promise.resolve(auth); }; var renderOAuth2 = function renderOAuth2(definition) { var authorizeUrl = _.get(definition, ['general', 'auth_urls', 'authorization_url'], 'TODO'); var accessTokenUrl = _.get(definition, ['general', 'auth_urls', 'access_token_url'], 'TODO'); var templateContext = { AUTHORIZE_URL: authorizeUrl, ACCESS_TOKEN_URL: accessTokenUrl }; var templateFile = path.join(TEMPLATE_DIR, '/oauth2.template.js'); return renderTemplate(templateFile, templateContext); }; var renderAuth = function renderAuth(definition) { var authTypeMap = { 'Basic Auth': 'basic', 'OAuth V2': 'oauth2' }; var type = authTypeMap[definition.general.auth_type]; if (type === 'basic') { return renderBasicAuth(definition); } else if (type === 'oauth2') { return renderOAuth2(definition); } else { return Promise.resolve('{\n // TODO: complete auth settings\n }'); } }; // convert a trigger, create or search var renderStep = function renderStep(type, definition, key) { var fields = _.map(definition.fields, renderField); var sample = !_.isEmpty(definition.sample_result_fields) ? renderSample(definition) + ',\n' : ''; var url = definition.url ? quote(definition.url) + ',' : '\'http://example.com/api/' + key + '.json\', // TODO this is just an example'; var templateContext = { KEY: snakeCase(key), CAMEL: camelCase(key), NOUN: _.capitalize(key), LOWER_NOUN: key.toLowerCase(), FIELDS: fields.join(',\n'), SAMPLE: sample, URL: url }; var templateFile = path.join(TEMPLATE_DIR, '/' + type + '.template.js'); return renderTemplate(templateFile, templateContext); }; // write a new trigger, create, or search var writeStep = function writeStep(type, definition, key, newAppDir) { var stepTypeMap = { trigger: 'triggers', search: 'searches', create: 'creates' }; var fileName = stepTypeMap[type] + '/' + snakeCase(key) + '.js'; return renderStep(type, definition, key).then(function (content) { return createFile(content, fileName, newAppDir); }); }; var renderIndex = function renderIndex(legacyApp) { return renderAuth(legacyApp).then(function (auth) { var importLines = []; var dirMap = { trigger: 'triggers', search: 'searches', create: 'creates' }; var templateContext = { AUTHENTICATION: auth, TRIGGERS: '', SEARCHES: '', CREATES: '' }; _.each(stepNamesMap, function (cliType, v2Type) { var lines = []; _.each(legacyApp[v2Type], function (definition, name) { var varName = '' + camelCase(name) + _.capitalize(camelCase(cliType)); var requireFile = dirMap[cliType] + '/' + snakeCase(name); importLines.push('const ' + varName + ' = require(\'./' + requireFile + '\');'); lines.push('[' + varName + '.key]: ' + varName + ','); }); var section = dirMap[cliType].toUpperCase(); templateContext[section] = lines.join(',\n'); }); templateContext.REQUIRES = importLines.join('\n'); var templateFile = path.join(TEMPLATE_DIR, '/index.template.js'); return renderTemplate(templateFile, templateContext); }); }; var writeIndex = function writeIndex(legacyApp, newAppDir) { return renderIndex(legacyApp).then(function (content) { return createFile(content, 'index.js', newAppDir); }); }; var renderPackageJson = function renderPackageJson(legacyApp) { var templateContext = { NAME: _.kebabCase(legacyApp.general.title), DESCRIPTION: legacyApp.general.description, ZAPIER_CORE_VERSION: require('../../package.json').version }; var templateFile = path.join(TEMPLATE_DIR, '/package.template.json'); return renderTemplate(templateFile, templateContext); }; var writePackageJson = function writePackageJson(legacyApp, newAppDir) { return renderPackageJson(legacyApp).then(function (content) { return createFile(content, 'package.json', newAppDir); }); }; var convertApp = function convertApp(legacyApp, newAppDir) { var promises = []; _.each(stepNamesMap, function (cliType, v2Type) { _.each(legacyApp[v2Type], function (definition, key) { promises.push(writeStep(cliType, definition, key, newAppDir)); }); }); promises.push(writeIndex(legacyApp, newAppDir)); promises.push(writePackageJson(legacyApp, newAppDir)); return Promise.all(promises); }; module.exports = { convertApp: convertApp, renderAuth: renderAuth, renderField: renderField, renderSample: renderSample, renderStep: renderStep, renderTemplate: renderTemplate };