resend-cli 1.2.1 → 1.2.2
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/biome.json +1 -1
- package/bun.lock +0 -3
- package/package.json +2 -3
- package/src/cli.ts +11 -1
- package/src/commands/auth/login.ts +35 -8
- package/src/commands/doctor.ts +33 -115
- package/src/commands/teams/remove.ts +5 -2
- package/src/commands/teams/switch.ts +3 -0
- package/src/lib/config.ts +37 -31
- package/src/lib/spinner.ts +17 -10
- package/src/lib/update-check.ts +172 -0
- package/tests/commands/auth/login.test.ts +37 -0
- package/tests/lib/config.test.ts +38 -7
- package/tests/lib/update-check.test.ts +169 -0
- package/.claude/worktrees/emails-list/.claude/settings.local.json +0 -5
- package/.claude/worktrees/emails-list/.github/scripts/pr-title-check.js +0 -34
- package/.claude/worktrees/emails-list/.github/workflows/ci.yml +0 -32
- package/.claude/worktrees/emails-list/.github/workflows/pr-title-check.yml +0 -13
- package/.claude/worktrees/emails-list/.github/workflows/release.yml +0 -93
- package/.claude/worktrees/emails-list/CHANGELOG.md +0 -31
- package/.claude/worktrees/emails-list/LICENSE +0 -21
- package/.claude/worktrees/emails-list/README.md +0 -424
- package/.claude/worktrees/emails-list/biome.json +0 -36
- package/.claude/worktrees/emails-list/bun.lock +0 -76
- package/.claude/worktrees/emails-list/bunfig.toml +0 -2
- package/.claude/worktrees/emails-list/install.ps1 +0 -140
- package/.claude/worktrees/emails-list/install.sh +0 -301
- package/.claude/worktrees/emails-list/package.json +0 -43
- package/.claude/worktrees/emails-list/renovate.json +0 -6
- package/.claude/worktrees/emails-list/src/cli.ts +0 -74
- package/.claude/worktrees/emails-list/src/commands/api-keys/create.ts +0 -114
- package/.claude/worktrees/emails-list/src/commands/api-keys/delete.ts +0 -47
- package/.claude/worktrees/emails-list/src/commands/api-keys/index.ts +0 -26
- package/.claude/worktrees/emails-list/src/commands/api-keys/list.ts +0 -35
- package/.claude/worktrees/emails-list/src/commands/api-keys/utils.ts +0 -8
- package/.claude/worktrees/emails-list/src/commands/auth/index.ts +0 -20
- package/.claude/worktrees/emails-list/src/commands/auth/login.ts +0 -207
- package/.claude/worktrees/emails-list/src/commands/auth/logout.ts +0 -105
- package/.claude/worktrees/emails-list/src/commands/broadcasts/create.ts +0 -196
- package/.claude/worktrees/emails-list/src/commands/broadcasts/delete.ts +0 -46
- package/.claude/worktrees/emails-list/src/commands/broadcasts/get.ts +0 -59
- package/.claude/worktrees/emails-list/src/commands/broadcasts/index.ts +0 -43
- package/.claude/worktrees/emails-list/src/commands/broadcasts/list.ts +0 -60
- package/.claude/worktrees/emails-list/src/commands/broadcasts/send.ts +0 -56
- package/.claude/worktrees/emails-list/src/commands/broadcasts/update.ts +0 -95
- package/.claude/worktrees/emails-list/src/commands/broadcasts/utils.ts +0 -35
- package/.claude/worktrees/emails-list/src/commands/contact-properties/create.ts +0 -118
- package/.claude/worktrees/emails-list/src/commands/contact-properties/delete.ts +0 -48
- package/.claude/worktrees/emails-list/src/commands/contact-properties/get.ts +0 -46
- package/.claude/worktrees/emails-list/src/commands/contact-properties/index.ts +0 -48
- package/.claude/worktrees/emails-list/src/commands/contact-properties/list.ts +0 -68
- package/.claude/worktrees/emails-list/src/commands/contact-properties/update.ts +0 -88
- package/.claude/worktrees/emails-list/src/commands/contact-properties/utils.ts +0 -17
- package/.claude/worktrees/emails-list/src/commands/contacts/add-segment.ts +0 -78
- package/.claude/worktrees/emails-list/src/commands/contacts/create.ts +0 -122
- package/.claude/worktrees/emails-list/src/commands/contacts/delete.ts +0 -49
- package/.claude/worktrees/emails-list/src/commands/contacts/get.ts +0 -53
- package/.claude/worktrees/emails-list/src/commands/contacts/index.ts +0 -58
- package/.claude/worktrees/emails-list/src/commands/contacts/list.ts +0 -57
- package/.claude/worktrees/emails-list/src/commands/contacts/remove-segment.ts +0 -48
- package/.claude/worktrees/emails-list/src/commands/contacts/segments.ts +0 -39
- package/.claude/worktrees/emails-list/src/commands/contacts/topics.ts +0 -45
- package/.claude/worktrees/emails-list/src/commands/contacts/update-topics.ts +0 -90
- package/.claude/worktrees/emails-list/src/commands/contacts/update.ts +0 -77
- package/.claude/worktrees/emails-list/src/commands/contacts/utils.ts +0 -119
- package/.claude/worktrees/emails-list/src/commands/doctor.ts +0 -298
- package/.claude/worktrees/emails-list/src/commands/domains/create.ts +0 -83
- package/.claude/worktrees/emails-list/src/commands/domains/delete.ts +0 -42
- package/.claude/worktrees/emails-list/src/commands/domains/get.ts +0 -47
- package/.claude/worktrees/emails-list/src/commands/domains/index.ts +0 -35
- package/.claude/worktrees/emails-list/src/commands/domains/list.ts +0 -53
- package/.claude/worktrees/emails-list/src/commands/domains/update.ts +0 -75
- package/.claude/worktrees/emails-list/src/commands/domains/utils.ts +0 -44
- package/.claude/worktrees/emails-list/src/commands/domains/verify.ts +0 -38
- package/.claude/worktrees/emails-list/src/commands/emails/batch.ts +0 -140
- package/.claude/worktrees/emails-list/src/commands/emails/index.ts +0 -28
- package/.claude/worktrees/emails-list/src/commands/emails/list.ts +0 -73
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachment.ts +0 -55
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachments.ts +0 -68
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/get.ts +0 -58
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/index.ts +0 -28
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/list.ts +0 -59
- package/.claude/worktrees/emails-list/src/commands/emails/receiving/utils.ts +0 -38
- package/.claude/worktrees/emails-list/src/commands/emails/send.ts +0 -189
- package/.claude/worktrees/emails-list/src/commands/open.ts +0 -24
- package/.claude/worktrees/emails-list/src/commands/segments/create.ts +0 -50
- package/.claude/worktrees/emails-list/src/commands/segments/delete.ts +0 -47
- package/.claude/worktrees/emails-list/src/commands/segments/get.ts +0 -38
- package/.claude/worktrees/emails-list/src/commands/segments/index.ts +0 -36
- package/.claude/worktrees/emails-list/src/commands/segments/list.ts +0 -58
- package/.claude/worktrees/emails-list/src/commands/segments/utils.ts +0 -7
- package/.claude/worktrees/emails-list/src/commands/teams/index.ts +0 -10
- package/.claude/worktrees/emails-list/src/commands/teams/list.ts +0 -35
- package/.claude/worktrees/emails-list/src/commands/teams/remove.ts +0 -83
- package/.claude/worktrees/emails-list/src/commands/teams/switch.ts +0 -73
- package/.claude/worktrees/emails-list/src/commands/topics/create.ts +0 -73
- package/.claude/worktrees/emails-list/src/commands/topics/delete.ts +0 -47
- package/.claude/worktrees/emails-list/src/commands/topics/get.ts +0 -42
- package/.claude/worktrees/emails-list/src/commands/topics/index.ts +0 -42
- package/.claude/worktrees/emails-list/src/commands/topics/list.ts +0 -34
- package/.claude/worktrees/emails-list/src/commands/topics/update.ts +0 -59
- package/.claude/worktrees/emails-list/src/commands/topics/utils.ts +0 -16
- package/.claude/worktrees/emails-list/src/commands/webhooks/create.ts +0 -128
- package/.claude/worktrees/emails-list/src/commands/webhooks/delete.ts +0 -49
- package/.claude/worktrees/emails-list/src/commands/webhooks/get.ts +0 -42
- package/.claude/worktrees/emails-list/src/commands/webhooks/index.ts +0 -44
- package/.claude/worktrees/emails-list/src/commands/webhooks/list.ts +0 -55
- package/.claude/worktrees/emails-list/src/commands/webhooks/update.ts +0 -83
- package/.claude/worktrees/emails-list/src/commands/webhooks/utils.ts +0 -36
- package/.claude/worktrees/emails-list/src/commands/whoami.ts +0 -71
- package/.claude/worktrees/emails-list/src/lib/actions.ts +0 -157
- package/.claude/worktrees/emails-list/src/lib/client.ts +0 -34
- package/.claude/worktrees/emails-list/src/lib/config.ts +0 -211
- package/.claude/worktrees/emails-list/src/lib/files.ts +0 -15
- package/.claude/worktrees/emails-list/src/lib/help-text.ts +0 -38
- package/.claude/worktrees/emails-list/src/lib/output.ts +0 -54
- package/.claude/worktrees/emails-list/src/lib/pagination.ts +0 -36
- package/.claude/worktrees/emails-list/src/lib/prompts.ts +0 -149
- package/.claude/worktrees/emails-list/src/lib/spinner.ts +0 -93
- package/.claude/worktrees/emails-list/src/lib/table.ts +0 -57
- package/.claude/worktrees/emails-list/src/lib/tty.ts +0 -28
- package/.claude/worktrees/emails-list/src/lib/version.ts +0 -4
- package/.claude/worktrees/emails-list/tests/commands/api-keys/create.test.ts +0 -195
- package/.claude/worktrees/emails-list/tests/commands/api-keys/delete.test.ts +0 -156
- package/.claude/worktrees/emails-list/tests/commands/api-keys/list.test.ts +0 -133
- package/.claude/worktrees/emails-list/tests/commands/auth/login.test.ts +0 -119
- package/.claude/worktrees/emails-list/tests/commands/auth/logout.test.ts +0 -146
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/create.test.ts +0 -447
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/delete.test.ts +0 -182
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/get.test.ts +0 -146
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/list.test.ts +0 -196
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/send.test.ts +0 -161
- package/.claude/worktrees/emails-list/tests/commands/broadcasts/update.test.ts +0 -283
- package/.claude/worktrees/emails-list/tests/commands/contact-properties/create.test.ts +0 -250
- package/.claude/worktrees/emails-list/tests/commands/contact-properties/delete.test.ts +0 -183
- package/.claude/worktrees/emails-list/tests/commands/contact-properties/get.test.ts +0 -144
- package/.claude/worktrees/emails-list/tests/commands/contact-properties/list.test.ts +0 -180
- package/.claude/worktrees/emails-list/tests/commands/contact-properties/update.test.ts +0 -216
- package/.claude/worktrees/emails-list/tests/commands/contacts/add-segment.test.ts +0 -188
- package/.claude/worktrees/emails-list/tests/commands/contacts/create.test.ts +0 -270
- package/.claude/worktrees/emails-list/tests/commands/contacts/delete.test.ts +0 -192
- package/.claude/worktrees/emails-list/tests/commands/contacts/get.test.ts +0 -148
- package/.claude/worktrees/emails-list/tests/commands/contacts/list.test.ts +0 -175
- package/.claude/worktrees/emails-list/tests/commands/contacts/remove-segment.test.ts +0 -166
- package/.claude/worktrees/emails-list/tests/commands/contacts/segments.test.ts +0 -167
- package/.claude/worktrees/emails-list/tests/commands/contacts/topics.test.ts +0 -163
- package/.claude/worktrees/emails-list/tests/commands/contacts/update-topics.test.ts +0 -247
- package/.claude/worktrees/emails-list/tests/commands/contacts/update.test.ts +0 -205
- package/.claude/worktrees/emails-list/tests/commands/doctor.test.ts +0 -165
- package/.claude/worktrees/emails-list/tests/commands/domains/create.test.ts +0 -192
- package/.claude/worktrees/emails-list/tests/commands/domains/delete.test.ts +0 -156
- package/.claude/worktrees/emails-list/tests/commands/domains/get.test.ts +0 -137
- package/.claude/worktrees/emails-list/tests/commands/domains/list.test.ts +0 -164
- package/.claude/worktrees/emails-list/tests/commands/domains/update.test.ts +0 -223
- package/.claude/worktrees/emails-list/tests/commands/domains/verify.test.ts +0 -117
- package/.claude/worktrees/emails-list/tests/commands/emails/batch.test.ts +0 -313
- package/.claude/worktrees/emails-list/tests/commands/emails/list.test.ts +0 -196
- package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachment.test.ts +0 -140
- package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachments.test.ts +0 -168
- package/.claude/worktrees/emails-list/tests/commands/emails/receiving/get.test.ts +0 -140
- package/.claude/worktrees/emails-list/tests/commands/emails/receiving/list.test.ts +0 -181
- package/.claude/worktrees/emails-list/tests/commands/emails/send.test.ts +0 -309
- package/.claude/worktrees/emails-list/tests/commands/segments/create.test.ts +0 -163
- package/.claude/worktrees/emails-list/tests/commands/segments/delete.test.ts +0 -182
- package/.claude/worktrees/emails-list/tests/commands/segments/get.test.ts +0 -137
- package/.claude/worktrees/emails-list/tests/commands/segments/list.test.ts +0 -173
- package/.claude/worktrees/emails-list/tests/commands/teams/list.test.ts +0 -63
- package/.claude/worktrees/emails-list/tests/commands/teams/remove.test.ts +0 -103
- package/.claude/worktrees/emails-list/tests/commands/teams/switch.test.ts +0 -96
- package/.claude/worktrees/emails-list/tests/commands/topics/create.test.ts +0 -191
- package/.claude/worktrees/emails-list/tests/commands/topics/delete.test.ts +0 -156
- package/.claude/worktrees/emails-list/tests/commands/topics/get.test.ts +0 -125
- package/.claude/worktrees/emails-list/tests/commands/topics/list.test.ts +0 -124
- package/.claude/worktrees/emails-list/tests/commands/topics/update.test.ts +0 -177
- package/.claude/worktrees/emails-list/tests/commands/webhooks/create.test.ts +0 -224
- package/.claude/worktrees/emails-list/tests/commands/webhooks/delete.test.ts +0 -156
- package/.claude/worktrees/emails-list/tests/commands/webhooks/get.test.ts +0 -125
- package/.claude/worktrees/emails-list/tests/commands/webhooks/list.test.ts +0 -177
- package/.claude/worktrees/emails-list/tests/commands/webhooks/update.test.ts +0 -206
- package/.claude/worktrees/emails-list/tests/commands/whoami.test.ts +0 -99
- package/.claude/worktrees/emails-list/tests/helpers.ts +0 -93
- package/.claude/worktrees/emails-list/tests/lib/client.test.ts +0 -71
- package/.claude/worktrees/emails-list/tests/lib/config.test.ts +0 -414
- package/.claude/worktrees/emails-list/tests/lib/files.test.ts +0 -65
- package/.claude/worktrees/emails-list/tests/lib/help-text.test.ts +0 -97
- package/.claude/worktrees/emails-list/tests/lib/output.test.ts +0 -127
- package/.claude/worktrees/emails-list/tests/lib/prompts.test.ts +0 -178
- package/.claude/worktrees/emails-list/tests/lib/spinner.test.ts +0 -146
- package/.claude/worktrees/emails-list/tests/lib/table.test.ts +0 -63
- package/.claude/worktrees/emails-list/tests/lib/tty.test.ts +0 -85
- package/.claude/worktrees/emails-list/tsconfig.json +0 -14
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import type { GlobalOpts } from '../../../lib/client';
|
|
3
|
-
import { requireClient } from '../../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../../lib/help-text';
|
|
5
|
-
import { outputResult } from '../../../lib/output';
|
|
6
|
-
import { withSpinner } from '../../../lib/spinner';
|
|
7
|
-
import { isInteractive } from '../../../lib/tty';
|
|
8
|
-
|
|
9
|
-
export const getAttachmentCommand = new Command('attachment')
|
|
10
|
-
.description('Retrieve a single attachment from a received (inbound) email')
|
|
11
|
-
.argument('<emailId>', 'Received email UUID')
|
|
12
|
-
.argument('<attachmentId>', 'Attachment UUID')
|
|
13
|
-
.addHelpText(
|
|
14
|
-
'after',
|
|
15
|
-
buildHelpText({
|
|
16
|
-
context:
|
|
17
|
-
'The download_url is a signed URL that expires in ~1 hour. Download the file directly:\n resend emails receiving attachment <emailId> <attachmentId> --json | jq -r .download_url | xargs curl -O',
|
|
18
|
-
output:
|
|
19
|
-
' {"object":"attachment","id":"<uuid>","filename":"invoice.pdf","size":51200,"content_type":"application/pdf","content_disposition":"attachment","content_id":null,"download_url":"<signed-url>","expires_at":"<iso-date>"}',
|
|
20
|
-
errorCodes: ['auth_error', 'fetch_error'],
|
|
21
|
-
examples: [
|
|
22
|
-
'resend emails receiving attachment <email-id> <attachment-id>',
|
|
23
|
-
'resend emails receiving attachment <email-id> <attachment-id> --json',
|
|
24
|
-
],
|
|
25
|
-
}),
|
|
26
|
-
)
|
|
27
|
-
.action(async (emailId, attachmentId, _opts, cmd) => {
|
|
28
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
29
|
-
const resend = requireClient(globalOpts);
|
|
30
|
-
|
|
31
|
-
const data = await withSpinner(
|
|
32
|
-
{
|
|
33
|
-
loading: 'Fetching attachment...',
|
|
34
|
-
success: 'Attachment fetched',
|
|
35
|
-
fail: 'Failed to fetch attachment',
|
|
36
|
-
},
|
|
37
|
-
() =>
|
|
38
|
-
resend.emails.receiving.attachments.get({ emailId, id: attachmentId }),
|
|
39
|
-
'fetch_error',
|
|
40
|
-
globalOpts,
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (!globalOpts.json && isInteractive()) {
|
|
44
|
-
const d = data;
|
|
45
|
-
console.log(`\n${d.filename ?? '(unnamed)'}`);
|
|
46
|
-
console.log(`ID: ${d.id}`);
|
|
47
|
-
console.log(`Content-Type: ${d.content_type}`);
|
|
48
|
-
console.log(`Size: ${d.size} bytes`);
|
|
49
|
-
console.log(`Disposition: ${d.content_disposition}`);
|
|
50
|
-
console.log(`Download URL: ${d.download_url}`);
|
|
51
|
-
console.log(`Expires: ${d.expires_at}`);
|
|
52
|
-
} else {
|
|
53
|
-
outputResult(data, { json: globalOpts.json });
|
|
54
|
-
}
|
|
55
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runList } from '../../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../../lib/help-text';
|
|
5
|
-
import {
|
|
6
|
-
buildPaginationOpts,
|
|
7
|
-
parseLimitOpt,
|
|
8
|
-
printPaginationHint,
|
|
9
|
-
} from '../../../lib/pagination';
|
|
10
|
-
import { renderAttachmentsTable } from './utils';
|
|
11
|
-
|
|
12
|
-
export const listAttachmentsCommand = new Command('attachments')
|
|
13
|
-
.description('List attachments on a received (inbound) email')
|
|
14
|
-
.argument('<emailId>', 'Received email UUID')
|
|
15
|
-
.option(
|
|
16
|
-
'--limit <n>',
|
|
17
|
-
'Maximum number of attachments to return (1-100)',
|
|
18
|
-
'10',
|
|
19
|
-
)
|
|
20
|
-
.option(
|
|
21
|
-
'--after <cursor>',
|
|
22
|
-
'Return attachments after this cursor (next page)',
|
|
23
|
-
)
|
|
24
|
-
.option(
|
|
25
|
-
'--before <cursor>',
|
|
26
|
-
'Return attachments before this cursor (previous page)',
|
|
27
|
-
)
|
|
28
|
-
.addHelpText(
|
|
29
|
-
'after',
|
|
30
|
-
buildHelpText({
|
|
31
|
-
context:
|
|
32
|
-
'Each attachment has a download_url (signed, expires ~1 hour).\nUse the attachment sub-command to retrieve a single attachment with its download URL:\n resend emails receiving attachment <emailId> <attachmentId>\n\ncontent_disposition: "inline" means the attachment is embedded in the HTML body (e.g. an image).\ncontent_disposition: "attachment" means it is a standalone file download.',
|
|
33
|
-
output:
|
|
34
|
-
' {"object":"list","has_more":false,"data":[{"id":"<uuid>","filename":"invoice.pdf","size":51200,"content_type":"application/pdf","content_disposition":"attachment","content_id":null,"download_url":"<url>","expires_at":"<iso-date>"}]}',
|
|
35
|
-
errorCodes: ['auth_error', 'invalid_limit', 'list_error'],
|
|
36
|
-
examples: [
|
|
37
|
-
'resend emails receiving attachments <email-id>',
|
|
38
|
-
'resend emails receiving attachments <email-id> --json',
|
|
39
|
-
'resend emails receiving attachments <email-id> --limit 25 --json',
|
|
40
|
-
],
|
|
41
|
-
}),
|
|
42
|
-
)
|
|
43
|
-
.action(async (emailId, opts, cmd) => {
|
|
44
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
45
|
-
|
|
46
|
-
const limit = parseLimitOpt(opts.limit, globalOpts);
|
|
47
|
-
const paginationOpts = buildPaginationOpts(limit, opts.after, opts.before);
|
|
48
|
-
|
|
49
|
-
await runList(
|
|
50
|
-
{
|
|
51
|
-
spinner: {
|
|
52
|
-
loading: 'Fetching attachments...',
|
|
53
|
-
success: 'Attachments fetched',
|
|
54
|
-
fail: 'Failed to list attachments',
|
|
55
|
-
},
|
|
56
|
-
sdkCall: (resend) =>
|
|
57
|
-
resend.emails.receiving.attachments.list({
|
|
58
|
-
emailId,
|
|
59
|
-
...paginationOpts,
|
|
60
|
-
}),
|
|
61
|
-
onInteractive: (list) => {
|
|
62
|
-
console.log(renderAttachmentsTable(list.data));
|
|
63
|
-
printPaginationHint(list);
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
globalOpts,
|
|
67
|
-
);
|
|
68
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runGet } from '../../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../../lib/help-text';
|
|
5
|
-
|
|
6
|
-
export const getReceivingCommand = new Command('get')
|
|
7
|
-
.description(
|
|
8
|
-
'Retrieve a single received (inbound) email with full details including HTML, text, and headers',
|
|
9
|
-
)
|
|
10
|
-
.argument('<id>', 'Received email UUID')
|
|
11
|
-
.addHelpText(
|
|
12
|
-
'after',
|
|
13
|
-
buildHelpText({
|
|
14
|
-
context:
|
|
15
|
-
'The raw.download_url field is a signed URL (expires ~1 hour) containing the full RFC 2822\nMIME message. Pipe it to curl to save the original email:\n resend emails receiving get <id> --json | jq -r .raw.download_url | xargs curl > email.eml\n\nAttachments are listed in the attachments array. Use the attachments sub-command to get\ndownload URLs:\n resend emails receiving attachments <id>',
|
|
16
|
-
output:
|
|
17
|
-
' {"object":"email","id":"<uuid>","to":["inbox@yourdomain.com"],"from":"sender@external.com","subject":"Hello","html":"<p>Hello!</p>","text":"Hello!","headers":{"x-mailer":"..."},"message_id":"<str>","bcc":[],"cc":[],"reply_to":[],"raw":{"download_url":"<url>","expires_at":"<iso-date>"},"attachments":[]}',
|
|
18
|
-
errorCodes: ['auth_error', 'fetch_error'],
|
|
19
|
-
examples: [
|
|
20
|
-
'resend emails receiving get <email-id>',
|
|
21
|
-
'resend emails receiving get <email-id> --json',
|
|
22
|
-
],
|
|
23
|
-
}),
|
|
24
|
-
)
|
|
25
|
-
.action(async (id, _opts, cmd) => {
|
|
26
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
27
|
-
await runGet(
|
|
28
|
-
{
|
|
29
|
-
spinner: {
|
|
30
|
-
loading: 'Fetching received email...',
|
|
31
|
-
success: 'Received email fetched',
|
|
32
|
-
fail: 'Failed to fetch received email',
|
|
33
|
-
},
|
|
34
|
-
sdkCall: (resend) => resend.emails.receiving.get(id),
|
|
35
|
-
onInteractive: (data) => {
|
|
36
|
-
console.log(`\nFrom: ${data.from}`);
|
|
37
|
-
console.log(`To: ${data.to.join(', ')}`);
|
|
38
|
-
console.log(`Subject: ${data.subject}`);
|
|
39
|
-
console.log(`Date: ${data.created_at}`);
|
|
40
|
-
if (data.attachments.length > 0) {
|
|
41
|
-
console.log(`Files: ${data.attachments.length} attachment(s)`);
|
|
42
|
-
}
|
|
43
|
-
if (data.text) {
|
|
44
|
-
const snippet =
|
|
45
|
-
data.text.length > 200
|
|
46
|
-
? `${data.text.slice(0, 197)}...`
|
|
47
|
-
: data.text;
|
|
48
|
-
console.log(`\n${snippet}`);
|
|
49
|
-
} else if (data.html) {
|
|
50
|
-
console.log(
|
|
51
|
-
'\n(HTML body only — use --json to view or pipe to a browser)',
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
globalOpts,
|
|
57
|
-
);
|
|
58
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { buildHelpText } from '../../../lib/help-text';
|
|
3
|
-
import { getAttachmentCommand } from './attachment';
|
|
4
|
-
import { listAttachmentsCommand } from './attachments';
|
|
5
|
-
import { getReceivingCommand } from './get';
|
|
6
|
-
import { listReceivingCommand } from './list';
|
|
7
|
-
|
|
8
|
-
export const receivingCommand = new Command('receiving')
|
|
9
|
-
.description(
|
|
10
|
-
'Manage received (inbound) emails — requires domain receiving to be enabled',
|
|
11
|
-
)
|
|
12
|
-
.addHelpText(
|
|
13
|
-
'after',
|
|
14
|
-
buildHelpText({
|
|
15
|
-
context:
|
|
16
|
-
'Receiving must be enabled on the domain first:\n resend domains update <id> --receiving enabled',
|
|
17
|
-
examples: [
|
|
18
|
-
'resend emails receiving list',
|
|
19
|
-
'resend emails receiving get <email-id>',
|
|
20
|
-
'resend emails receiving attachments <email-id>',
|
|
21
|
-
'resend emails receiving attachment <email-id> <attachment-id>',
|
|
22
|
-
],
|
|
23
|
-
}),
|
|
24
|
-
)
|
|
25
|
-
.addCommand(listReceivingCommand, { isDefault: true })
|
|
26
|
-
.addCommand(getReceivingCommand)
|
|
27
|
-
.addCommand(listAttachmentsCommand)
|
|
28
|
-
.addCommand(getAttachmentCommand);
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runList } from '../../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../../lib/help-text';
|
|
5
|
-
import {
|
|
6
|
-
buildPaginationOpts,
|
|
7
|
-
parseLimitOpt,
|
|
8
|
-
printPaginationHint,
|
|
9
|
-
} from '../../../lib/pagination';
|
|
10
|
-
import { renderReceivingEmailsTable } from './utils';
|
|
11
|
-
|
|
12
|
-
export const listReceivingCommand = new Command('list')
|
|
13
|
-
.alias('ls')
|
|
14
|
-
.description(
|
|
15
|
-
'List received (inbound) emails for domains with receiving enabled',
|
|
16
|
-
)
|
|
17
|
-
.option('--limit <n>', 'Maximum number of emails to return (1-100)', '10')
|
|
18
|
-
.option('--after <cursor>', 'Return emails after this cursor (next page)')
|
|
19
|
-
.option(
|
|
20
|
-
'--before <cursor>',
|
|
21
|
-
'Return emails before this cursor (previous page)',
|
|
22
|
-
)
|
|
23
|
-
.addHelpText(
|
|
24
|
-
'after',
|
|
25
|
-
buildHelpText({
|
|
26
|
-
context:
|
|
27
|
-
'Receiving must be enabled on the domain first:\n resend domains update <id> --receiving enabled\n\nPagination: use --after or --before with a received email ID as the cursor.\nOnly one of --after or --before may be used at a time.\nThe response includes has_more: true when additional pages exist.',
|
|
28
|
-
output:
|
|
29
|
-
' {"object":"list","has_more":false,"data":[{"id":"<uuid>","to":["inbox@yourdomain.com"],"from":"sender@external.com","subject":"Hello","created_at":"<iso-date>","message_id":"<str>","bcc":null,"cc":null,"reply_to":null,"attachments":[]}]}',
|
|
30
|
-
errorCodes: ['auth_error', 'invalid_limit', 'list_error'],
|
|
31
|
-
examples: [
|
|
32
|
-
'resend emails receiving list',
|
|
33
|
-
'resend emails receiving list --limit 25 --json',
|
|
34
|
-
'resend emails receiving list --after <email-id> --json',
|
|
35
|
-
],
|
|
36
|
-
}),
|
|
37
|
-
)
|
|
38
|
-
.action(async (opts, cmd) => {
|
|
39
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
40
|
-
|
|
41
|
-
const limit = parseLimitOpt(opts.limit, globalOpts);
|
|
42
|
-
const paginationOpts = buildPaginationOpts(limit, opts.after, opts.before);
|
|
43
|
-
|
|
44
|
-
await runList(
|
|
45
|
-
{
|
|
46
|
-
spinner: {
|
|
47
|
-
loading: 'Fetching received emails...',
|
|
48
|
-
success: 'Received emails fetched',
|
|
49
|
-
fail: 'Failed to list received emails',
|
|
50
|
-
},
|
|
51
|
-
sdkCall: (resend) => resend.emails.receiving.list(paginationOpts),
|
|
52
|
-
onInteractive: (list) => {
|
|
53
|
-
console.log(renderReceivingEmailsTable(list.data));
|
|
54
|
-
printPaginationHint(list);
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
globalOpts,
|
|
58
|
-
);
|
|
59
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ListAttachmentsResponseSuccess,
|
|
3
|
-
ListReceivingEmail,
|
|
4
|
-
} from 'resend';
|
|
5
|
-
import { renderTable } from '../../../lib/table';
|
|
6
|
-
|
|
7
|
-
export function renderReceivingEmailsTable(
|
|
8
|
-
emails: ListReceivingEmail[],
|
|
9
|
-
): string {
|
|
10
|
-
const rows = emails.map((e) => {
|
|
11
|
-
const to = e.to.join(', ');
|
|
12
|
-
const toStr = to.length > 40 ? `${to.slice(0, 37)}...` : to;
|
|
13
|
-
const subject =
|
|
14
|
-
e.subject.length > 50 ? `${e.subject.slice(0, 47)}...` : e.subject;
|
|
15
|
-
return [e.from, toStr, subject, e.created_at, e.id];
|
|
16
|
-
});
|
|
17
|
-
return renderTable(
|
|
18
|
-
['From', 'To', 'Subject', 'Created At', 'ID'],
|
|
19
|
-
rows,
|
|
20
|
-
'(no received emails)',
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function renderAttachmentsTable(
|
|
25
|
-
attachments: ListAttachmentsResponseSuccess['data'],
|
|
26
|
-
): string {
|
|
27
|
-
const rows = attachments.map((a) => [
|
|
28
|
-
a.filename ?? '(unnamed)',
|
|
29
|
-
a.content_type,
|
|
30
|
-
String(a.size),
|
|
31
|
-
a.id,
|
|
32
|
-
]);
|
|
33
|
-
return renderTable(
|
|
34
|
-
['Filename', 'Content-Type', 'Size (bytes)', 'ID'],
|
|
35
|
-
rows,
|
|
36
|
-
'(no attachments)',
|
|
37
|
-
);
|
|
38
|
-
}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import * as p from '@clack/prompts';
|
|
2
|
-
import { Command } from '@commander-js/extra-typings';
|
|
3
|
-
import type { Resend } from 'resend';
|
|
4
|
-
import type { GlobalOpts } from '../../lib/client';
|
|
5
|
-
import { requireClient } from '../../lib/client';
|
|
6
|
-
import { readFile } from '../../lib/files';
|
|
7
|
-
import { buildHelpText } from '../../lib/help-text';
|
|
8
|
-
import { outputResult } from '../../lib/output';
|
|
9
|
-
import {
|
|
10
|
-
cancelAndExit,
|
|
11
|
-
promptForMissing,
|
|
12
|
-
requireText,
|
|
13
|
-
} from '../../lib/prompts';
|
|
14
|
-
import { withSpinner } from '../../lib/spinner';
|
|
15
|
-
import { isInteractive } from '../../lib/tty';
|
|
16
|
-
|
|
17
|
-
export async function fetchVerifiedDomains(resend: Resend): Promise<string[]> {
|
|
18
|
-
try {
|
|
19
|
-
const { data, error } = await resend.domains.list();
|
|
20
|
-
if (error || !data) {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
return data.data
|
|
24
|
-
.filter(
|
|
25
|
-
(d) => d.status === 'verified' && d.capabilities.sending === 'enabled',
|
|
26
|
-
)
|
|
27
|
-
.map((d) => d.name);
|
|
28
|
-
} catch {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const FROM_PREFIXES = ['noreply', 'hello', 'hi', 'info', 'support', 'team'];
|
|
34
|
-
|
|
35
|
-
async function promptForFromAddress(domains: string[]): Promise<string> {
|
|
36
|
-
let domain: string;
|
|
37
|
-
if (domains.length === 1) {
|
|
38
|
-
domain = domains[0];
|
|
39
|
-
} else {
|
|
40
|
-
const result = await p.select({
|
|
41
|
-
message: 'Select a verified domain',
|
|
42
|
-
options: domains.map((d) => ({ value: d, label: d })),
|
|
43
|
-
});
|
|
44
|
-
if (p.isCancel(result)) {
|
|
45
|
-
cancelAndExit('Send cancelled.');
|
|
46
|
-
}
|
|
47
|
-
domain = result;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const options: Array<{ value: string | null; label: string }> =
|
|
51
|
-
FROM_PREFIXES.map((prefix) => ({
|
|
52
|
-
value: `${prefix}@${domain}`,
|
|
53
|
-
label: `${prefix}@${domain}`,
|
|
54
|
-
}));
|
|
55
|
-
options.push({ value: null, label: 'Custom address...' });
|
|
56
|
-
|
|
57
|
-
const result = await p.select({
|
|
58
|
-
message: `From address (@${domain})`,
|
|
59
|
-
options,
|
|
60
|
-
});
|
|
61
|
-
if (p.isCancel(result)) {
|
|
62
|
-
cancelAndExit('Send cancelled.');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (result === null) {
|
|
66
|
-
const custom = await p.text({
|
|
67
|
-
message: 'From address',
|
|
68
|
-
placeholder: `you@${domain}`,
|
|
69
|
-
validate: (v) =>
|
|
70
|
-
!v || !v.includes('@') ? 'Enter a valid email address' : undefined,
|
|
71
|
-
});
|
|
72
|
-
if (p.isCancel(custom)) {
|
|
73
|
-
cancelAndExit('Send cancelled.');
|
|
74
|
-
}
|
|
75
|
-
return custom;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return result;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const sendCommand = new Command('send')
|
|
82
|
-
.description('Send an email')
|
|
83
|
-
.option('--from <address>', 'Sender address (required)')
|
|
84
|
-
.option('--to <addresses...>', 'Recipient address(es) (required)')
|
|
85
|
-
.option('--subject <subject>', 'Email subject (required)')
|
|
86
|
-
.option('--html <html>', 'HTML body')
|
|
87
|
-
.option('--html-file <path>', 'Path to an HTML file for the body')
|
|
88
|
-
.option('--text <text>', 'Plain-text body')
|
|
89
|
-
.option('--cc <addresses...>', 'CC recipients')
|
|
90
|
-
.option('--bcc <addresses...>', 'BCC recipients')
|
|
91
|
-
.option('--reply-to <address>', 'Reply-to address')
|
|
92
|
-
.addHelpText(
|
|
93
|
-
'after',
|
|
94
|
-
buildHelpText({
|
|
95
|
-
context:
|
|
96
|
-
'Required: --from, --to, --subject, and one of --text | --html | --html-file',
|
|
97
|
-
output: ' {"id":"<email-id>"}',
|
|
98
|
-
errorCodes: ['auth_error', 'missing_body', 'send_error'],
|
|
99
|
-
examples: [
|
|
100
|
-
'resend emails send --from you@domain.com --to user@example.com --subject "Hello" --text "Hi"',
|
|
101
|
-
'resend emails send --from you@domain.com --to a@example.com --to b@example.com --subject "Hi" --html "<b>Hi</b>" --json',
|
|
102
|
-
'resend emails send --from you@domain.com --to user@example.com --subject "Hi" --html-file ./email.html --json',
|
|
103
|
-
'RESEND_API_KEY=re_123 resend emails send --from you@domain.com --to user@example.com --subject "Hi" --text "Hi"',
|
|
104
|
-
],
|
|
105
|
-
}),
|
|
106
|
-
)
|
|
107
|
-
.action(async (opts, cmd) => {
|
|
108
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
109
|
-
|
|
110
|
-
const resend = requireClient(globalOpts);
|
|
111
|
-
|
|
112
|
-
// Only fetch verified domains in interactive mode — non-interactive
|
|
113
|
-
// callers (CI, agents, scripts) must pass --from explicitly.
|
|
114
|
-
let fromAddress = opts.from;
|
|
115
|
-
if (!fromAddress && isInteractive()) {
|
|
116
|
-
const domains = await fetchVerifiedDomains(resend);
|
|
117
|
-
if (domains.length > 0) {
|
|
118
|
-
fromAddress = await promptForFromAddress(domains);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const filled = await promptForMissing(
|
|
123
|
-
{ from: fromAddress, to: opts.to?.[0], subject: opts.subject },
|
|
124
|
-
[
|
|
125
|
-
{
|
|
126
|
-
flag: 'from',
|
|
127
|
-
message: 'From address',
|
|
128
|
-
placeholder: 'you@example.com',
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
flag: 'to',
|
|
132
|
-
message: 'To address',
|
|
133
|
-
placeholder: 'recipient@example.com',
|
|
134
|
-
},
|
|
135
|
-
{ flag: 'subject', message: 'Subject', placeholder: 'Hello!' },
|
|
136
|
-
],
|
|
137
|
-
globalOpts,
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
let html = opts.html;
|
|
141
|
-
const text = opts.text;
|
|
142
|
-
|
|
143
|
-
if (opts.htmlFile) {
|
|
144
|
-
html = readFile(opts.htmlFile, globalOpts);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let body: string | undefined = text;
|
|
148
|
-
if (!html && !text) {
|
|
149
|
-
body = await requireText(
|
|
150
|
-
undefined,
|
|
151
|
-
{
|
|
152
|
-
message: 'Email body (plain text)',
|
|
153
|
-
placeholder: 'Type your message...',
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
message: 'Missing email body. Provide --html, --html-file, or --text',
|
|
157
|
-
code: 'missing_body',
|
|
158
|
-
},
|
|
159
|
-
globalOpts,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const toAddresses = opts.to ?? [filled.to];
|
|
164
|
-
|
|
165
|
-
const data = await withSpinner(
|
|
166
|
-
{
|
|
167
|
-
loading: 'Sending email...',
|
|
168
|
-
success: 'Email sent',
|
|
169
|
-
fail: 'Failed to send email',
|
|
170
|
-
},
|
|
171
|
-
() =>
|
|
172
|
-
resend.emails.send({
|
|
173
|
-
from: filled.from,
|
|
174
|
-
to: toAddresses,
|
|
175
|
-
subject: filled.subject,
|
|
176
|
-
...(html ? { html } : { text: body as string }),
|
|
177
|
-
...(opts.cc && { cc: opts.cc }),
|
|
178
|
-
...(opts.bcc && { bcc: opts.bcc }),
|
|
179
|
-
...(opts.replyTo && { replyTo: opts.replyTo }),
|
|
180
|
-
}),
|
|
181
|
-
'send_error',
|
|
182
|
-
globalOpts,
|
|
183
|
-
);
|
|
184
|
-
if (!globalOpts.json && isInteractive()) {
|
|
185
|
-
console.log(`\nEmail sent: ${data.id}`);
|
|
186
|
-
} else {
|
|
187
|
-
outputResult(data, { json: globalOpts.json });
|
|
188
|
-
}
|
|
189
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { buildHelpText } from '../lib/help-text';
|
|
3
|
-
|
|
4
|
-
export const openCommand = new Command('open')
|
|
5
|
-
.description('Open the Resend dashboard in your browser')
|
|
6
|
-
.addHelpText(
|
|
7
|
-
'after',
|
|
8
|
-
buildHelpText({
|
|
9
|
-
context: 'Opens https://resend.com/emails in your default browser.',
|
|
10
|
-
examples: ['resend open'],
|
|
11
|
-
}),
|
|
12
|
-
)
|
|
13
|
-
.action(async () => {
|
|
14
|
-
const url = 'https://resend.com/emails';
|
|
15
|
-
const { platform } = process;
|
|
16
|
-
const args =
|
|
17
|
-
platform === 'darwin'
|
|
18
|
-
? ['open', url]
|
|
19
|
-
: platform === 'win32'
|
|
20
|
-
? ['cmd', '/c', 'start', url]
|
|
21
|
-
: ['xdg-open', url];
|
|
22
|
-
|
|
23
|
-
Bun.spawn(args, { stdio: ['ignore', 'ignore', 'ignore'] });
|
|
24
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runCreate } from '../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../lib/help-text';
|
|
5
|
-
import { requireText } from '../../lib/prompts';
|
|
6
|
-
|
|
7
|
-
export const createSegmentCommand = new Command('create')
|
|
8
|
-
.description('Create a new segment')
|
|
9
|
-
.option('--name <name>', 'Segment name (required)')
|
|
10
|
-
.addHelpText(
|
|
11
|
-
'after',
|
|
12
|
-
buildHelpText({
|
|
13
|
-
context: `Segments are named groups of contacts. Broadcasts target segments via segment_id.
|
|
14
|
-
Contacts can belong to multiple segments. Audiences are deprecated — use segments instead.
|
|
15
|
-
|
|
16
|
-
Non-interactive: --name is required.`,
|
|
17
|
-
output: ` {"object":"segment","id":"<uuid>","name":"<name>"}`,
|
|
18
|
-
errorCodes: ['auth_error', 'missing_name', 'create_error'],
|
|
19
|
-
examples: [
|
|
20
|
-
'resend segments create --name "Newsletter Subscribers"',
|
|
21
|
-
'resend segments create --name "Beta Users" --json',
|
|
22
|
-
],
|
|
23
|
-
}),
|
|
24
|
-
)
|
|
25
|
-
.action(async (opts, cmd) => {
|
|
26
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
27
|
-
|
|
28
|
-
const name = await requireText(
|
|
29
|
-
opts.name,
|
|
30
|
-
{ message: 'Segment name', placeholder: 'Newsletter Subscribers' },
|
|
31
|
-
{ message: 'Missing --name flag.', code: 'missing_name' },
|
|
32
|
-
globalOpts,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
await runCreate(
|
|
36
|
-
{
|
|
37
|
-
spinner: {
|
|
38
|
-
loading: 'Creating segment...',
|
|
39
|
-
success: 'Segment created',
|
|
40
|
-
fail: 'Failed to create segment',
|
|
41
|
-
},
|
|
42
|
-
sdkCall: (resend) => resend.segments.create({ name }),
|
|
43
|
-
onInteractive: (data) => {
|
|
44
|
-
console.log(`\nSegment created: ${data.id}`);
|
|
45
|
-
console.log(`Name: ${data.name}`);
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
globalOpts,
|
|
49
|
-
);
|
|
50
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runDelete } from '../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../lib/help-text';
|
|
5
|
-
|
|
6
|
-
export const deleteSegmentCommand = new Command('delete')
|
|
7
|
-
.alias('rm')
|
|
8
|
-
.description('Delete a segment')
|
|
9
|
-
.argument('<id>', 'Segment UUID')
|
|
10
|
-
.option(
|
|
11
|
-
'--yes',
|
|
12
|
-
'Skip the confirmation prompt (required in non-interactive mode)',
|
|
13
|
-
)
|
|
14
|
-
.addHelpText(
|
|
15
|
-
'after',
|
|
16
|
-
buildHelpText({
|
|
17
|
-
context: `Warning: Deleting a segment removes it as a target for future broadcasts,
|
|
18
|
-
but does NOT delete the contacts within it.
|
|
19
|
-
|
|
20
|
-
Non-interactive: --yes is required to confirm deletion when stdin/stdout is not a TTY.`,
|
|
21
|
-
output: ` {"object":"segment","id":"<uuid>","deleted":true}`,
|
|
22
|
-
errorCodes: ['auth_error', 'confirmation_required', 'delete_error'],
|
|
23
|
-
examples: [
|
|
24
|
-
'resend segments delete 78261eea-8f8b-4381-83c6-79fa7120f1cf --yes',
|
|
25
|
-
'resend segments delete 78261eea-8f8b-4381-83c6-79fa7120f1cf --yes --json',
|
|
26
|
-
],
|
|
27
|
-
}),
|
|
28
|
-
)
|
|
29
|
-
.action(async (id, opts, cmd) => {
|
|
30
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
31
|
-
await runDelete(
|
|
32
|
-
id,
|
|
33
|
-
!!opts.yes,
|
|
34
|
-
{
|
|
35
|
-
confirmMessage: `Delete segment ${id}?\nContacts will not be deleted, but broadcasts targeting this segment will no longer work.`,
|
|
36
|
-
spinner: {
|
|
37
|
-
loading: 'Deleting segment...',
|
|
38
|
-
success: 'Segment deleted',
|
|
39
|
-
fail: 'Failed to delete segment',
|
|
40
|
-
},
|
|
41
|
-
object: 'segment',
|
|
42
|
-
successMsg: 'Segment deleted.',
|
|
43
|
-
sdkCall: (resend) => resend.segments.remove(id),
|
|
44
|
-
},
|
|
45
|
-
globalOpts,
|
|
46
|
-
);
|
|
47
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Command } from '@commander-js/extra-typings';
|
|
2
|
-
import { runGet } from '../../lib/actions';
|
|
3
|
-
import type { GlobalOpts } from '../../lib/client';
|
|
4
|
-
import { buildHelpText } from '../../lib/help-text';
|
|
5
|
-
|
|
6
|
-
export const getSegmentCommand = new Command('get')
|
|
7
|
-
.description('Retrieve a segment by ID')
|
|
8
|
-
.argument('<id>', 'Segment UUID')
|
|
9
|
-
.addHelpText(
|
|
10
|
-
'after',
|
|
11
|
-
buildHelpText({
|
|
12
|
-
output: ` {"object":"segment","id":"<uuid>","name":"<name>","created_at":"<iso-date>"}`,
|
|
13
|
-
errorCodes: ['auth_error', 'fetch_error'],
|
|
14
|
-
examples: [
|
|
15
|
-
'resend segments get 78261eea-8f8b-4381-83c6-79fa7120f1cf',
|
|
16
|
-
'resend segments get 78261eea-8f8b-4381-83c6-79fa7120f1cf --json',
|
|
17
|
-
],
|
|
18
|
-
}),
|
|
19
|
-
)
|
|
20
|
-
.action(async (id, _opts, cmd) => {
|
|
21
|
-
const globalOpts = cmd.optsWithGlobals() as GlobalOpts;
|
|
22
|
-
await runGet(
|
|
23
|
-
{
|
|
24
|
-
spinner: {
|
|
25
|
-
loading: 'Fetching segment...',
|
|
26
|
-
success: 'Segment fetched',
|
|
27
|
-
fail: 'Failed to fetch segment',
|
|
28
|
-
},
|
|
29
|
-
sdkCall: (resend) => resend.segments.get(id),
|
|
30
|
-
onInteractive: (data) => {
|
|
31
|
-
console.log(`\n${data.name}`);
|
|
32
|
-
console.log(`ID: ${data.id}`);
|
|
33
|
-
console.log(`Created: ${data.created_at}`);
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
globalOpts,
|
|
37
|
-
);
|
|
38
|
-
});
|