zapier-platform-cli 15.18.1 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/oclif.manifest.json +2316 -1
  2. package/package.json +43 -33
  3. package/scaffold/create.template.ts +64 -0
  4. package/scaffold/resource.template.ts +119 -0
  5. package/scaffold/search.template.ts +63 -0
  6. package/scaffold/test.template.ts +18 -0
  7. package/scaffold/trigger.template.ts +58 -0
  8. package/src/bin/run +4 -4
  9. package/src/bin/run.cmd +0 -3
  10. package/src/generators/index.js +11 -11
  11. package/src/index.js +1 -1
  12. package/src/oclif/ZapierBaseCommand.js +51 -44
  13. package/src/oclif/buildFlags.js +14 -16
  14. package/src/oclif/commands/analytics.js +6 -6
  15. package/src/oclif/commands/build.js +6 -6
  16. package/src/oclif/commands/cache/clear.js +13 -13
  17. package/src/oclif/commands/canary/create.js +27 -20
  18. package/src/oclif/commands/canary/delete.js +26 -16
  19. package/src/oclif/commands/canary/list.js +5 -7
  20. package/src/oclif/commands/convert.js +16 -16
  21. package/src/oclif/commands/delete/version.js +6 -6
  22. package/src/oclif/commands/deprecate.js +10 -11
  23. package/src/oclif/commands/describe.js +5 -5
  24. package/src/oclif/commands/env/get.js +5 -5
  25. package/src/oclif/commands/env/set.js +11 -12
  26. package/src/oclif/commands/env/unset.js +9 -10
  27. package/src/oclif/commands/init.js +12 -13
  28. package/src/oclif/commands/invoke.js +67 -69
  29. package/src/oclif/commands/jobs.js +1 -1
  30. package/src/oclif/commands/link.js +2 -2
  31. package/src/oclif/commands/login.js +15 -15
  32. package/src/oclif/commands/logout.js +1 -1
  33. package/src/oclif/commands/logs.js +9 -9
  34. package/src/oclif/commands/migrate.js +19 -22
  35. package/src/oclif/commands/promote.js +25 -27
  36. package/src/oclif/commands/push.js +2 -2
  37. package/src/oclif/commands/register.js +31 -32
  38. package/src/oclif/commands/scaffold.js +112 -106
  39. package/src/oclif/commands/team/add.js +12 -15
  40. package/src/oclif/commands/team/get.js +2 -2
  41. package/src/oclif/commands/team/remove.js +6 -6
  42. package/src/oclif/commands/test.js +8 -8
  43. package/src/oclif/commands/upload.js +1 -1
  44. package/src/oclif/commands/users/add.js +9 -11
  45. package/src/oclif/commands/users/get.js +7 -7
  46. package/src/oclif/commands/users/links.js +4 -4
  47. package/src/oclif/commands/users/remove.js +8 -9
  48. package/src/oclif/commands/validate.js +29 -21
  49. package/src/oclif/commands/versions.js +26 -1
  50. package/src/oclif/hooks/checkValidNodeVersion.js +1 -1
  51. package/src/oclif/hooks/deprecated.js +1 -1
  52. package/src/oclif/hooks/getAppRegistrationFieldChoices.js +4 -4
  53. package/src/oclif/hooks/renderMarkdownHelp.js +1 -2
  54. package/src/oclif/hooks/versionInfo.js +2 -2
  55. package/src/utils/analytics.js +4 -4
  56. package/src/utils/api.js +26 -29
  57. package/src/utils/ast.js +112 -11
  58. package/src/utils/auth-files-codegen.js +102 -99
  59. package/src/utils/build.js +27 -28
  60. package/src/utils/changelog.js +1 -1
  61. package/src/utils/check-missing-app-info.js +2 -2
  62. package/src/utils/convert.js +26 -20
  63. package/src/utils/credentials.js +1 -1
  64. package/src/utils/display.js +31 -8
  65. package/src/utils/files.js +3 -3
  66. package/src/utils/ignore.js +2 -2
  67. package/src/utils/local.js +1 -1
  68. package/src/utils/metadata.js +1 -1
  69. package/src/utils/misc.js +21 -22
  70. package/src/utils/promisify.js +1 -1
  71. package/src/utils/scaffold.js +293 -40
  72. package/src/utils/team.js +3 -3
  73. package/src/utils/xdg.js +3 -3
@@ -1,13 +1,16 @@
1
+ /* eslint-disable camelcase */
2
+ // @ts-check
3
+
1
4
  const path = require('path');
5
+ const fs = require('fs');
2
6
 
3
- const { flags } = require('@oclif/command');
7
+ const { Args, Flags } = require('@oclif/core');
4
8
 
5
9
  const BaseCommand = require('../ZapierBaseCommand');
6
10
  const { buildFlags } = require('../buildFlags');
7
11
 
8
12
  const {
9
- createTemplateContext,
10
- getRelativeRequirePath,
13
+ createScaffoldingContext,
11
14
  plural,
12
15
  updateEntryFile,
13
16
  isValidEntryFileUpdate,
@@ -18,127 +21,90 @@ const { isValidAppInstall } = require('../../utils/misc');
18
21
  const { writeFile } = require('../../utils/files');
19
22
  const { ISSUES_URL } = require('../../constants');
20
23
 
21
- const getNewFileDirectory = (action, test = false) =>
22
- path.join(test ? 'test/' : '', plural(action));
23
-
24
- const getLocalFilePath = (directory, actionKey) =>
25
- path.join(directory, actionKey);
26
- /**
27
- * both the string to `require` and later, the filepath to write to
28
- */
29
- const getFullActionFilePath = (directory, actionKey) =>
30
- path.join(process.cwd(), getLocalFilePath(directory, actionKey));
31
-
32
- const getFullActionFilePathWithExtension = (directory, actionKey, isTest) =>
33
- `${getFullActionFilePath(directory, actionKey)}${isTest ? '.test' : ''}.js`;
34
-
35
24
  class ScaffoldCommand extends BaseCommand {
36
25
  async perform() {
37
26
  const { actionType, noun } = this.args;
38
-
39
- // TODO: interactive portion here?
27
+ const indexFileLocal = this.flags.entry ?? this.defaultIndexFileLocal();
40
28
  const {
41
- dest: newActionDir = getNewFileDirectory(actionType),
42
- testDest: newTestActionDir = getNewFileDirectory(actionType, true),
43
- entry = 'index.js',
29
+ dest: actionDirLocal = this.defaultActionDirLocal(indexFileLocal),
30
+ 'test-dest': testDirLocal = this.defaultTestDirLocal(indexFileLocal),
44
31
  force,
45
32
  } = this.flags;
46
33
 
47
- // this is possible, just extra work that's out of scope
48
- // const tsParser = j.withParser('ts')
49
- // tsParser(codeStr)
50
- // will have to change logic probably though
51
- if (entry.endsWith('ts')) {
52
- this.error(
53
- `Typescript isn't supported for scaffolding yet. Instead, try copying the example code at https://github.com/zapier/zapier-platform/blob/b8224ec9855be91c66c924b731199a068b1e913a/example-apps/typescript/src/resources/recipe.ts`
54
- );
55
- }
34
+ const language = indexFileLocal.endsWith('.ts') ? 'ts' : 'js';
56
35
 
57
- const shouldIncludeComments = !this.flags['no-help']; // when called from other commands (namely `init`) this will be false
58
- const templateContext = createTemplateContext(
36
+ const context = createScaffoldingContext({
59
37
  actionType,
60
38
  noun,
61
- shouldIncludeComments
62
- );
63
-
64
- const actionKey = templateContext.KEY;
39
+ language,
40
+ indexFileLocal,
41
+ actionDirLocal,
42
+ testDirLocal,
43
+ includeIntroComments: !this.flags['no-help'],
44
+ preventOverwrite: !force,
45
+ });
65
46
 
66
- const preventOverwrite = !force;
67
47
  // TODO: read from config file?
68
48
 
69
- this.startSpinner(
70
- `Creating new file: ${getLocalFilePath(newActionDir, actionKey)}.js`
71
- );
72
- await writeTemplateFile(
73
- actionType,
74
- templateContext,
75
- getFullActionFilePathWithExtension(newActionDir, actionKey),
76
- preventOverwrite
77
- );
49
+ this.startSpinner(`Creating new file: ${context.actionFileLocal}`);
50
+
51
+ await writeTemplateFile({
52
+ destinationPath: context.actionFileResolved,
53
+ templateType: context.actionType,
54
+ language: context.language,
55
+ preventOverwrite: context.preventOverwrite,
56
+ templateContext: context.templateContext,
57
+ });
78
58
  this.stopSpinner();
79
59
 
80
- this.startSpinner(
81
- `Creating new test file: ${getLocalFilePath(
82
- newTestActionDir,
83
- actionKey
84
- )}.js`
85
- );
86
- await writeTemplateFile(
87
- 'test',
88
- templateContext,
89
- getFullActionFilePathWithExtension(newTestActionDir, actionKey, true),
90
- preventOverwrite
91
- );
60
+ this.startSpinner(`Creating new test file: ${context.testFileLocal}`);
61
+ await writeTemplateFile({
62
+ destinationPath: context.testFileResolved,
63
+ templateType: 'test',
64
+ language: context.language,
65
+ preventOverwrite: context.preventOverwrite,
66
+ templateContext: context.templateContext,
67
+ });
92
68
  this.stopSpinner();
93
69
 
94
70
  // * rewire the index.js to point to the new file
95
- this.startSpinner(`Rewriting your ${entry}`);
96
-
97
- const entryFilePath = path.join(process.cwd(), entry);
71
+ this.startSpinner(`Rewriting your ${context.indexFileLocal}`);
98
72
 
99
- const originalContents = await updateEntryFile(
100
- entryFilePath,
101
- templateContext.VARIABLE,
102
- getFullActionFilePath(newActionDir, actionKey),
103
- actionType,
104
- templateContext.KEY
105
- );
73
+ const originalContents = await updateEntryFile({
74
+ language: context.language,
75
+ indexFileResolved: context.indexFileResolved,
76
+ actionRelativeImportPath: context.actionRelativeImportPath,
77
+ actionImportName: context.templateContext.VARIABLE,
78
+ actionType: context.actionType,
79
+ });
106
80
 
107
81
  if (isValidAppInstall().valid) {
108
82
  const success = isValidEntryFileUpdate(
109
- entryFilePath,
110
- actionType,
111
- templateContext.KEY
83
+ context.language,
84
+ context.indexFileResolved,
85
+ context.actionType,
86
+ context.templateContext.KEY,
112
87
  );
113
88
 
114
89
  this.stopSpinner({ success });
115
90
 
116
91
  if (!success) {
117
- const entryName = splitFileFromPath(entryFilePath)[1];
92
+ const entryName = splitFileFromPath(context.indexFileResolved)[1];
118
93
 
119
94
  this.startSpinner(
120
- `Unable to successfully rewrite your ${entryName}. Rolling back...`
95
+ `Unable to successfully rewrite your ${entryName}. Rolling back...`,
121
96
  );
122
- await writeFile(entryFilePath, originalContents);
97
+ await writeFile(context.indexFileResolved, originalContents);
123
98
  this.stopSpinner();
124
99
 
125
100
  this.error(
126
101
  [
127
- `\nPlease add the following lines to ${entryFilePath}:`,
128
- ` * \`const ${
129
- templateContext.VARIABLE
130
- } = require('./${getRelativeRequirePath(
131
- entryFilePath,
132
- getFullActionFilePath(newActionDir, actionKey)
133
- )}');\` at the top-level`,
134
- ` * \`[${templateContext.VARIABLE}.key]: ${
135
- templateContext.VARIABLE
136
- }\` in the "${plural(
137
- actionType
138
- )}" object in your exported integration definition.`,
102
+ `\nPlease add the following lines to ${context.indexFileResolved}:`,
103
+ ` * \`const ${context.templateContext.VARIABLE} = require('./${context.actionRelativeImportPath}');\` at the top-level`,
104
+ ` * \`[${context.templateContext.VARIABLE}.key]: ${context.templateContext.VARIABLE}\` in the "${context.actionTypePlural}" object in your exported integration definition.`,
139
105
  '',
140
- `Also, please file an issue at ${ISSUES_URL} with the contents of your ${entryFilePath}.`,
141
- ].join('\n')
106
+ `Also, please file an issue at ${ISSUES_URL} with the contents of your ${context.indexFileResolved}.`,
107
+ ].join('\n'),
142
108
  );
143
109
  }
144
110
  }
@@ -146,49 +112,89 @@ class ScaffoldCommand extends BaseCommand {
146
112
  this.stopSpinner();
147
113
 
148
114
  if (!this.flags.invokedFromAnotherCommand) {
149
- this.log(`\nAll done! Your new ${actionType} is ready to use.`);
115
+ this.log(`\nAll done! Your new ${context.actionType} is ready to use.`);
150
116
  }
151
117
  }
118
+
119
+ /**
120
+ * If `--entry` is not provided, this will determine the path to the
121
+ * root index file. Notably, we'll look for tsconfig.json and
122
+ * src/index.ts first, because even TS apps have a root level plain
123
+ * index.js that we should ignore.
124
+ *
125
+ * @returns {string}
126
+ */
127
+ defaultIndexFileLocal() {
128
+ const tsConfigPath = path.join(process.cwd(), 'tsconfig.json');
129
+ const srcIndexTsPath = path.join(process.cwd(), 'src', 'index.ts');
130
+ if (fs.existsSync(tsConfigPath) && fs.existsSync(srcIndexTsPath)) {
131
+ this.log('Automatically detected TypeScript project');
132
+ return 'src/index.ts';
133
+ }
134
+
135
+ return 'index.js';
136
+ }
137
+
138
+ /**
139
+ * If `--dest` is not provided, this will determine the directory for
140
+ * the new action file to be created in.
141
+ *
142
+ * @param {string} indexFileLocal - The path to the index file
143
+ * @returns {string}
144
+ */
145
+ defaultActionDirLocal(indexFileLocal) {
146
+ const parent = path.dirname(indexFileLocal);
147
+ return path.join(parent, plural(this.args.actionType));
148
+ }
149
+
150
+ /**
151
+ * If `--test-dest` is not provided, this will determine the directory
152
+ * for the new test file to be created in.
153
+ *
154
+ * @param {string} indexFileLocal - The path to the index file
155
+ * @returns {string}
156
+ */
157
+ defaultTestDirLocal(indexFileLocal) {
158
+ const parent = path.dirname(indexFileLocal);
159
+ return path.join(parent, 'test', plural(this.args.actionType));
160
+ }
152
161
  }
153
162
 
154
- ScaffoldCommand.args = [
155
- {
156
- name: 'actionType',
163
+ ScaffoldCommand.args = {
164
+ actionType: Args.string({
157
165
  help: 'What type of step type are you creating?',
158
166
  required: true,
159
167
  options: ['trigger', 'search', 'create', 'resource'],
160
- },
161
- {
162
- name: 'noun',
168
+ }),
169
+ noun: Args.string({
163
170
  help: 'What sort of object this action acts on. For example, the name of the new thing to create',
164
171
  required: true,
165
- },
166
- ];
172
+ }),
173
+ };
167
174
 
168
175
  ScaffoldCommand.flags = buildFlags({
169
176
  commandFlags: {
170
- dest: flags.string({
177
+ dest: Flags.string({
171
178
  char: 'd',
172
179
  description:
173
180
  "Specify the new file's directory. Use this flag when you want to create a different folder structure such as `src/triggers` instead of the default `triggers`. Defaults to `[triggers|searches|creates]/{noun}`.",
174
181
  }),
175
- 'test-dest': flags.string({
182
+ 'test-dest': Flags.string({
176
183
  description:
177
184
  "Specify the new test file's directory. Use this flag when you want to create a different folder structure such as `src/triggers` instead of the default `triggers`. Defaults to `test/[triggers|searches|creates]/{noun}`.",
178
185
  }),
179
- entry: flags.string({
186
+ entry: Flags.string({
180
187
  char: 'e',
181
188
  description:
182
- "Supply the path to your integration's root (`index.js`). Only needed if your `index.js` is in a subfolder, like `src`.",
183
- default: 'index.js',
189
+ "Supply the path to your integration's entry point (`index.js` or `src/index.ts`). This will try to automatically detect the correct file if not provided.",
184
190
  }),
185
- force: flags.boolean({
191
+ force: Flags.boolean({
186
192
  char: 'f',
187
193
  description:
188
- 'Should we overwrite an exisiting trigger/search/create file?',
194
+ 'Should we overwrite an existing trigger/search/create file?',
189
195
  default: false,
190
196
  }),
191
- 'no-help': flags.boolean({
197
+ 'no-help': Flags.boolean({
192
198
  description:
193
199
  "When scaffolding, should we skip adding helpful intro comments? Useful if this isn't your first rodeo.",
194
200
  default: false,
@@ -1,5 +1,5 @@
1
1
  const ZapierBaseCommand = require('../../ZapierBaseCommand');
2
- // const { flags } = require('@oclif/command');
2
+ const { Args } = require('@oclif/core');
3
3
  const { cyan } = require('colors/safe');
4
4
  const { buildFlags } = require('../../buildFlags');
5
5
  const { callAPI } = require('../../../utils/api');
@@ -29,7 +29,7 @@ class TeamAddCommand extends ZapierBaseCommand {
29
29
  `About to invite ${cyan(this.args.email)} to as a team member at the ${
30
30
  this.args.role
31
31
  } level. An email will be sent with the following message:\n\n"${message}"\n\nIs that ok?`,
32
- true
32
+ true,
33
33
  ))
34
34
  ) {
35
35
  this.log('\ncancelled');
@@ -42,8 +42,8 @@ class TeamAddCommand extends ZapierBaseCommand {
42
42
  role === 'admin'
43
43
  ? `/apps/${id}/collaborators`
44
44
  : role === 'subscriber'
45
- ? `${BASE_ENDPOINT}/api/platform/v3/integrations/${id}/subscribers`
46
- : `/apps/${id}/limited_collaborators`;
45
+ ? `${BASE_ENDPOINT}/api/platform/v3/integrations/${id}/subscribers`
46
+ : `/apps/${id}/limited_collaborators`;
47
47
 
48
48
  await callAPI(url, {
49
49
  url: url.startsWith('http') ? url : undefined,
@@ -54,26 +54,23 @@ class TeamAddCommand extends ZapierBaseCommand {
54
54
  }
55
55
  }
56
56
 
57
- TeamAddCommand.args = [
58
- {
59
- name: 'email',
57
+ TeamAddCommand.args = {
58
+ email: Args.string({
60
59
  description:
61
60
  "The user to be invited. If they don't have a Zapier account, they'll be prompted to create one.",
62
61
  required: true,
63
- },
64
- {
65
- name: 'role',
62
+ }),
63
+ role: Args.string({
66
64
  description:
67
65
  'The level the invited team member should be at. Admins can edit everything and get email updates. Collaborators have read-access to the app and get email updates. Subscribers only get email updates.',
68
66
  options: ['admin', 'collaborator', 'subscriber'],
69
67
  required: true,
70
- },
71
- {
72
- name: 'message',
68
+ }),
69
+ message: Args.string({
73
70
  description:
74
71
  'A message sent in the email to your team member, if you need to provide context. Wrap the message in quotes to ensure spaces get saved.',
75
- },
76
- ];
72
+ }),
73
+ };
77
74
  TeamAddCommand.flags = buildFlags();
78
75
  TeamAddCommand.description = `Add a team member to your integration.
79
76
 
@@ -34,8 +34,8 @@ class TeamListCommand extends ZapierBaseCommand {
34
34
 
35
35
  this.log(
36
36
  `To invite more team members, use the \`${cyan(
37
- 'zapier team:add'
38
- )}\` command.`
37
+ 'zapier team:add',
38
+ )}\` command.`,
39
39
  );
40
40
  }
41
41
  }
@@ -17,7 +17,7 @@ class TeamRemoveCommand extends ZapierBaseCommand {
17
17
  value: { id, email, role: transformUserRole(role) },
18
18
  name: `${email} (${transformUserRole(role)})`,
19
19
  short: email,
20
- })
20
+ }),
21
21
  );
22
22
 
23
23
  this.stopSpinner();
@@ -28,15 +28,15 @@ class TeamRemoveCommand extends ZapierBaseCommand {
28
28
  id: invitationId,
29
29
  } = await this.promptWithList(
30
30
  'Which team member do you want to remove?',
31
- choices
31
+ choices,
32
32
  );
33
33
  this.log();
34
34
  if (
35
35
  !(await this.confirm(
36
36
  `About to revoke ${cyan(role)}-level access from ${cyan(
37
- email
37
+ email,
38
38
  )}. Are you sure?`,
39
- true
39
+ true,
40
40
  ))
41
41
  ) {
42
42
  this.log('\ncancelled');
@@ -49,8 +49,8 @@ class TeamRemoveCommand extends ZapierBaseCommand {
49
49
  role === 'admin'
50
50
  ? `/apps/${appId}/collaborators/${invitationId}`
51
51
  : role === 'subscriber'
52
- ? `${BASE_ENDPOINT}/api/platform/v3/integrations/${appId}/subscribers/${invitationId}`
53
- : `/apps/${appId}/limited_collaborators`;
52
+ ? `${BASE_ENDPOINT}/api/platform/v3/integrations/${appId}/subscribers/${invitationId}`
53
+ : `/apps/${appId}/limited_collaborators`;
54
54
 
55
55
  await callAPI(url, {
56
56
  url: url.startsWith('http') ? url : undefined,
@@ -1,4 +1,4 @@
1
- const { flags } = require('@oclif/command');
1
+ const { Flags } = require('@oclif/core');
2
2
  const chalk = require('chalk');
3
3
 
4
4
  const BaseCommand = require('../ZapierBaseCommand');
@@ -27,7 +27,7 @@ class TestCommand extends BaseCommand {
27
27
  const credentials = await readCredentials(false);
28
28
  if (credentials.deployKey) {
29
29
  this.log(
30
- `Adding ${constants.AUTH_LOCATION} to environment as ZAPIER_DEPLOY_KEY...`
30
+ `Adding ${constants.AUTH_LOCATION} to environment as ZAPIER_DEPLOY_KEY...`,
31
31
  );
32
32
  extraEnv.ZAPIER_DEPLOY_KEY = credentials.deployKey;
33
33
  }
@@ -53,10 +53,10 @@ class TestCommand extends BaseCommand {
53
53
  // but the space-joined array made that unclear
54
54
  this.log(
55
55
  `\n ${chalk.cyanBright.bold(
56
- packageManager.executable
56
+ packageManager.executable,
57
57
  )} ${chalk.cyanBright(
58
- argv.map((a) => (a.includes(' ') ? `"${a}"` : a)).join(' ')
59
- )}\n`
58
+ argv.map((a) => (a.includes(' ') ? `"${a}"` : a)).join(' '),
59
+ )}\n`,
60
60
  );
61
61
 
62
62
  const output = await runCommand(packageManager.executable, argv, {
@@ -71,15 +71,15 @@ class TestCommand extends BaseCommand {
71
71
 
72
72
  TestCommand.flags = buildFlags({
73
73
  commandFlags: {
74
- 'skip-validate': flags.boolean({
74
+ 'skip-validate': Flags.boolean({
75
75
  description:
76
76
  "Forgo running `zapier validate` before tests are run. This will speed up tests if you're modifying functionality of an existing integration rather than adding new actions.",
77
77
  }),
78
- yarn: flags.boolean({
78
+ yarn: Flags.boolean({
79
79
  description:
80
80
  "Use `yarn` instead of `npm`. This happens automatically if there's a `yarn.lock` file, but you can manually force `yarn` if you run tests from a sub-directory.",
81
81
  }),
82
- pnpm: flags.boolean({
82
+ pnpm: Flags.boolean({
83
83
  description:
84
84
  "Use `pnpm` instead of `npm`. This happens automatically if there's a `pnpm-lock.yaml` file, but you can manually force `pnpm` if you run tests from a sub-directory.",
85
85
  }),
@@ -10,7 +10,7 @@ class UploadCommand extends BaseCommand {
10
10
  // it would be cool if we differentiated between new/updated here
11
11
  await buildAndOrUpload({ upload: true });
12
12
  this.log(
13
- `\nUpload complete! Uploaded ${BUILD_PATH} and ${SOURCE_PATH} to Zapier. If it's a new version, it should now be available in the Zap editor.`
13
+ `\nUpload complete! Uploaded ${BUILD_PATH} and ${SOURCE_PATH} to Zapier. If it's a new version, it should now be available in the Zap editor.`,
14
14
  );
15
15
  }
16
16
  }
@@ -1,5 +1,5 @@
1
1
  const ZapierBaseCommand = require('../../ZapierBaseCommand');
2
- const { flags } = require('@oclif/command');
2
+ const { Args, Flags } = require('@oclif/core');
3
3
  const { cyan } = require('colors/safe');
4
4
  const { buildFlags } = require('../../buildFlags');
5
5
  const { callAPI } = require('../../../utils/api');
@@ -12,7 +12,7 @@ class UsersAddCommand extends ZapierBaseCommand {
12
12
  `About to invite ${cyan(this.args.email)} to ${
13
13
  this.args.version ? `version ${this.args.version}` : 'all versions'
14
14
  } of your integration. An invite email will be sent. Is that ok?`,
15
- true
15
+ true,
16
16
  ))
17
17
  ) {
18
18
  this.log('\ncancelled');
@@ -29,22 +29,20 @@ class UsersAddCommand extends ZapierBaseCommand {
29
29
  }
30
30
  }
31
31
 
32
- UsersAddCommand.args = [
33
- {
34
- name: 'email',
32
+ UsersAddCommand.args = {
33
+ email: Args.string({
35
34
  description:
36
35
  "The user to be invited. If they don't have a Zapier account, they'll be prompted to create one.",
37
36
  required: true,
38
- },
39
- {
40
- name: 'version',
37
+ }),
38
+ version: Args.string({
41
39
  description:
42
40
  'A version string (like 1.2.3). Optional, used only if you want to invite a user to a specific version instead of all versions.',
43
- },
44
- ];
41
+ }),
42
+ };
45
43
  UsersAddCommand.flags = buildFlags({
46
44
  commandFlags: {
47
- force: flags.boolean({
45
+ force: Flags.boolean({
48
46
  char: 'f',
49
47
  description: 'Skip confirmation. Useful for running programatically.',
50
48
  }),
@@ -17,8 +17,8 @@ class UsersListCommand extends ZapierBaseCommand {
17
17
 
18
18
  this.log(
19
19
  `\n${yellow(
20
- 'Note'
21
- )} that this list of users is NOT a comprehensive list of everyone who is using your integration. It only includes users who were invited directly by email (using the \`users:add EMAIL\` command or the web UI).\n`
20
+ 'Note',
21
+ )} that this list of users is NOT a comprehensive list of everyone who is using your integration. It only includes users who were invited directly by email (using the \`users:add EMAIL\` command or the web UI).\n`,
22
22
  );
23
23
 
24
24
  this.logTable({
@@ -33,10 +33,10 @@ class UsersListCommand extends ZapierBaseCommand {
33
33
 
34
34
  this.log(
35
35
  `\nTo invite users via a link, use the \`${cyan(
36
- 'zapier users:links'
36
+ 'zapier users:links',
37
37
  )}\` command. To invite a specific user by email, use the \`${cyan(
38
- 'zapier users:add'
39
- )}\` command.`
38
+ 'zapier users:add',
39
+ )}\` command.`,
40
40
  );
41
41
  }
42
42
  }
@@ -45,9 +45,9 @@ UsersListCommand.flags = buildFlags({ opts: { format: true } });
45
45
  UsersListCommand.description = `Get a list of users who have been invited to your integration.
46
46
 
47
47
  Note that this list of users is NOT a comprehensive list of everyone who is using your integration. It only includes users who were invited directly by email (using the \`${cyan(
48
- 'zapier users:add'
48
+ 'zapier users:add',
49
49
  )}\` command or the web UI). Users who joined by clicking links generated using the \`${cyan(
50
- 'zapier user:links'
50
+ 'zapier user:links',
51
51
  )}\` command won't show up here.`;
52
52
  UsersListCommand.aliases = ['users:list'];
53
53
  UsersListCommand.skipValidInstallCheck = true;
@@ -13,13 +13,13 @@ class UsersLinksCommand extends ZapierBaseCommand {
13
13
 
14
14
  this.log(
15
15
  `\nYou can invite users to ${bold(
16
- 'all'
17
- )} versions of your integration using the following link:`
16
+ 'all',
17
+ )} versions of your integration using the following link:`,
18
18
  );
19
19
  this.log(`\n${cyan(inviteUrl)}\n`);
20
20
 
21
21
  this.log(
22
- 'You can invite users to a specific integration version using the following links:'
22
+ 'You can invite users to a specific integration version using the following links:',
23
23
  );
24
24
  this.logTable({
25
25
  rows: Object.entries(versionInviteUrls).map(([version, url]) => ({
@@ -33,7 +33,7 @@ class UsersLinksCommand extends ZapierBaseCommand {
33
33
  });
34
34
 
35
35
  this.log(
36
- '\nTo invite a specific user by email, use the `zapier users:add` command.'
36
+ '\nTo invite a specific user by email, use the `zapier users:add` command.',
37
37
  );
38
38
  }
39
39
  }
@@ -1,5 +1,5 @@
1
1
  const ZapierBaseCommand = require('../../ZapierBaseCommand');
2
- const { flags } = require('@oclif/command');
2
+ const { Args, Flags } = require('@oclif/core');
3
3
  const { cyan } = require('colors/safe');
4
4
  const { buildFlags } = require('../../buildFlags');
5
5
  const { callAPI } = require('../../../utils/api');
@@ -10,9 +10,9 @@ class UsersRemoveCommand extends ZapierBaseCommand {
10
10
  !this.flags.force &&
11
11
  !(await this.confirm(
12
12
  `About to revoke access to ${cyan(
13
- this.args.email
13
+ this.args.email,
14
14
  )}. They won't be able to see your app in the editor and their Zaps will stop working. Are you sure?`,
15
- true
15
+ true,
16
16
  ))
17
17
  ) {
18
18
  this.log('\ncancelled');
@@ -27,16 +27,15 @@ class UsersRemoveCommand extends ZapierBaseCommand {
27
27
  }
28
28
  }
29
29
 
30
- UsersRemoveCommand.args = [
31
- {
32
- name: 'email',
30
+ UsersRemoveCommand.args = {
31
+ email: Args.string({
33
32
  description: 'The user to be removed.',
34
33
  required: true,
35
- },
36
- ];
34
+ }),
35
+ };
37
36
  UsersRemoveCommand.flags = buildFlags({
38
37
  commandFlags: {
39
- force: flags.boolean({
38
+ force: Flags.boolean({
40
39
  char: 'f',
41
40
  description: 'Skips confirmation. Useful for running programatically.',
42
41
  }),