@cakemail-org/cakemail-cli 1.7.0 → 2.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 (198) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +41 -37
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/client.js +1 -1
  9. package/dist/client.js.map +1 -1
  10. package/dist/commands/account.js +1 -1
  11. package/dist/commands/account.js.map +1 -1
  12. package/dist/commands/attributes.js +1 -1
  13. package/dist/commands/attributes.js.map +1 -1
  14. package/dist/commands/campaigns.js +1 -1
  15. package/dist/commands/campaigns.js.map +1 -1
  16. package/dist/commands/contacts.js +1 -1
  17. package/dist/commands/contacts.js.map +1 -1
  18. package/dist/commands/emails.js +1 -1
  19. package/dist/commands/emails.js.map +1 -1
  20. package/dist/commands/interests.js +1 -1
  21. package/dist/commands/interests.js.map +1 -1
  22. package/dist/commands/lists.js +1 -1
  23. package/dist/commands/lists.js.map +1 -1
  24. package/dist/commands/logs.js +1 -1
  25. package/dist/commands/logs.js.map +1 -1
  26. package/dist/commands/reports.js +1 -1
  27. package/dist/commands/reports.js.map +1 -1
  28. package/dist/commands/segments.js +1 -1
  29. package/dist/commands/segments.js.map +1 -1
  30. package/dist/commands/senders.js +1 -1
  31. package/dist/commands/senders.js.map +1 -1
  32. package/dist/commands/suppressed.js +1 -1
  33. package/dist/commands/suppressed.js.map +1 -1
  34. package/dist/commands/tags.js +1 -1
  35. package/dist/commands/tags.js.map +1 -1
  36. package/dist/commands/templates.js +1 -1
  37. package/dist/commands/templates.js.map +1 -1
  38. package/dist/commands/transactional-templates.js +1 -1
  39. package/dist/commands/transactional-templates.js.map +1 -1
  40. package/dist/commands/webhooks.js +1 -1
  41. package/dist/commands/webhooks.js.map +1 -1
  42. package/dist/utils/config.js +2 -2
  43. package/dist/utils/config.js.map +1 -1
  44. package/dist/utils/errors.js +1 -1
  45. package/dist/utils/errors.js.map +1 -1
  46. package/dist/utils/progress.d.ts.map +1 -1
  47. package/dist/utils/progress.js +32 -4
  48. package/dist/utils/progress.js.map +1 -1
  49. package/dist/utils/spinner.d.ts +17 -0
  50. package/dist/utils/spinner.d.ts.map +1 -0
  51. package/dist/utils/spinner.js +43 -0
  52. package/dist/utils/spinner.js.map +1 -0
  53. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  54. package/docs/README.md +161 -0
  55. package/docs/developer/ARCHITECTURE.md +516 -0
  56. package/docs/developer/AUTH.md +204 -0
  57. package/docs/developer/CONTRIBUTING.md +227 -0
  58. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  59. package/docs/developer/PROJECT_INDEX.md +365 -0
  60. package/docs/planning/API_COVERAGE.md +1045 -0
  61. package/docs/planning/BACKLOG.md +1159 -0
  62. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  63. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  64. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  65. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  66. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  67. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  68. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  69. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  70. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  71. package/docs/user-manual/.obsidian/app.json +1 -0
  72. package/docs/user-manual/.obsidian/appearance.json +1 -0
  73. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  74. package/docs/user-manual/.obsidian/workspace.json +167 -0
  75. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  76. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  77. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  78. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  79. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  80. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  81. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  82. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  83. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  84. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  85. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  86. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  87. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  88. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  89. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  90. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  91. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  92. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  93. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  94. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  95. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  96. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  97. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  98. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  99. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  100. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  101. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  102. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  103. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  104. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  105. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  106. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  107. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  108. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  109. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  110. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  111. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  112. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  113. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  114. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  115. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  116. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  117. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  118. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  119. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  120. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  121. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  122. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  123. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  124. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  125. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  126. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  127. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  128. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  129. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  130. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  131. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  132. package/docs/user-manual/README.md +0 -0
  133. package/package.json +13 -61
  134. package/src/cli.ts +125 -0
  135. package/src/client.ts +16 -0
  136. package/src/commands/account.ts +267 -0
  137. package/src/commands/accounts.ts +78 -0
  138. package/src/commands/actions.ts +249 -0
  139. package/src/commands/attributes.ts +139 -0
  140. package/src/commands/campaign-blueprints.ts +106 -0
  141. package/src/commands/campaigns.ts +469 -0
  142. package/src/commands/config.ts +77 -0
  143. package/src/commands/contacts.ts +612 -0
  144. package/src/commands/custom-attributes.ts +127 -0
  145. package/src/commands/dkims.ts +117 -0
  146. package/src/commands/domains.ts +82 -0
  147. package/src/commands/email-apis.ts +569 -0
  148. package/src/commands/emails.ts +197 -0
  149. package/src/commands/forms.ts +283 -0
  150. package/src/commands/interests.ts +155 -0
  151. package/src/commands/links.ts +38 -0
  152. package/src/commands/lists.ts +406 -0
  153. package/src/commands/logos.ts +71 -0
  154. package/src/commands/logs.ts +386 -0
  155. package/src/commands/reports.ts +306 -0
  156. package/src/commands/segments.ts +158 -0
  157. package/src/commands/senders.ts +204 -0
  158. package/src/commands/sub-accounts.ts +271 -0
  159. package/src/commands/suppressed-emails.ts +234 -0
  160. package/src/commands/suppressed.ts +198 -0
  161. package/src/commands/system-emails.ts +85 -0
  162. package/src/commands/tags.ts +146 -0
  163. package/src/commands/tasks.ts +116 -0
  164. package/src/commands/templates.ts +189 -0
  165. package/src/commands/tokens.ts +83 -0
  166. package/src/commands/transactional-emails.ts +374 -0
  167. package/src/commands/transactional-templates.ts +385 -0
  168. package/src/commands/users.ts +506 -0
  169. package/src/commands/webhooks.ts +172 -0
  170. package/src/commands/workflow-blueprints.ts +123 -0
  171. package/src/commands/workflows.ts +265 -0
  172. package/src/types/profile.ts +93 -0
  173. package/src/utils/auth.ts +272 -0
  174. package/src/utils/config-file.ts +96 -0
  175. package/src/utils/config.ts +134 -0
  176. package/src/utils/confirm.ts +32 -0
  177. package/src/utils/defaults.ts +99 -0
  178. package/src/utils/errors.ts +116 -0
  179. package/src/utils/interactive.ts +91 -0
  180. package/src/utils/list-defaults.ts +74 -0
  181. package/src/utils/output.ts +190 -0
  182. package/src/utils/progress.ts +320 -0
  183. package/src/utils/spinner.ts +22 -0
  184. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  185. package/tests/PTY_SETUP.md +118 -0
  186. package/tests/PTY_TESTING_GUIDE.md +507 -0
  187. package/tests/README.md +244 -0
  188. package/tests/fixtures/api-responses/campaigns.json +34 -0
  189. package/tests/fixtures/test-config.json +13 -0
  190. package/tests/helpers/cli-runner.ts +128 -0
  191. package/tests/helpers/mock-server.ts +301 -0
  192. package/tests/helpers/pty-runner.ts +181 -0
  193. package/tests/integration/campaigns-real-api.test.ts +196 -0
  194. package/tests/integration/setup-integration.ts +50 -0
  195. package/tests/pty/campaigns.test.ts +241 -0
  196. package/tests/setup.ts +34 -0
  197. package/tsconfig.json +15 -0
  198. package/vitest.config.ts +28 -0
@@ -0,0 +1,116 @@
1
+ // ABOUTME: CLI commands for Task.
2
+ // ABOUTME: Generated by api-kit from the OpenAPI spec.
3
+
4
+ import { Command } from 'commander';
5
+ import { createSpinner } from '../utils/spinner.js';
6
+ import { confirmDelete } from '../utils/confirm.js';
7
+
8
+ export function createTasksCommand(
9
+ client: any,
10
+ formatter: any
11
+ ): Command {
12
+ const cmd = new Command('tasks')
13
+ .description('Monitor asynchronous background tasks such as exports and imports. Tasks track the progress and status of long-running operations.');
14
+
15
+
16
+ cmd
17
+ .command('list')
18
+ .description('Show all asynchronous Tasks')
19
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
20
+ .option('--page <value>', 'page')
21
+ .option('--per-page <value>', 'per_page')
22
+ .option('--with-count <value>', 'Include count in the response')
23
+ .option('--sort <value>', 'Sort term and direction, using syntax `[-|+]term`.
24
+
25
+ Valid terms:
26
+ - `status`
27
+ - `created_on`
28
+ - `expires_on`')
29
+ .option('--filter <value>', 'Valid Terms:
30
+ - `type`
31
+ - `status`
32
+ - `list_id`
33
+ - `progress`
34
+
35
+ Valid Operators:
36
+ - `==`
37
+
38
+ Query separator:
39
+ - `;`')
40
+ .action(async (options) => {
41
+ const spinner = createSpinner('Fetching task...').start();
42
+ try {
43
+ const data = await client.listTasks({
44
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
45
+ page: options.page != null ? Number(options.page) : undefined,
46
+ perPage: options.perPage != null ? Number(options.perPage) : undefined,
47
+ withCount: options.withCount,
48
+ sort: options.sort,
49
+ filter: options.filter,
50
+ });
51
+
52
+ spinner.stop();
53
+ formatter.output(data);
54
+ } catch (error: any) {
55
+ spinner.stop();
56
+ formatter.error(error.message);
57
+ process.exit(1);
58
+ }
59
+ });
60
+
61
+
62
+ cmd
63
+ .command('get <task-id>')
64
+ .description('Show an asynchronous Task')
65
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
66
+ .action(async (task_id, options) => {
67
+ const spinner = createSpinner('Fetching task...').start();
68
+ try {
69
+ const data = await client.getTask({
70
+ task_id,
71
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
72
+ });
73
+
74
+ spinner.stop();
75
+ formatter.output(data);
76
+ } catch (error: any) {
77
+ spinner.stop();
78
+ formatter.error(error.message);
79
+ process.exit(1);
80
+ }
81
+ });
82
+
83
+
84
+ cmd
85
+ .command('delete <task-id>')
86
+ .description('Delete an asynchronous Task')
87
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
88
+ .option('-f, --force', 'Skip confirmation prompt')
89
+ .action(async (task_id, options) => {
90
+ if (!options.force) {
91
+ const confirmed = await confirmDelete('task', task_id);
92
+ if (!confirmed) {
93
+ formatter.info('Deletion cancelled');
94
+ return;
95
+ }
96
+ }
97
+
98
+ const spinner = createSpinner('Deleting task...').start();
99
+ try {
100
+ const data = await client.deleteTask({
101
+ task_id,
102
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
103
+ });
104
+
105
+ spinner.stop();
106
+ formatter.success('Task deleted successfully');
107
+ } catch (error: any) {
108
+ spinner.stop();
109
+ formatter.error(error.message);
110
+ process.exit(1);
111
+ }
112
+ });
113
+
114
+
115
+ return cmd;
116
+ }
@@ -0,0 +1,189 @@
1
+ // ABOUTME: CLI commands for Template.
2
+ // ABOUTME: Generated by api-kit from the OpenAPI spec.
3
+
4
+ import { Command } from 'commander';
5
+ import { createSpinner } from '../utils/spinner.js';
6
+ import { confirmDelete } from '../utils/confirm.js';
7
+
8
+ export function createTemplatesCommand(
9
+ client: any,
10
+ formatter: any
11
+ ): Command {
12
+ const cmd = new Command('templates')
13
+ .description('Create and manage reusable email templates. Templates contain the HTML/text content and subject line that can be reused across multiple campaigns. Templates support custom attributes, tags, and can be rendered to preview the final output.');
14
+
15
+
16
+ cmd
17
+ .command('list')
18
+ .description('Show all templates')
19
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
20
+ .option('--page <value>', 'page')
21
+ .option('--per-page <value>', 'per_page')
22
+ .option('--with-count <value>', 'Include count in the response')
23
+ .option('--filter <value>', 'Valid Terms:
24
+ - `tag`
25
+ - `not_tag`
26
+ - `name`
27
+ - `is_owner`
28
+ - `is_not_owner`
29
+
30
+ Valid Operators:
31
+ - `==`
32
+
33
+ Query separator:
34
+ - `;`')
35
+ .option('--sort <value>', 'Sort term and direction, using syntax `[-|+]term`.
36
+
37
+ Valid terms:
38
+ - `id`
39
+ - `created_on`
40
+ - `updated_on`
41
+ - `name`')
42
+ .action(async (options) => {
43
+ const spinner = createSpinner('Fetching template...').start();
44
+ try {
45
+ const data = await client.listTemplates({
46
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
47
+ page: options.page != null ? Number(options.page) : undefined,
48
+ perPage: options.perPage != null ? Number(options.perPage) : undefined,
49
+ withCount: options.withCount,
50
+ filter: options.filter,
51
+ sort: options.sort,
52
+ });
53
+
54
+ spinner.stop();
55
+ formatter.output(data);
56
+ } catch (error: any) {
57
+ spinner.stop();
58
+ formatter.error(error.message);
59
+ process.exit(1);
60
+ }
61
+ });
62
+
63
+
64
+ cmd
65
+ .command('create')
66
+ .description('Create a template')
67
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
68
+ .requiredOption('--data <value>', 'Request body as JSON string')
69
+ .action(async (options) => {
70
+ const spinner = createSpinner('Creating template...').start();
71
+ try {
72
+ const body = JSON.parse(options.data);
73
+ const data = await client.createTemplate({
74
+ ...body,
75
+ });
76
+
77
+ spinner.stop();
78
+ formatter.success('Template created successfully');
79
+ formatter.output(data);
80
+ } catch (error: any) {
81
+ spinner.stop();
82
+ formatter.error(error.message);
83
+ process.exit(1);
84
+ }
85
+ });
86
+
87
+
88
+ cmd
89
+ .command('get <template-id>')
90
+ .description('Get a template')
91
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
92
+ .action(async (template_id, options) => {
93
+ const spinner = createSpinner('Fetching template...').start();
94
+ try {
95
+ const data = await client.getTemplate({
96
+ template_id: Number(template_id),
97
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
98
+ });
99
+
100
+ spinner.stop();
101
+ formatter.output(data);
102
+ } catch (error: any) {
103
+ spinner.stop();
104
+ formatter.error(error.message);
105
+ process.exit(1);
106
+ }
107
+ });
108
+
109
+
110
+ cmd
111
+ .command('patch <template-id>')
112
+ .description('Update a template')
113
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
114
+ .requiredOption('--data <value>', 'Request body as JSON string')
115
+ .action(async (template_id, options) => {
116
+ const spinner = createSpinner('Updating template...').start();
117
+ try {
118
+ const body = JSON.parse(options.data);
119
+ const data = await client.patchTemplate({
120
+ template_id: Number(template_id),
121
+ ...body,
122
+ });
123
+
124
+ spinner.stop();
125
+ formatter.success('Template updated successfully');
126
+ formatter.output(data);
127
+ } catch (error: any) {
128
+ spinner.stop();
129
+ formatter.error(error.message);
130
+ process.exit(1);
131
+ }
132
+ });
133
+
134
+
135
+ cmd
136
+ .command('delete <template-id>')
137
+ .description('Delete a template')
138
+ .option('--account-id <value>', 'Optional Account ID to be used for the request')
139
+ .option('-f, --force', 'Skip confirmation prompt')
140
+ .action(async (template_id, options) => {
141
+ if (!options.force) {
142
+ const confirmed = await confirmDelete('template', template_id);
143
+ if (!confirmed) {
144
+ formatter.info('Deletion cancelled');
145
+ return;
146
+ }
147
+ }
148
+
149
+ const spinner = createSpinner('Deleting template...').start();
150
+ try {
151
+ const data = await client.deleteTemplate({
152
+ template_id: Number(template_id),
153
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
154
+ });
155
+
156
+ spinner.stop();
157
+ formatter.success('Template deleted successfully');
158
+ } catch (error: any) {
159
+ spinner.stop();
160
+ formatter.error(error.message);
161
+ process.exit(1);
162
+ }
163
+ });
164
+
165
+
166
+ cmd
167
+ .command('render <template-id>')
168
+ .description('Render a template')
169
+ .option('--account-id <value>', 'account_id')
170
+ .action(async (template_id, options) => {
171
+ const spinner = createSpinner('Fetching template...').start();
172
+ try {
173
+ const data = await client.renderTemplate({
174
+ template_id: Number(template_id),
175
+ accountId: options.accountId != null ? Number(options.accountId) : undefined,
176
+ });
177
+
178
+ spinner.stop();
179
+ formatter.output(data);
180
+ } catch (error: any) {
181
+ spinner.stop();
182
+ formatter.error(error.message);
183
+ process.exit(1);
184
+ }
185
+ });
186
+
187
+
188
+ return cmd;
189
+ }
@@ -0,0 +1,83 @@
1
+ // ABOUTME: CLI commands for Token.
2
+ // ABOUTME: Generated by api-kit from the OpenAPI spec.
3
+
4
+ import { Command } from 'commander';
5
+ import { createSpinner } from '../utils/spinner.js';
6
+
7
+ export function createTokensCommand(
8
+ client: any,
9
+ formatter: any
10
+ ): Command {
11
+ const cmd = new Command('tokens')
12
+ .description('Authentication and token management. The API uses OAuth 2.0 Resource Owner Password Credentials grant. Use these endpoints to obtain access and refresh tokens, refresh expired tokens, and complete multi-factor authentication challenges.');
13
+
14
+
15
+ cmd
16
+ .command('create')
17
+ .description('Create or Refresh a token')
18
+ .option('--version <value>', 'version')
19
+ .action(async (options) => {
20
+ const spinner = createSpinner('Creating token...').start();
21
+ try {
22
+ const data = await client.createToken({
23
+ version: options.version,
24
+ });
25
+
26
+ spinner.stop();
27
+ formatter.success('Token created successfully');
28
+ formatter.output(data);
29
+ } catch (error: any) {
30
+ spinner.stop();
31
+ formatter.error(error.message);
32
+ process.exit(1);
33
+ }
34
+ });
35
+
36
+
37
+ cmd
38
+ .command('refresh')
39
+ .description('Refresh a token')
40
+ .option('--version <value>', 'version')
41
+ .action(async (options) => {
42
+ const spinner = createSpinner('Updating token...').start();
43
+ try {
44
+ const data = await client.refreshToken({
45
+ version: options.version,
46
+ });
47
+
48
+ spinner.stop();
49
+ formatter.success('Token updated successfully');
50
+ formatter.output(data);
51
+ } catch (error: any) {
52
+ spinner.stop();
53
+ formatter.error(error.message);
54
+ process.exit(1);
55
+ }
56
+ });
57
+
58
+
59
+ cmd
60
+ .command('create-token-from-challenge')
61
+ .description('Complete a Multi-Factor Authentication challenge')
62
+ .requiredOption('--data <value>', 'Request body as JSON string')
63
+ .action(async (options) => {
64
+ const spinner = createSpinner('Creating token...').start();
65
+ try {
66
+ const body = JSON.parse(options.data);
67
+ const data = await client.createTokenFromChallenge({
68
+ ...body,
69
+ });
70
+
71
+ spinner.stop();
72
+ formatter.success('Token created successfully');
73
+ formatter.output(data);
74
+ } catch (error: any) {
75
+ spinner.stop();
76
+ formatter.error(error.message);
77
+ process.exit(1);
78
+ }
79
+ });
80
+
81
+
82
+ return cmd;
83
+ }