diff --git a/docs/cli.html b/docs/cli.html index d1fc80919..3b0085bc7 100644 --- a/docs/cli.html +++ b/docs/cli.html @@ -393,26 +393,16 @@

convert

Converts a Legacy Web Builder or Visual Builder app to a CLI app.

-

Usage: zapier convert appid path

Creates a new CLI app from an existing app.

If you're converting a Legacy Web Builder app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app!

After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them.

Once you've run the command, make sure to run zapier push to see it in the editor.

If you're converting a Visual Builder app, then it will be identical and ready to push and use immediately! You'll need to do a zapier push before the new version is visible in the editor, but otherwise you're good to go.

Arguments

-
-
$ zapier convert 1234 .
-# Let's convert your app!
-#
-#   Downloading app from Zapier - done!
-#   Writing triggers/trigger.js - done!
-#   Writing package.json - done!
-#   Writing index.js - done!
-#   Copy ./index.js - done!
-#   Copy ./package.json - done!
-#   Copy ./triggers/trigger.js - done!
-#
-# Finished! You might need to `npm install` then try `zapier test`!
-
+
+
diff --git a/docs/cli.md b/docs/cli.md index 4afb5744f..f916a2780 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -55,41 +55,25 @@ This command is typically followed by `zapier upload`. ## convert - > Converts a Legacy Web Builder or Visual Builder app to a CLI app. +> Converts a Legacy Web Builder or Visual Builder app to a CLI app. - **Usage:** `zapier convert appid path` - - -Creates a new CLI app from an existing app. +**Usage**: `zapier convert INTEGRATIONID PATH` If you're converting a **Legacy Web Builder** app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app! After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them. -Once you've run the command, make sure to run `zapier push` to see it in the editor. +If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! -If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! You'll need to do a `zapier push` before the new version is visible in the editor, but otherwise you're good to go. +You'll need to do a `zapier push` before the new version is visible in the editor, but otherwise you're good to go. **Arguments** +* (required) `integrationId` | To get the integration id, go to "https://zapier.com/app/developer", click on an integration, and copy the number directly after "/app/" in the url. +* (required) `path` | Relative to your current path - IE: `.` for current directory -* `appid [value]` -- **required**, Get the appid from "https://zapier.com/app/developer", clicking on an integration, and taking the number after "/app" in the url. -* `location [value]` -- **required**, Relative to your current path - IE: `.` for current directory -* `--version=1.0.0` -- _optional_, Convert a specific version. Required when converting a Visual Builder app - -```bash -$ zapier convert 1234 . -# Let's convert your app! -# -# Downloading app from Zapier - done! -# Writing triggers/trigger.js - done! -# Writing package.json - done! -# Writing index.js - done! -# Copy ./index.js - done! -# Copy ./package.json - done! -# Copy ./triggers/trigger.js - done! -# -# Finished! You might need to `npm install` then try `zapier test`! -``` +**Flags** +* `-v, --version` | Convert a specific version. Required when converting a Visual Builder app +* `-d, --debug` | Show extra debugging output ## delete:integration diff --git a/packages/cli/docs/cli.html b/packages/cli/docs/cli.html index d1fc80919..3b0085bc7 100644 --- a/packages/cli/docs/cli.html +++ b/packages/cli/docs/cli.html @@ -393,26 +393,16 @@

convert

Converts a Legacy Web Builder or Visual Builder app to a CLI app.

-

Usage: zapier convert appid path

Creates a new CLI app from an existing app.

If you're converting a Legacy Web Builder app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app!

After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them.

Once you've run the command, make sure to run zapier push to see it in the editor.

If you're converting a Visual Builder app, then it will be identical and ready to push and use immediately! You'll need to do a zapier push before the new version is visible in the editor, but otherwise you're good to go.

Arguments

-
-
$ zapier convert 1234 .
-# Let's convert your app!
-#
-#   Downloading app from Zapier - done!
-#   Writing triggers/trigger.js - done!
-#   Writing package.json - done!
-#   Writing index.js - done!
-#   Copy ./index.js - done!
-#   Copy ./package.json - done!
-#   Copy ./triggers/trigger.js - done!
-#
-# Finished! You might need to `npm install` then try `zapier test`!
-
+
+
diff --git a/packages/cli/docs/cli.md b/packages/cli/docs/cli.md index 4afb5744f..f916a2780 100644 --- a/packages/cli/docs/cli.md +++ b/packages/cli/docs/cli.md @@ -55,41 +55,25 @@ This command is typically followed by `zapier upload`. ## convert - > Converts a Legacy Web Builder or Visual Builder app to a CLI app. +> Converts a Legacy Web Builder or Visual Builder app to a CLI app. - **Usage:** `zapier convert appid path` - - -Creates a new CLI app from an existing app. +**Usage**: `zapier convert INTEGRATIONID PATH` If you're converting a **Legacy Web Builder** app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app! After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them. -Once you've run the command, make sure to run `zapier push` to see it in the editor. +If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! -If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! You'll need to do a `zapier push` before the new version is visible in the editor, but otherwise you're good to go. +You'll need to do a `zapier push` before the new version is visible in the editor, but otherwise you're good to go. **Arguments** +* (required) `integrationId` | To get the integration id, go to "https://zapier.com/app/developer", click on an integration, and copy the number directly after "/app/" in the url. +* (required) `path` | Relative to your current path - IE: `.` for current directory -* `appid [value]` -- **required**, Get the appid from "https://zapier.com/app/developer", clicking on an integration, and taking the number after "/app" in the url. -* `location [value]` -- **required**, Relative to your current path - IE: `.` for current directory -* `--version=1.0.0` -- _optional_, Convert a specific version. Required when converting a Visual Builder app - -```bash -$ zapier convert 1234 . -# Let's convert your app! -# -# Downloading app from Zapier - done! -# Writing triggers/trigger.js - done! -# Writing package.json - done! -# Writing index.js - done! -# Copy ./index.js - done! -# Copy ./package.json - done! -# Copy ./triggers/trigger.js - done! -# -# Finished! You might need to `npm install` then try `zapier test`! -``` +**Flags** +* `-v, --version` | Convert a specific version. Required when converting a Visual Builder app +* `-d, --debug` | Show extra debugging output ## delete:integration diff --git a/packages/cli/src/commands/convert.js b/packages/cli/src/commands/convert.js deleted file mode 100644 index a0fa0fb7b..000000000 --- a/packages/cli/src/commands/convert.js +++ /dev/null @@ -1,154 +0,0 @@ -const utils = require('../utils'); -const constants = require('../constants'); - -const convert = (context, appid, location) => { - context.line('Beginning Conversion'); - context.line(); - - appid = Number(appid); - if (!appid) { - const message = `You must provide an appid - get that from ${ - constants.BASE_ENDPOINT - }/developer/builder/ (check the URL).`; - return Promise.reject(new Error(message)); - } - const isVisual = Boolean(context.argOpts.version); - - const createApp = async tempAppDir => { - if (isVisual) { - // has info about the app, such as title - - // has a CLI version of the actual app implementation - - utils.startSpinner('Downloading app from Zapier'); - try { - const [appInfo, versionInfo] = await Promise.all([ - utils.callAPI(`/apps/${appid}`, true), - utils.callAPI( - `/apps/${appid}/versions/${context.argOpts.version}`, - true - ) - ]); - utils.endSpinner(); - return utils.convertVisualApp( - appInfo, - versionInfo.definition_override, - tempAppDir - ); - } catch (e) { - if (e.status === 404) { - throw new Error( - `Visual Builder app ${appid} @ ${ - context.argOpts.version - } not found. If you want to convert a Legacy Web Builder app, don't pass a \`--version\` option.` - ); - } - throw e; - } - } else { - // has info about the app, such as title - const legacyDumpUrl = `${ - constants.BASE_ENDPOINT - }/api/developer/v1/apps/${appid}/dump`; - // has a CLI version of the actual app implementation - const cliDumpUrl = `${ - constants.BASE_ENDPOINT - }/api/developer/v1/apps/${appid}/cli-dump`; - - utils.startSpinner('Downloading app from Zapier'); - - try { - const [legacyApp, appDefinition] = await Promise.all([ - // these have weird call signatures because we're not calling the platform api - utils.callAPI(null, { url: legacyDumpUrl }, true), - utils.callAPI(null, { url: cliDumpUrl }, true) - ]); - // The JSON dump of the app doesn't have app ID, let's add it here - legacyApp.general.app_id = appid; - - utils.endSpinner(); - - return utils.convertLegacyApp(legacyApp, appDefinition, tempAppDir); - } catch (e) { - if (e.status === 404) { - throw new Error( - `Legacy Web Builder app ${appid} not found. If you want to convert a Visual Builder app, make sure to pass a \`--version\` option.` - ); - } - throw e; - } - } - }; - - return utils.initApp(context, location, createApp).then(() => { - context.line(); - context.line( - `Finished! You may try \`npm install\` and then \`zapier test\` in the "${location}" directory.` - ); - context.line( - "Also, if your app has authentication, don't forget to set environment variables:" - ); - context.line('* for local testing, edit the .env file'); - if (!isVisual) { - // converted apps already have this set - context.line('* for produciton, use `zapier env` command'); - } - }); -}; -convert.argsSpec = [ - { - name: 'appid', - required: true, - help: `Get the appid from "${ - constants.BASE_ENDPOINT - }/app/developer", clicking on an integration, and taking the number after "/app" in the url.` - }, - { - name: 'location', - required: true, - help: 'Relative to your current path - IE: `.` for current directory' - } -]; -convert.argOptsSpec = { - version: { - help: - 'Convert a specific version. Required when converting a Visual Builder app', - example: '1.0.0' - } -}; -convert.help = - 'Converts a Legacy Web Builder or Visual Builder app to a CLI app.'; -convert.example = 'zapier convert appid path'; -convert.docs = ` -Creates a new CLI app from an existing app. - -If you're converting a **Legacy Web Builder** app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app! - -After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them. - -Once you've run the command, make sure to run \`zapier push\` to see it in the editor. - -If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! You'll need to do a \`zapier push\` before the new version is visible in the editor, but otherwise you're good to go. - -**Arguments** - -${utils.argsFragment(convert.argsSpec)} -${utils.argOptsFragment(convert.argOptsSpec)} - -${'```'}bash -$ zapier convert 1234 . -# Let's convert your app! -# -# Downloading app from Zapier - done! -# Writing triggers/trigger.js - done! -# Writing package.json - done! -# Writing index.js - done! -# Copy ./index.js - done! -# Copy ./package.json - done! -# Copy ./triggers/trigger.js - done! -# -# Finished! You might need to \`npm install\` then try \`zapier test\`! -${'```'} -`; - -module.exports = convert; diff --git a/packages/cli/src/commands/index.js b/packages/cli/src/commands/index.js index 556b99edd..6b237c21b 100644 --- a/packages/cli/src/commands/index.js +++ b/packages/cli/src/commands/index.js @@ -1,4 +1,3 @@ module.exports = { - convert: require('./convert'), help: require('./help') }; diff --git a/packages/cli/src/oclif/commands/convert.js b/packages/cli/src/oclif/commands/convert.js new file mode 100644 index 000000000..d3a7923d4 --- /dev/null +++ b/packages/cli/src/oclif/commands/convert.js @@ -0,0 +1,130 @@ +const BaseCommand = require('../ZapierBaseCommand'); +const { buildFlags } = require('../buildFlags'); + +const { callAPI } = require('../../utils/api'); +const { convertVisualApp, convertLegacyApp } = require('../../utils/convert'); +const { isExistingEmptyDir } = require('../../utils/files'); +const { initApp } = require('../../utils/init'); +const { BASE_ENDPOINT } = require('../../constants'); + +const { flags } = require('@oclif/command'); + +class ConvertCommand extends BaseCommand { + generateCreateFunc(isVisual, appId, version) { + return async tempAppDir => { + if (isVisual) { + // has info about the app, such as title + // has a CLI version of the actual app implementation + this.throwForInvalidVersion(version); + this.startSpinner('Downloading integration from Zapier'); + try { + const [appInfo, versionInfo] = await Promise.all([ + callAPI(`/apps/${appId}`, undefined, true), + callAPI(`/apps/${appId}/versions/${version}`, undefined, true) + ]); + + if (!versionInfo.definition_override) { + this.error( + `Integration ${appId} @ ${version} is already a CLI integration and can't be converted. Instead, pick a version that was created using the Visual Builder.` + ); + } + this.stopSpinner(); + + return convertVisualApp( + appInfo, + versionInfo.definition_override, + tempAppDir + ); + } catch (e) { + if (e.status === 404) { + this.error( + `Visual Builder integration ${appId} @ ${version} not found. If you want to convert a Legacy Web Builder app, don't pass a \`--version\` option. Otherwise, double check the integration id and version.` + ); + } + this.error(e); + } + } else { + // has info about the app, such as title + const legacyDumpUrl = `${BASE_ENDPOINT}/api/developer/v1/apps/${appId}/dump`; + // has a CLI version of the actual app implementation + const cliDumpUrl = `${BASE_ENDPOINT}/api/developer/v1/apps/${appId}/cli-dump`; + + this.startSpinner('Downloading app from Zapier'); + + try { + const [legacyApp, appDefinition] = await Promise.all([ + // these have weird call signatures because we're not calling the platform api + callAPI(null, { url: legacyDumpUrl }, true), + callAPI(null, { url: cliDumpUrl }, true) + ]); + // The JSON dump of the app doesn't have app ID, let's add it here + legacyApp.general.app_id = appId; + + this.stopSpinner(); + + return convertLegacyApp(legacyApp, appDefinition, tempAppDir); + } catch (e) { + if (e.status === 404) { + this.error( + `Legacy Web Builder app ${appId} not found. If you want to convert a Visual Builder app, make sure to pass a \`--version\` option.` + ); + } + this.error(e); + } + } + }; + } + + async perform() { + const { integrationId: appId, path } = this.args; + const { version } = this.flags; + if (!appId) { + this.error( + 'You must provide an integrationId. See zapier convert --help for more info.' + ); + } + const isVisual = Boolean(this.flags.version); + + if ( + (await isExistingEmptyDir(path)) && + !(await this.confirm(`Path "${path}" is not empty. Continue anyway?`)) + ) { + this.exit(); + } + + await initApp(path, this.generateCreateFunc(isVisual, appId, version)); + } +} + +ConvertCommand.args = [ + { + name: 'integrationId', + required: true, + description: `To get the integration id, go to "${BASE_ENDPOINT}/app/developer", click on an integration, and copy the number directly after "/app/" in the url.`, + parse: input => Number(input) + }, + { + name: 'path', + required: true, + description: 'Relative to your current path - IE: `.` for current directory' + } +]; +ConvertCommand.flags = buildFlags({ + commandFlags: { + version: flags.string({ + char: 'v', + description: + 'Convert a specific version. Required when converting a Visual Builder app' + }) + } +}); +ConvertCommand.description = `Converts a Legacy Web Builder or Visual Builder app to a CLI app. + +If you're converting a **Legacy Web Builder** app: the new app contains code stubs only. It is supposed to get you started - it isn't going to create a complete app! +After running this, you'll have a new app in your directory, with stubs for your trigger and actions. If you re-run this command on an existing directory it will leave existing files alone and not clobber them. + +If you're converting a **Visual Builder** app, then it will be identical and ready to push and use immediately! + +You'll need to do a \`zapier push\` before the new version is visible in the editor, but otherwise you're good to go.`; + +module.exports = ConvertCommand; diff --git a/packages/cli/src/oclif/commands/init.js b/packages/cli/src/oclif/commands/init.js index 84752b7ef..222c1369b 100644 --- a/packages/cli/src/oclif/commands/init.js +++ b/packages/cli/src/oclif/commands/init.js @@ -6,7 +6,7 @@ const appTemplates = require('../../app-templates'); const { isExistingEmptyDir } = require('../../utils/files'); -const { oInitApp } = require('../../utils/init'); +const { initApp } = require('../../utils/init'); const { downloadExampleAppTo, removeReadme @@ -41,7 +41,7 @@ class InitCommand extends BaseCommand { this.exit(); } - await oInitApp(path, this.generateCreateFunc(template)); + await initApp(path, this.generateCreateFunc(template)); } } diff --git a/packages/cli/src/oclif/oCommands.js b/packages/cli/src/oclif/oCommands.js index 85a8852c0..9e01e911d 100644 --- a/packages/cli/src/oclif/oCommands.js +++ b/packages/cli/src/oclif/oCommands.js @@ -4,6 +4,7 @@ module.exports = { analytics: require('./commands/analytics'), apps: true, build: require('./commands/build'), + convert: require('./commands/convert'), deprecate: require('./commands/deprecate'), delete: true, 'delete:integration': require('./commands/delete/integration'), diff --git a/packages/cli/src/utils/convert.js b/packages/cli/src/utils/convert.js index 1778f268d..a9a91c81b 100644 --- a/packages/cli/src/utils/convert.js +++ b/packages/cli/src/utils/convert.js @@ -7,6 +7,7 @@ const semver = require('semver'); const { PACKAGE_VERSION, PLATFORM_PACKAGE, + LAMBDA_VERSION, IS_TESTING } = require('../constants'); const { copyFile, ensureDir, readFile, writeFile } = require('./files'); @@ -130,7 +131,7 @@ const renderVisualPackageJson = (appInfo, appDefinition) => { test: 'mocha --recursive -t 10000' }, engines: { - node: '8.10.0', + node: `>=${LAMBDA_VERSION}`, npm: '>=5.6.0' }, dependencies: { diff --git a/packages/cli/src/utils/init.js b/packages/cli/src/utils/init.js index 806175509..998aa2a20 100644 --- a/packages/cli/src/utils/init.js +++ b/packages/cli/src/utils/init.js @@ -2,39 +2,9 @@ const { resolve } = require('path'); const tmp = require('tmp'); const { startSpinner, endSpinner } = require('./display'); -const { - confirmNonEmptyDir, - copyDir, - removeDir, - ensureDir -} = require('./files'); +const { copyDir, removeDir, ensureDir } = require('./files'); -const initApp = (context, location, createApp) => { - const appDir = resolve(location); - const tempAppDir = tmp.tmpNameSync(); - - const copyOpts = { - clobber: false, - onCopy: file => { - startSpinner(`Copy ${file}`); - endSpinner(); - }, - onSkip: file => { - startSpinner(`File ${file} already exists (skipped)`); - endSpinner(); - } - }; - - return confirmNonEmptyDir(location) - .then(() => removeDir(tempAppDir)) - .then(() => ensureDir(tempAppDir)) - .then(() => createApp(tempAppDir)) - .then(() => ensureDir(appDir)) - .then(() => copyDir(tempAppDir, appDir, copyOpts)) - .then(() => removeDir(tempAppDir)); -}; - -const oInitApp = async (path, createFunc) => { +const initApp = async (path, createFunc) => { const appDir = resolve(path); const tempAppDir = tmp.tmpNameSync(); @@ -59,6 +29,5 @@ const oInitApp = async (path, createFunc) => { }; module.exports = { - initApp, - oInitApp + initApp };