@cakemail-org/cakemail-cli 1.5.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.
- package/.claude/settings.local.json +12 -0
- package/.env.example +40 -0
- package/.env.test.example +45 -0
- package/CHANGELOG.md +1031 -0
- package/README.md +319 -15
- package/audit-formats.js +128 -0
- package/cakemail.rb +20 -0
- package/dist/cli.js +27 -10
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -6
- package/dist/client.js.map +1 -1
- package/dist/commands/account.js +1 -1
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/attributes.js +1 -1
- package/dist/commands/attributes.js.map +1 -1
- package/dist/commands/campaigns.d.ts.map +1 -1
- package/dist/commands/campaigns.js +103 -8
- package/dist/commands/campaigns.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +63 -4
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contacts.d.ts.map +1 -1
- package/dist/commands/contacts.js +91 -12
- package/dist/commands/contacts.js.map +1 -1
- package/dist/commands/emails.js +1 -1
- package/dist/commands/emails.js.map +1 -1
- package/dist/commands/interests.d.ts +5 -0
- package/dist/commands/interests.d.ts.map +1 -0
- package/dist/commands/interests.js +172 -0
- package/dist/commands/interests.js.map +1 -0
- package/dist/commands/lists.d.ts.map +1 -1
- package/dist/commands/lists.js +6 -8
- package/dist/commands/lists.js.map +1 -1
- package/dist/commands/logs.d.ts +5 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +237 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/reports.js +1 -1
- package/dist/commands/reports.js.map +1 -1
- package/dist/commands/segments.js +1 -1
- package/dist/commands/segments.js.map +1 -1
- package/dist/commands/senders.d.ts.map +1 -1
- package/dist/commands/senders.js +11 -8
- package/dist/commands/senders.js.map +1 -1
- package/dist/commands/suppressed.js +1 -1
- package/dist/commands/suppressed.js.map +1 -1
- package/dist/commands/tags.d.ts +5 -0
- package/dist/commands/tags.d.ts.map +1 -0
- package/dist/commands/tags.js +124 -0
- package/dist/commands/tags.js.map +1 -0
- package/dist/commands/templates.js +1 -1
- package/dist/commands/templates.js.map +1 -1
- package/dist/commands/transactional-templates.d.ts +5 -0
- package/dist/commands/transactional-templates.d.ts.map +1 -0
- package/dist/commands/transactional-templates.js +354 -0
- package/dist/commands/transactional-templates.js.map +1 -0
- package/dist/commands/webhooks.js +1 -1
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/utils/auth.d.ts +8 -1
- package/dist/utils/auth.d.ts.map +1 -1
- package/dist/utils/auth.js +39 -11
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/config-file.d.ts +7 -0
- package/dist/utils/config-file.d.ts.map +1 -1
- package/dist/utils/config-file.js +15 -0
- package/dist/utils/config-file.js.map +1 -1
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errors.js +1 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/list-defaults.d.ts +33 -0
- package/dist/utils/list-defaults.d.ts.map +1 -0
- package/dist/utils/list-defaults.js +52 -0
- package/dist/utils/list-defaults.js.map +1 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +36 -13
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/progress.d.ts.map +1 -1
- package/dist/utils/progress.js +32 -4
- package/dist/utils/progress.js.map +1 -1
- package/dist/utils/spinner.d.ts +17 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +43 -0
- package/dist/utils/spinner.js.map +1 -0
- package/docs/DOCUMENTATION-STANDARD.md +1068 -0
- package/docs/README.md +161 -0
- package/docs/developer/ARCHITECTURE.md +516 -0
- package/docs/developer/AUTH.md +204 -0
- package/docs/developer/CONTRIBUTING.md +227 -0
- package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
- package/docs/developer/PROJECT_INDEX.md +365 -0
- package/docs/planning/API_COVERAGE.md +1045 -0
- package/docs/planning/BACKLOG.md +1159 -0
- package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
- package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
- package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
- package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
- package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
- package/docs/planning/cakemail-profile-system-plan.md +1121 -0
- package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
- package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
- package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
- package/docs/user-manual/.obsidian/app.json +1 -0
- package/docs/user-manual/.obsidian/appearance.json +1 -0
- package/docs/user-manual/.obsidian/core-plugins.json +33 -0
- package/docs/user-manual/.obsidian/workspace.json +167 -0
- package/docs/user-manual/01-getting-started/01-installation.md +214 -0
- package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
- package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
- package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
- package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
- package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
- package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
- package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
- package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
- package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
- package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
- package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
- package/docs/user-manual/03-email-operations/01-senders.md +490 -0
- package/docs/user-manual/03-email-operations/02-templates.md +444 -0
- package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
- package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
- package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
- package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
- package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
- package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
- package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
- package/docs/user-manual/05-contact-management/01-lists.md +836 -0
- package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
- package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
- package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
- package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
- package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
- package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
- package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
- package/docs/user-manual/07-integrations/02-automation.md +326 -0
- package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
- package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
- package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
- package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
- package/docs/user-manual/09-command-reference/01-config.md +776 -0
- package/docs/user-manual/09-command-reference/02-account.md +652 -0
- package/docs/user-manual/09-command-reference/03-lists.md +958 -0
- package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
- package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
- package/docs/user-manual/09-command-reference/06-segments.md +894 -0
- package/docs/user-manual/09-command-reference/07-senders.md +803 -0
- package/docs/user-manual/09-command-reference/08-templates.md +818 -0
- package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
- package/docs/user-manual/09-command-reference/10-emails.md +807 -0
- package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
- package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
- package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
- package/docs/user-manual/09-command-reference/14-interests.md +630 -0
- package/docs/user-manual/09-command-reference/15-tags.md +584 -0
- package/docs/user-manual/09-command-reference/16-logs.md +656 -0
- package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
- package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
- package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
- package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
- package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
- package/docs/user-manual/11-appendix/04-faq.md +484 -0
- package/docs/user-manual/11-appendix/05-glossary.md +250 -0
- package/docs/user-manual/README.md +0 -0
- package/package.json +13 -47
- package/src/cli.ts +125 -0
- package/src/client.ts +16 -0
- package/src/commands/account.ts +267 -0
- package/src/commands/accounts.ts +78 -0
- package/src/commands/actions.ts +249 -0
- package/src/commands/attributes.ts +139 -0
- package/src/commands/campaign-blueprints.ts +106 -0
- package/src/commands/campaigns.ts +469 -0
- package/src/commands/config.ts +77 -0
- package/src/commands/contacts.ts +612 -0
- package/src/commands/custom-attributes.ts +127 -0
- package/src/commands/dkims.ts +117 -0
- package/src/commands/domains.ts +82 -0
- package/src/commands/email-apis.ts +569 -0
- package/src/commands/emails.ts +197 -0
- package/src/commands/forms.ts +283 -0
- package/src/commands/interests.ts +155 -0
- package/src/commands/links.ts +38 -0
- package/src/commands/lists.ts +406 -0
- package/src/commands/logos.ts +71 -0
- package/src/commands/logs.ts +386 -0
- package/src/commands/reports.ts +306 -0
- package/src/commands/segments.ts +158 -0
- package/src/commands/senders.ts +204 -0
- package/src/commands/sub-accounts.ts +271 -0
- package/src/commands/suppressed-emails.ts +234 -0
- package/src/commands/suppressed.ts +198 -0
- package/src/commands/system-emails.ts +85 -0
- package/src/commands/tags.ts +146 -0
- package/src/commands/tasks.ts +116 -0
- package/src/commands/templates.ts +189 -0
- package/src/commands/tokens.ts +83 -0
- package/src/commands/transactional-emails.ts +374 -0
- package/src/commands/transactional-templates.ts +385 -0
- package/src/commands/users.ts +506 -0
- package/src/commands/webhooks.ts +172 -0
- package/src/commands/workflow-blueprints.ts +123 -0
- package/src/commands/workflows.ts +265 -0
- package/src/types/profile.ts +93 -0
- package/src/utils/auth.ts +272 -0
- package/src/utils/config-file.ts +96 -0
- package/src/utils/config.ts +134 -0
- package/src/utils/confirm.ts +32 -0
- package/src/utils/defaults.ts +99 -0
- package/src/utils/errors.ts +116 -0
- package/src/utils/interactive.ts +91 -0
- package/src/utils/list-defaults.ts +74 -0
- package/src/utils/output.ts +190 -0
- package/src/utils/progress.ts +320 -0
- package/src/utils/spinner.ts +22 -0
- package/tests/IMPLEMENTATION_STATUS.md +258 -0
- package/tests/PTY_SETUP.md +118 -0
- package/tests/PTY_TESTING_GUIDE.md +507 -0
- package/tests/README.md +244 -0
- package/tests/fixtures/api-responses/campaigns.json +34 -0
- package/tests/fixtures/test-config.json +13 -0
- package/tests/helpers/cli-runner.ts +128 -0
- package/tests/helpers/mock-server.ts +301 -0
- package/tests/helpers/pty-runner.ts +181 -0
- package/tests/integration/campaigns-real-api.test.ts +196 -0
- package/tests/integration/setup-integration.ts +50 -0
- package/tests/pty/campaigns.test.ts +241 -0
- package/tests/setup.ts +34 -0
- package/tsconfig.json +15 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// ABOUTME: CLI commands for Segment.
|
|
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 createSegmentsCommand(
|
|
9
|
+
client: any,
|
|
10
|
+
formatter: any
|
|
11
|
+
): Command {
|
|
12
|
+
const cmd = new Command('segments')
|
|
13
|
+
.description('Create and manage segments within lists. A segment is a dynamic filter that defines a subset of contacts based on query criteria. Segments can be defined using SQL-like expressions, FIQL, or JSON query format. Segments are used to target specific audiences when sending campaigns.');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
cmd
|
|
17
|
+
.command('list <list-id>')
|
|
18
|
+
.description('Show all segments')
|
|
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
|
+
- `id`
|
|
27
|
+
- `name`
|
|
28
|
+
- `created_on`')
|
|
29
|
+
.action(async (list_id, options) => {
|
|
30
|
+
const spinner = createSpinner('Fetching segment...').start();
|
|
31
|
+
try {
|
|
32
|
+
const data = await client.listSegments({
|
|
33
|
+
list_id: Number(list_id),
|
|
34
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
35
|
+
page: options.page != null ? Number(options.page) : undefined,
|
|
36
|
+
perPage: options.perPage != null ? Number(options.perPage) : undefined,
|
|
37
|
+
withCount: options.withCount,
|
|
38
|
+
sort: options.sort,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
spinner.stop();
|
|
42
|
+
formatter.output(data);
|
|
43
|
+
} catch (error: any) {
|
|
44
|
+
spinner.stop();
|
|
45
|
+
formatter.error(error.message);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
cmd
|
|
52
|
+
.command('create <list-id>')
|
|
53
|
+
.description('Create a segment')
|
|
54
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
55
|
+
.requiredOption('--data <value>', 'Request body as JSON string')
|
|
56
|
+
.action(async (list_id, options) => {
|
|
57
|
+
const spinner = createSpinner('Creating segment...').start();
|
|
58
|
+
try {
|
|
59
|
+
const body = JSON.parse(options.data);
|
|
60
|
+
const data = await client.createSegment({
|
|
61
|
+
list_id: Number(list_id),
|
|
62
|
+
...body,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
spinner.stop();
|
|
66
|
+
formatter.success('Segment created successfully');
|
|
67
|
+
formatter.output(data);
|
|
68
|
+
} catch (error: any) {
|
|
69
|
+
spinner.stop();
|
|
70
|
+
formatter.error(error.message);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
cmd
|
|
77
|
+
.command('get <list-id> <segment-id>')
|
|
78
|
+
.description('Show a segment details')
|
|
79
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
80
|
+
.action(async (list_id, segment_id, options) => {
|
|
81
|
+
const spinner = createSpinner('Fetching segment...').start();
|
|
82
|
+
try {
|
|
83
|
+
const data = await client.getSegment({
|
|
84
|
+
list_id: Number(list_id),
|
|
85
|
+
segment_id: Number(segment_id),
|
|
86
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
spinner.stop();
|
|
90
|
+
formatter.output(data);
|
|
91
|
+
} catch (error: any) {
|
|
92
|
+
spinner.stop();
|
|
93
|
+
formatter.error(error.message);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
cmd
|
|
100
|
+
.command('patch <list-id> <segment-id>')
|
|
101
|
+
.description('Update a segment')
|
|
102
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
103
|
+
.requiredOption('--data <value>', 'Request body as JSON string')
|
|
104
|
+
.action(async (list_id, segment_id, options) => {
|
|
105
|
+
const spinner = createSpinner('Updating segment...').start();
|
|
106
|
+
try {
|
|
107
|
+
const body = JSON.parse(options.data);
|
|
108
|
+
const data = await client.patchSegment({
|
|
109
|
+
list_id: Number(list_id),
|
|
110
|
+
segment_id: Number(segment_id),
|
|
111
|
+
...body,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
spinner.stop();
|
|
115
|
+
formatter.success('Segment updated successfully');
|
|
116
|
+
formatter.output(data);
|
|
117
|
+
} catch (error: any) {
|
|
118
|
+
spinner.stop();
|
|
119
|
+
formatter.error(error.message);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
cmd
|
|
126
|
+
.command('delete <list-id> <segment-id>')
|
|
127
|
+
.description('Delete a segment')
|
|
128
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
129
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
130
|
+
.action(async (list_id, segment_id, options) => {
|
|
131
|
+
if (!options.force) {
|
|
132
|
+
const confirmed = await confirmDelete('segment', list_id);
|
|
133
|
+
if (!confirmed) {
|
|
134
|
+
formatter.info('Deletion cancelled');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const spinner = createSpinner('Deleting segment...').start();
|
|
140
|
+
try {
|
|
141
|
+
const data = await client.deleteSegment({
|
|
142
|
+
list_id: Number(list_id),
|
|
143
|
+
segment_id: Number(segment_id),
|
|
144
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
spinner.stop();
|
|
148
|
+
formatter.success('Segment deleted successfully');
|
|
149
|
+
} catch (error: any) {
|
|
150
|
+
spinner.stop();
|
|
151
|
+
formatter.error(error.message);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
return cmd;
|
|
158
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// ABOUTME: CLI commands for Sender.
|
|
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 createSendersCommand(
|
|
9
|
+
client: any,
|
|
10
|
+
formatter: any
|
|
11
|
+
): Command {
|
|
12
|
+
const cmd = new Command('senders')
|
|
13
|
+
.description('Manage sender identities (name and email pairs) used as the 'From' address in campaigns and transactional emails. New senders require email confirmation before use.');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
cmd
|
|
17
|
+
.command('list')
|
|
18
|
+
.description('Show all senders')
|
|
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
|
+
- `name`
|
|
27
|
+
- `email`
|
|
28
|
+
- `confirmed`')
|
|
29
|
+
.action(async (options) => {
|
|
30
|
+
const spinner = createSpinner('Fetching sender...').start();
|
|
31
|
+
try {
|
|
32
|
+
const data = await client.listSenders({
|
|
33
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
34
|
+
page: options.page != null ? Number(options.page) : undefined,
|
|
35
|
+
perPage: options.perPage != null ? Number(options.perPage) : undefined,
|
|
36
|
+
withCount: options.withCount,
|
|
37
|
+
sort: options.sort,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
spinner.stop();
|
|
41
|
+
formatter.output(data);
|
|
42
|
+
} catch (error: any) {
|
|
43
|
+
spinner.stop();
|
|
44
|
+
formatter.error(error.message);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
cmd
|
|
51
|
+
.command('create')
|
|
52
|
+
.description('Add a sender')
|
|
53
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
54
|
+
.requiredOption('--name <value>', 'Display name of the sender')
|
|
55
|
+
.requiredOption('--email <value>', 'Email address of the sender')
|
|
56
|
+
.option('--language <value>', 'Language for sender-related communications')
|
|
57
|
+
.action(async (options) => {
|
|
58
|
+
const spinner = createSpinner('Creating sender...').start();
|
|
59
|
+
try {
|
|
60
|
+
const data = await client.createSender({
|
|
61
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
62
|
+
name: options.name,
|
|
63
|
+
email: options.email,
|
|
64
|
+
language: options.language,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
spinner.stop();
|
|
68
|
+
formatter.success('Sender created successfully');
|
|
69
|
+
formatter.output(data);
|
|
70
|
+
} catch (error: any) {
|
|
71
|
+
spinner.stop();
|
|
72
|
+
formatter.error(error.message);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
cmd
|
|
79
|
+
.command('get <sender-id>')
|
|
80
|
+
.description('Show a sender details')
|
|
81
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
82
|
+
.action(async (sender_id, options) => {
|
|
83
|
+
const spinner = createSpinner('Fetching sender...').start();
|
|
84
|
+
try {
|
|
85
|
+
const data = await client.getSender({
|
|
86
|
+
sender_id,
|
|
87
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
spinner.stop();
|
|
91
|
+
formatter.output(data);
|
|
92
|
+
} catch (error: any) {
|
|
93
|
+
spinner.stop();
|
|
94
|
+
formatter.error(error.message);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
cmd
|
|
101
|
+
.command('patch <sender-id>')
|
|
102
|
+
.description('Update a sender')
|
|
103
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
104
|
+
.option('--name <value>', 'Display name of the sender')
|
|
105
|
+
.option('--language <value>', 'Language for sender-related communications')
|
|
106
|
+
.action(async (sender_id, options) => {
|
|
107
|
+
const spinner = createSpinner('Updating sender...').start();
|
|
108
|
+
try {
|
|
109
|
+
const data = await client.patchSender({
|
|
110
|
+
sender_id,
|
|
111
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
112
|
+
name: options.name,
|
|
113
|
+
language: options.language,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
spinner.stop();
|
|
117
|
+
formatter.success('Sender updated successfully');
|
|
118
|
+
formatter.output(data);
|
|
119
|
+
} catch (error: any) {
|
|
120
|
+
spinner.stop();
|
|
121
|
+
formatter.error(error.message);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
cmd
|
|
128
|
+
.command('delete <sender-id>')
|
|
129
|
+
.description('Delete a sender')
|
|
130
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
131
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
132
|
+
.action(async (sender_id, options) => {
|
|
133
|
+
if (!options.force) {
|
|
134
|
+
const confirmed = await confirmDelete('sender', sender_id);
|
|
135
|
+
if (!confirmed) {
|
|
136
|
+
formatter.info('Deletion cancelled');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const spinner = createSpinner('Deleting sender...').start();
|
|
142
|
+
try {
|
|
143
|
+
const data = await client.deleteSender({
|
|
144
|
+
sender_id,
|
|
145
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
spinner.stop();
|
|
149
|
+
formatter.success('Sender deleted successfully');
|
|
150
|
+
} catch (error: any) {
|
|
151
|
+
spinner.stop();
|
|
152
|
+
formatter.error(error.message);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
cmd
|
|
159
|
+
.command('confirm')
|
|
160
|
+
.description('Confirm a sender')
|
|
161
|
+
.requiredOption('--confirmation-id <value>', 'Confirmation token from the verification email')
|
|
162
|
+
.action(async (options) => {
|
|
163
|
+
const spinner = createSpinner('Creating sender...').start();
|
|
164
|
+
try {
|
|
165
|
+
const data = await client.confirmSender({
|
|
166
|
+
confirmationId: options.confirmationId,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
spinner.stop();
|
|
170
|
+
formatter.success('Sender created successfully');
|
|
171
|
+
formatter.output(data);
|
|
172
|
+
} catch (error: any) {
|
|
173
|
+
spinner.stop();
|
|
174
|
+
formatter.error(error.message);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
cmd
|
|
181
|
+
.command('resend-confirmation-email <sender-id>')
|
|
182
|
+
.description('Resend confirmation email')
|
|
183
|
+
.option('--account-id <value>', 'Optional Account ID to be used for the request')
|
|
184
|
+
.action(async (sender_id, options) => {
|
|
185
|
+
const spinner = createSpinner('Creating sender...').start();
|
|
186
|
+
try {
|
|
187
|
+
const data = await client.resendConfirmationEmail({
|
|
188
|
+
sender_id,
|
|
189
|
+
accountId: options.accountId != null ? Number(options.accountId) : undefined,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
spinner.stop();
|
|
193
|
+
formatter.success('Sender created successfully');
|
|
194
|
+
formatter.output(data);
|
|
195
|
+
} catch (error: any) {
|
|
196
|
+
spinner.stop();
|
|
197
|
+
formatter.error(error.message);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
return cmd;
|
|
204
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// ABOUTME: CLI commands for Sub-Account.
|
|
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 createSubAccountsCommand(
|
|
9
|
+
client: any,
|
|
10
|
+
formatter: any
|
|
11
|
+
): Command {
|
|
12
|
+
const cmd = new Command('sub-accounts')
|
|
13
|
+
.description('Manage sub-accounts under a partner or organization account. Sub-accounts are independent accounts with their own users, contacts, and campaigns, managed by the parent account. Includes creation, suspension, and configuration.');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
cmd
|
|
17
|
+
.command('list-accounts')
|
|
18
|
+
.description('Show all sub-accounts')
|
|
19
|
+
.option('--partner-account-id <value>', 'partner_account_id')
|
|
20
|
+
.option('--recursive <value>', 'recursive')
|
|
21
|
+
.option('--page <value>', 'page')
|
|
22
|
+
.option('--per-page <value>', 'per_page')
|
|
23
|
+
.option('--with-count <value>', 'Include count in the response')
|
|
24
|
+
.option('--sort <value>', 'Sort term and direction, using syntax `[-|+]term`.
|
|
25
|
+
|
|
26
|
+
Valid terms:
|
|
27
|
+
- `name`
|
|
28
|
+
- `created_on`')
|
|
29
|
+
.option('--filter <value>', 'Valid Terms:
|
|
30
|
+
- `name`
|
|
31
|
+
- `status`
|
|
32
|
+
|
|
33
|
+
Valid Operators:
|
|
34
|
+
- `==`
|
|
35
|
+
|
|
36
|
+
Query separator:
|
|
37
|
+
- `;`')
|
|
38
|
+
.action(async (options) => {
|
|
39
|
+
const spinner = createSpinner('Fetching sub-account...').start();
|
|
40
|
+
try {
|
|
41
|
+
const data = await client.listAccounts({
|
|
42
|
+
partnerAccountId: options.partnerAccountId != null ? Number(options.partnerAccountId) : undefined,
|
|
43
|
+
recursive: options.recursive,
|
|
44
|
+
page: options.page != null ? Number(options.page) : undefined,
|
|
45
|
+
perPage: options.perPage != null ? Number(options.perPage) : undefined,
|
|
46
|
+
withCount: options.withCount,
|
|
47
|
+
sort: options.sort,
|
|
48
|
+
filter: options.filter,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
spinner.stop();
|
|
52
|
+
formatter.output(data);
|
|
53
|
+
} catch (error: any) {
|
|
54
|
+
spinner.stop();
|
|
55
|
+
formatter.error(error.message);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
cmd
|
|
62
|
+
.command('create-account')
|
|
63
|
+
.description('Create a sub-account')
|
|
64
|
+
.option('--partner-account-id <value>', 'partner_account_id')
|
|
65
|
+
.option('--skip-verification <value>', 'skip_verification')
|
|
66
|
+
.requiredOption('--data <value>', 'Request body as JSON string')
|
|
67
|
+
.action(async (options) => {
|
|
68
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
69
|
+
try {
|
|
70
|
+
const body = JSON.parse(options.data);
|
|
71
|
+
const data = await client.createAccount({
|
|
72
|
+
...body,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
spinner.stop();
|
|
76
|
+
formatter.success('Sub-Account created successfully');
|
|
77
|
+
formatter.output(data);
|
|
78
|
+
} catch (error: any) {
|
|
79
|
+
spinner.stop();
|
|
80
|
+
formatter.error(error.message);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
cmd
|
|
87
|
+
.command('get-account <account-id>')
|
|
88
|
+
.description('Show sub-account details')
|
|
89
|
+
.action(async (account_id) => {
|
|
90
|
+
const spinner = createSpinner('Fetching sub-account...').start();
|
|
91
|
+
try {
|
|
92
|
+
const data = await client.getAccount({
|
|
93
|
+
account_id,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
spinner.stop();
|
|
97
|
+
formatter.output(data);
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
spinner.stop();
|
|
100
|
+
formatter.error(error.message);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
cmd
|
|
107
|
+
.command('patch-account <account-id>')
|
|
108
|
+
.description('Update a sub-account')
|
|
109
|
+
.requiredOption('--data <value>', 'Request body as JSON string')
|
|
110
|
+
.action(async (account_id, options) => {
|
|
111
|
+
const spinner = createSpinner('Updating sub-account...').start();
|
|
112
|
+
try {
|
|
113
|
+
const body = JSON.parse(options.data);
|
|
114
|
+
const data = await client.patchAccount({
|
|
115
|
+
account_id: Number(account_id),
|
|
116
|
+
...body,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
spinner.stop();
|
|
120
|
+
formatter.success('Sub-Account updated successfully');
|
|
121
|
+
formatter.output(data);
|
|
122
|
+
} catch (error: any) {
|
|
123
|
+
spinner.stop();
|
|
124
|
+
formatter.error(error.message);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
cmd
|
|
131
|
+
.command('delete-account <account-id>')
|
|
132
|
+
.description('Delete a sub-account')
|
|
133
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
134
|
+
.action(async (account_idoptions) => {
|
|
135
|
+
if (!options.force) {
|
|
136
|
+
const confirmed = await confirmDelete('sub-account', account_id);
|
|
137
|
+
if (!confirmed) {
|
|
138
|
+
formatter.info('Deletion cancelled');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const spinner = createSpinner('Deleting sub-account...').start();
|
|
144
|
+
try {
|
|
145
|
+
const data = await client.deleteAccount({
|
|
146
|
+
account_id,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
spinner.stop();
|
|
150
|
+
formatter.success('Sub-Account deleted successfully');
|
|
151
|
+
} catch (error: any) {
|
|
152
|
+
spinner.stop();
|
|
153
|
+
formatter.error(error.message);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
cmd
|
|
160
|
+
.command('suspend-account <account-id>')
|
|
161
|
+
.description('Suspend a sub-account')
|
|
162
|
+
.action(async (account_id) => {
|
|
163
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
164
|
+
try {
|
|
165
|
+
const data = await client.suspendAccount({
|
|
166
|
+
account_id: Number(account_id),
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
spinner.stop();
|
|
170
|
+
formatter.success('Sub-Account created successfully');
|
|
171
|
+
formatter.output(data);
|
|
172
|
+
} catch (error: any) {
|
|
173
|
+
spinner.stop();
|
|
174
|
+
formatter.error(error.message);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
cmd
|
|
181
|
+
.command('unsuspend-account <account-id>')
|
|
182
|
+
.description('Unsuspend a sub-account')
|
|
183
|
+
.action(async (account_id) => {
|
|
184
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
185
|
+
try {
|
|
186
|
+
const data = await client.unsuspendAccount({
|
|
187
|
+
account_id: Number(account_id),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
spinner.stop();
|
|
191
|
+
formatter.success('Sub-Account created successfully');
|
|
192
|
+
formatter.output(data);
|
|
193
|
+
} catch (error: any) {
|
|
194
|
+
spinner.stop();
|
|
195
|
+
formatter.error(error.message);
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
cmd
|
|
202
|
+
.command('confirm-account <account-id>')
|
|
203
|
+
.description('Confirm sub-account creation')
|
|
204
|
+
.requiredOption('--confirmation <value>', 'confirmation')
|
|
205
|
+
.action(async (account_id, options) => {
|
|
206
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
207
|
+
try {
|
|
208
|
+
const data = await client.confirmAccount({
|
|
209
|
+
account_id,
|
|
210
|
+
confirmation: options.confirmation,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
spinner.stop();
|
|
214
|
+
formatter.success('Sub-Account created successfully');
|
|
215
|
+
formatter.output(data);
|
|
216
|
+
} catch (error: any) {
|
|
217
|
+
spinner.stop();
|
|
218
|
+
formatter.error(error.message);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
cmd
|
|
225
|
+
.command('resend-account-verification')
|
|
226
|
+
.description('Resend the account verification email')
|
|
227
|
+
.requiredOption('--email <value>', 'Email address to resend the verification to')
|
|
228
|
+
.action(async (options) => {
|
|
229
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
230
|
+
try {
|
|
231
|
+
const data = await client.resendAccountVerification({
|
|
232
|
+
email: options.email,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
spinner.stop();
|
|
236
|
+
formatter.success('Sub-Account created successfully');
|
|
237
|
+
formatter.output(data);
|
|
238
|
+
} catch (error: any) {
|
|
239
|
+
spinner.stop();
|
|
240
|
+
formatter.error(error.message);
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
cmd
|
|
247
|
+
.command('convert-account-to-organization <account-id>')
|
|
248
|
+
.description('Convert an account to an Organization')
|
|
249
|
+
.requiredOption('--data <value>', 'Request body as JSON string')
|
|
250
|
+
.action(async (account_id, options) => {
|
|
251
|
+
const spinner = createSpinner('Creating sub-account...').start();
|
|
252
|
+
try {
|
|
253
|
+
const body = JSON.parse(options.data);
|
|
254
|
+
const data = await client.convertAccountToOrganization({
|
|
255
|
+
account_id: Number(account_id),
|
|
256
|
+
...body,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
spinner.stop();
|
|
260
|
+
formatter.success('Sub-Account created successfully');
|
|
261
|
+
formatter.output(data);
|
|
262
|
+
} catch (error: any) {
|
|
263
|
+
spinner.stop();
|
|
264
|
+
formatter.error(error.message);
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
return cmd;
|
|
271
|
+
}
|