groundmail-cli 0.18.1 → 0.20.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/dist/cli.js +182 -113
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -69,6 +69,9 @@ async function runSendCommand(args, deps) {
|
|
|
69
69
|
unsubscribe: options.unsubscribe
|
|
70
70
|
});
|
|
71
71
|
stdout(JSON.stringify(result));
|
|
72
|
+
if (result.test) {
|
|
73
|
+
stderr("Test send: simulated, nothing was delivered. Its status and webhooks are marked test.");
|
|
74
|
+
}
|
|
72
75
|
return 0;
|
|
73
76
|
} catch (error) {
|
|
74
77
|
stderr(error instanceof Error ? error.message : String(error));
|
|
@@ -109,8 +112,8 @@ function createDefaultSendDeps(apiKey, baseUrl) {
|
|
|
109
112
|
return {
|
|
110
113
|
sendEmail: async (params) => {
|
|
111
114
|
const { Groundmail } = await import("groundmail");
|
|
112
|
-
const
|
|
113
|
-
return
|
|
115
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
116
|
+
return client2.emails.send(params);
|
|
114
117
|
}
|
|
115
118
|
};
|
|
116
119
|
}
|
|
@@ -179,10 +182,10 @@ async function runBatchCommandWithClient(args, env = process.env) {
|
|
|
179
182
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
180
183
|
}
|
|
181
184
|
const { Groundmail } = await import("groundmail");
|
|
182
|
-
const
|
|
185
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
183
186
|
return runBatchCommand(args, {
|
|
184
187
|
env,
|
|
185
|
-
sendBatch: (emails) =>
|
|
188
|
+
sendBatch: (emails) => client2.emails.batch(emails)
|
|
186
189
|
});
|
|
187
190
|
}
|
|
188
191
|
function parseBatchPayload(source) {
|
|
@@ -235,10 +238,10 @@ async function runCancelCommandWithClient(args, env = process.env) {
|
|
|
235
238
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
236
239
|
}
|
|
237
240
|
const { Groundmail } = await import("groundmail");
|
|
238
|
-
const
|
|
241
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
239
242
|
return runCancelCommand(args, {
|
|
240
243
|
env,
|
|
241
|
-
cancelEmail: (id) =>
|
|
244
|
+
cancelEmail: (id) => client2.emails.cancel(id)
|
|
242
245
|
});
|
|
243
246
|
}
|
|
244
247
|
|
|
@@ -278,10 +281,10 @@ async function runResendCommandWithClient(args, env = process.env) {
|
|
|
278
281
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
279
282
|
}
|
|
280
283
|
const { Groundmail } = await import("groundmail");
|
|
281
|
-
const
|
|
284
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
282
285
|
return runResendCommand(args, {
|
|
283
286
|
env,
|
|
284
|
-
resendEmail: (id) =>
|
|
287
|
+
resendEmail: (id) => client2.emails.resend(id)
|
|
285
288
|
});
|
|
286
289
|
}
|
|
287
290
|
|
|
@@ -321,10 +324,10 @@ async function runGetCommandWithClient(args, env = process.env) {
|
|
|
321
324
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
322
325
|
}
|
|
323
326
|
const { Groundmail } = await import("groundmail");
|
|
324
|
-
const
|
|
327
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
325
328
|
return runGetCommand(args, {
|
|
326
329
|
env,
|
|
327
|
-
getEmail: (id) =>
|
|
330
|
+
getEmail: (id) => client2.emails.get(id)
|
|
328
331
|
});
|
|
329
332
|
}
|
|
330
333
|
|
|
@@ -364,10 +367,10 @@ async function runInsightsCommandWithClient(args, env = process.env) {
|
|
|
364
367
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
365
368
|
}
|
|
366
369
|
const { Groundmail } = await import("groundmail");
|
|
367
|
-
const
|
|
370
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
368
371
|
return runInsightsCommand(args, {
|
|
369
372
|
env,
|
|
370
|
-
getInsights: (window) =>
|
|
373
|
+
getInsights: (window) => client2.emails.insights(window)
|
|
371
374
|
});
|
|
372
375
|
}
|
|
373
376
|
|
|
@@ -389,10 +392,16 @@ async function runListCommand(args, deps) {
|
|
|
389
392
|
const limitRaw = readFlag7(args, "--limit");
|
|
390
393
|
const cursor = readFlag7(args, "--cursor");
|
|
391
394
|
const limit = limitRaw ? Number(limitRaw) : void 0;
|
|
395
|
+
if (args.includes("--test") && args.includes("--live")) {
|
|
396
|
+
stderr("Pass --test or --live, not both.");
|
|
397
|
+
return { exitCode: 1, error: "conflicting flags" };
|
|
398
|
+
}
|
|
399
|
+
const test = args.includes("--test") ? true : args.includes("--live") ? false : void 0;
|
|
392
400
|
try {
|
|
393
401
|
const result = await deps.listEmails({
|
|
394
402
|
...limit != null && Number.isFinite(limit) ? { limit } : {},
|
|
395
|
-
...cursor ? { cursor } : {}
|
|
403
|
+
...cursor ? { cursor } : {},
|
|
404
|
+
...test !== void 0 ? { test } : {}
|
|
396
405
|
});
|
|
397
406
|
stdout(JSON.stringify(result));
|
|
398
407
|
return { exitCode: 0 };
|
|
@@ -408,10 +417,10 @@ async function runListCommandWithClient(args, env = process.env) {
|
|
|
408
417
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
409
418
|
}
|
|
410
419
|
const { Groundmail } = await import("groundmail");
|
|
411
|
-
const
|
|
420
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
412
421
|
return runListCommand(args, {
|
|
413
422
|
env,
|
|
414
|
-
listEmails: (params) =>
|
|
423
|
+
listEmails: (params) => client2.emails.list(params)
|
|
415
424
|
});
|
|
416
425
|
}
|
|
417
426
|
|
|
@@ -458,8 +467,8 @@ async function runSendEventCommand(args, env = process.env) {
|
|
|
458
467
|
}
|
|
459
468
|
}
|
|
460
469
|
try {
|
|
461
|
-
const
|
|
462
|
-
const result = await
|
|
470
|
+
const client2 = await createClient(apiKey, baseUrl);
|
|
471
|
+
const result = await client2.events.trigger({
|
|
463
472
|
name,
|
|
464
473
|
email,
|
|
465
474
|
user_id: userId,
|
|
@@ -542,8 +551,8 @@ async function runListCommand2(args, env = process.env) {
|
|
|
542
551
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
543
552
|
}
|
|
544
553
|
try {
|
|
545
|
-
const
|
|
546
|
-
const result = await
|
|
554
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
555
|
+
const result = await client2.automations.list();
|
|
547
556
|
console.log(JSON.stringify(result));
|
|
548
557
|
return { exitCode: 0 };
|
|
549
558
|
} catch (error) {
|
|
@@ -561,8 +570,8 @@ async function runGetCommand2(args, env = process.env) {
|
|
|
561
570
|
const id = readFlag9(args, "--id");
|
|
562
571
|
if (!id) return { exitCode: 1, error: "Required flag: --id" };
|
|
563
572
|
try {
|
|
564
|
-
const
|
|
565
|
-
const result = await
|
|
573
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
574
|
+
const result = await client2.automations.get(id);
|
|
566
575
|
console.log(JSON.stringify(result));
|
|
567
576
|
return { exitCode: 0 };
|
|
568
577
|
} catch (error) {
|
|
@@ -590,8 +599,8 @@ async function runCreateCommand(args, env = process.env) {
|
|
|
590
599
|
return { exitCode: 1, error: "Required: --steps or steps in --file" };
|
|
591
600
|
}
|
|
592
601
|
try {
|
|
593
|
-
const
|
|
594
|
-
const result = await
|
|
602
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
603
|
+
const result = await client2.automations.create({
|
|
595
604
|
name,
|
|
596
605
|
trigger,
|
|
597
606
|
steps
|
|
@@ -622,8 +631,8 @@ async function runUpdateCommand(args, env = process.env) {
|
|
|
622
631
|
};
|
|
623
632
|
}
|
|
624
633
|
try {
|
|
625
|
-
const
|
|
626
|
-
const result = await
|
|
634
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
635
|
+
const result = await client2.automations.update(id, {
|
|
627
636
|
...name ? { name } : {},
|
|
628
637
|
...trigger ? { trigger } : {},
|
|
629
638
|
...steps ? { steps } : {}
|
|
@@ -645,8 +654,8 @@ async function runActivateCommand(args, env = process.env) {
|
|
|
645
654
|
const id = readFlag9(args, "--id");
|
|
646
655
|
if (!id) return { exitCode: 1, error: "Required flag: --id" };
|
|
647
656
|
try {
|
|
648
|
-
const
|
|
649
|
-
const result = await
|
|
657
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
658
|
+
const result = await client2.automations.activate(id);
|
|
650
659
|
console.log(JSON.stringify(result));
|
|
651
660
|
return { exitCode: 0 };
|
|
652
661
|
} catch (error) {
|
|
@@ -662,8 +671,8 @@ async function runPauseCommand(args, env = process.env) {
|
|
|
662
671
|
const id = readFlag9(args, "--id");
|
|
663
672
|
if (!id) return { exitCode: 1, error: "Required flag: --id" };
|
|
664
673
|
try {
|
|
665
|
-
const
|
|
666
|
-
const result = await
|
|
674
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
675
|
+
const result = await client2.automations.pause(id);
|
|
667
676
|
console.log(JSON.stringify(result));
|
|
668
677
|
return { exitCode: 0 };
|
|
669
678
|
} catch (error) {
|
|
@@ -679,8 +688,8 @@ async function runDeleteCommand(args, env = process.env) {
|
|
|
679
688
|
const id = readFlag9(args, "--id");
|
|
680
689
|
if (!id) return { exitCode: 1, error: "Required flag: --id" };
|
|
681
690
|
try {
|
|
682
|
-
const
|
|
683
|
-
const result = await
|
|
691
|
+
const client2 = await createAutomationsClient(apiKey, options.baseUrl);
|
|
692
|
+
const result = await client2.automations.remove(id);
|
|
684
693
|
console.log(JSON.stringify(result));
|
|
685
694
|
return { exitCode: 0 };
|
|
686
695
|
} catch (error) {
|
|
@@ -740,9 +749,9 @@ async function runAddCommand(args, env = process.env) {
|
|
|
740
749
|
};
|
|
741
750
|
}
|
|
742
751
|
try {
|
|
743
|
-
const
|
|
752
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
744
753
|
const inbound = readFlag10(args, "--inbound");
|
|
745
|
-
const result = await
|
|
754
|
+
const result = await client2.domains.create({
|
|
746
755
|
name,
|
|
747
756
|
...inbound === "true" || inbound === "1" ? { inbound_enabled: true } : {}
|
|
748
757
|
});
|
|
@@ -788,12 +797,12 @@ async function runApplyCommand(args, env = process.env) {
|
|
|
788
797
|
};
|
|
789
798
|
}
|
|
790
799
|
try {
|
|
791
|
-
const
|
|
800
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
792
801
|
const localCloudflare = env.CLOUDFLARE_API_TOKEN || env.CLOUDFLARE_API_KEY;
|
|
793
802
|
const localVercel = env.VERCEL_API_TOKEN;
|
|
794
803
|
const useStoredCloudflare = provider === "cloudflare" && !localCloudflare;
|
|
795
804
|
const useStoredVercel = provider === "vercel" && !localVercel;
|
|
796
|
-
const result = useStoredCloudflare || useStoredVercel ? await
|
|
805
|
+
const result = useStoredCloudflare || useStoredVercel ? await client2.domains.apply(idOrName, { provider }) : await client2.domains.applyDns({
|
|
797
806
|
idOrName,
|
|
798
807
|
provider,
|
|
799
808
|
cloudflareApiToken: localCloudflare,
|
|
@@ -827,8 +836,8 @@ async function runDeleteCommand2(args, env = process.env) {
|
|
|
827
836
|
const idOrName = options.id || options.name || readFirstPositional2(args);
|
|
828
837
|
if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains delete example.com" };
|
|
829
838
|
try {
|
|
830
|
-
const
|
|
831
|
-
console.log(JSON.stringify(await
|
|
839
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
840
|
+
console.log(JSON.stringify(await client2.domains.delete(idOrName)));
|
|
832
841
|
return { exitCode: 0 };
|
|
833
842
|
} catch (error) {
|
|
834
843
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -855,8 +864,8 @@ async function runGetCommand3(args, env = process.env) {
|
|
|
855
864
|
const idOrName = options.id || options.name || readFirstPositional3(args);
|
|
856
865
|
if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains get example.com" };
|
|
857
866
|
try {
|
|
858
|
-
const
|
|
859
|
-
console.log(JSON.stringify(await
|
|
867
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
868
|
+
console.log(JSON.stringify(await client2.domains.get(idOrName)));
|
|
860
869
|
return { exitCode: 0 };
|
|
861
870
|
} catch (error) {
|
|
862
871
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -882,8 +891,8 @@ async function runListCommand3(args, env = process.env) {
|
|
|
882
891
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
883
892
|
}
|
|
884
893
|
try {
|
|
885
|
-
const
|
|
886
|
-
const result = await
|
|
894
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
895
|
+
const result = await client2.domains.list();
|
|
887
896
|
console.log(JSON.stringify(result));
|
|
888
897
|
return { exitCode: 0 };
|
|
889
898
|
} catch (error) {
|
|
@@ -954,8 +963,8 @@ async function runUpdateCommand2(args, env = process.env) {
|
|
|
954
963
|
error: "No updates provided. Pass --inbound true|false, --tls-mode opportunistic|enforced, --open-tracking true|false, or --click-tracking true|false."
|
|
955
964
|
};
|
|
956
965
|
}
|
|
957
|
-
const
|
|
958
|
-
console.log(JSON.stringify(await
|
|
966
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
967
|
+
console.log(JSON.stringify(await client2.domains.update(idOrName, payload)));
|
|
959
968
|
return { exitCode: 0 };
|
|
960
969
|
} catch (error) {
|
|
961
970
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -977,8 +986,8 @@ async function runVerifyCommand(args, env = process.env) {
|
|
|
977
986
|
};
|
|
978
987
|
}
|
|
979
988
|
try {
|
|
980
|
-
const
|
|
981
|
-
const result = await
|
|
989
|
+
const client2 = await createDomainsClient(apiKey, options.baseUrl);
|
|
990
|
+
const result = await client2.domains.verify(idOrName);
|
|
982
991
|
console.log(JSON.stringify(result));
|
|
983
992
|
if (result.verified) {
|
|
984
993
|
console.error(`Domain ${result.domain.name} verified.`);
|
|
@@ -1034,8 +1043,8 @@ async function runGetCommand4(args, env = process.env) {
|
|
|
1034
1043
|
return { exitCode: 1, error: "Missing id. Usage: groundmail received-emails get inb_..." };
|
|
1035
1044
|
}
|
|
1036
1045
|
try {
|
|
1037
|
-
const
|
|
1038
|
-
console.log(JSON.stringify(await
|
|
1046
|
+
const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
|
|
1047
|
+
console.log(JSON.stringify(await client2.receivedEmails.get(id)));
|
|
1039
1048
|
return { exitCode: 0 };
|
|
1040
1049
|
} catch (error) {
|
|
1041
1050
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -1050,10 +1059,10 @@ async function runListCommand4(args, env = process.env) {
|
|
|
1050
1059
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
1051
1060
|
}
|
|
1052
1061
|
try {
|
|
1053
|
-
const
|
|
1062
|
+
const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
|
|
1054
1063
|
console.log(
|
|
1055
1064
|
JSON.stringify(
|
|
1056
|
-
await
|
|
1065
|
+
await client2.receivedEmails.list({
|
|
1057
1066
|
limit: readFlag11(args, "--limit") ? Number(readFlag11(args, "--limit")) : void 0,
|
|
1058
1067
|
cursor: readFlag11(args, "--cursor"),
|
|
1059
1068
|
domain: readFlag11(args, "--domain")
|
|
@@ -1098,8 +1107,8 @@ async function runCreateCommand2(args, env = process.env) {
|
|
|
1098
1107
|
return { exitCode: 1, error: "Required flag: --url" };
|
|
1099
1108
|
}
|
|
1100
1109
|
try {
|
|
1101
|
-
const
|
|
1102
|
-
const result = await
|
|
1110
|
+
const client2 = await createWebhooksClient(apiKey, options.baseUrl);
|
|
1111
|
+
const result = await client2.webhooks.create({ url });
|
|
1103
1112
|
console.log(JSON.stringify(result));
|
|
1104
1113
|
return { exitCode: 0 };
|
|
1105
1114
|
} catch (error) {
|
|
@@ -1116,8 +1125,8 @@ async function runGetCommand5(args, env = process.env) {
|
|
|
1116
1125
|
const id = readFlag13(args, "--id") || readFirstPositional6(args);
|
|
1117
1126
|
if (!id) return { exitCode: 1, error: "Missing webhook id. Pass --id wh_\u2026" };
|
|
1118
1127
|
try {
|
|
1119
|
-
const
|
|
1120
|
-
console.log(JSON.stringify(await
|
|
1128
|
+
const client2 = await createWebhooksClient(apiKey, options.baseUrl);
|
|
1129
|
+
console.log(JSON.stringify(await client2.webhooks.get(id)));
|
|
1121
1130
|
return { exitCode: 0 };
|
|
1122
1131
|
} catch (error) {
|
|
1123
1132
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -1151,8 +1160,8 @@ async function runDeleteCommand3(args, env = process.env) {
|
|
|
1151
1160
|
return { exitCode: 1, error: "Required flag: --id" };
|
|
1152
1161
|
}
|
|
1153
1162
|
try {
|
|
1154
|
-
const
|
|
1155
|
-
const result = await
|
|
1163
|
+
const client2 = await createWebhooksClient(apiKey, options.baseUrl);
|
|
1164
|
+
const result = await client2.webhooks.delete(id);
|
|
1156
1165
|
console.log(JSON.stringify(result));
|
|
1157
1166
|
return { exitCode: 0 };
|
|
1158
1167
|
} catch (error) {
|
|
@@ -1168,8 +1177,8 @@ async function runListCommand5(args, env = process.env) {
|
|
|
1168
1177
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
1169
1178
|
}
|
|
1170
1179
|
try {
|
|
1171
|
-
const
|
|
1172
|
-
const result = await
|
|
1180
|
+
const client2 = await createWebhooksClient(apiKey, options.baseUrl);
|
|
1181
|
+
const result = await client2.webhooks.list();
|
|
1173
1182
|
console.log(JSON.stringify(result));
|
|
1174
1183
|
return { exitCode: 0 };
|
|
1175
1184
|
} catch (error) {
|
|
@@ -1198,8 +1207,8 @@ async function runUpdateCommand3(args, env = process.env) {
|
|
|
1198
1207
|
...enabled.value !== void 0 ? { enabled: enabled.value } : {}
|
|
1199
1208
|
};
|
|
1200
1209
|
try {
|
|
1201
|
-
const
|
|
1202
|
-
console.log(JSON.stringify(await
|
|
1210
|
+
const client2 = await createWebhooksClient(apiKey, options.baseUrl);
|
|
1211
|
+
console.log(JSON.stringify(await client2.webhooks.update(id, payload)));
|
|
1203
1212
|
return { exitCode: 0 };
|
|
1204
1213
|
} catch (error) {
|
|
1205
1214
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -1247,11 +1256,11 @@ async function runListKeysCommandWithClient(args, env = process.env) {
|
|
|
1247
1256
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
1248
1257
|
}
|
|
1249
1258
|
const { Groundmail } = await import("groundmail");
|
|
1250
|
-
const
|
|
1259
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
1251
1260
|
try {
|
|
1252
1261
|
const limitRaw = readFlag15(args, "--limit");
|
|
1253
1262
|
const cursor = readFlag15(args, "--cursor");
|
|
1254
|
-
const result = await
|
|
1263
|
+
const result = await client2.apiKeys.list({
|
|
1255
1264
|
...limitRaw ? { limit: Number(limitRaw) } : {},
|
|
1256
1265
|
...cursor ? { cursor } : {}
|
|
1257
1266
|
});
|
|
@@ -1288,7 +1297,7 @@ function trimUrl(value) {
|
|
|
1288
1297
|
}
|
|
1289
1298
|
|
|
1290
1299
|
// package.json
|
|
1291
|
-
var version = "0.
|
|
1300
|
+
var version = "0.20.0";
|
|
1292
1301
|
|
|
1293
1302
|
// src/user-agent.ts
|
|
1294
1303
|
function buildUserAgent(own) {
|
|
@@ -2146,6 +2155,7 @@ async function runCreateKeyCommandWithClient(args, env = process.env) {
|
|
|
2146
2155
|
if (scopes && !scopes.ok) return { exitCode: 1, error: scopes.error };
|
|
2147
2156
|
const domainsFlag = readFlag16(args, "--allowed-domains");
|
|
2148
2157
|
const allowedDomains = domainsFlag?.split(/[\s,]+/).map((domain) => domain.trim()).filter(Boolean);
|
|
2158
|
+
const test = args.includes("--test");
|
|
2149
2159
|
try {
|
|
2150
2160
|
const response = await apiRequest(baseUrl, "/api-keys", {
|
|
2151
2161
|
apiKey,
|
|
@@ -2154,13 +2164,17 @@ async function runCreateKeyCommandWithClient(args, env = process.env) {
|
|
|
2154
2164
|
...name ? { name } : {},
|
|
2155
2165
|
...scope && !scopes ? { scope } : {},
|
|
2156
2166
|
...scopes?.ok ? { scopes: scopes.scope.split(" ") } : {},
|
|
2157
|
-
...allowedDomains?.length ? { allowed_domains: allowedDomains } : {}
|
|
2167
|
+
...allowedDomains?.length ? { allowed_domains: allowedDomains } : {},
|
|
2168
|
+
...test ? { test: true } : {}
|
|
2158
2169
|
}
|
|
2159
2170
|
});
|
|
2160
2171
|
if (!response.ok) {
|
|
2161
2172
|
return { exitCode: 1, error: errorMessage(response, "Could not create the key") };
|
|
2162
2173
|
}
|
|
2163
2174
|
console.log(JSON.stringify(response.body));
|
|
2175
|
+
if (test) {
|
|
2176
|
+
console.error("Test key: sends with it run every check and fire webhooks, but nothing is delivered. https://docs.groundmail.dev/testing");
|
|
2177
|
+
}
|
|
2164
2178
|
return { exitCode: 0 };
|
|
2165
2179
|
} catch (error) {
|
|
2166
2180
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2184,9 +2198,9 @@ async function runDeleteKeyCommandWithClient(args, env = process.env) {
|
|
|
2184
2198
|
return { exitCode: 1, error: "Required: --id <api-key-id>" };
|
|
2185
2199
|
}
|
|
2186
2200
|
const { Groundmail } = await import("groundmail");
|
|
2187
|
-
const
|
|
2201
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
2188
2202
|
try {
|
|
2189
|
-
const result = await
|
|
2203
|
+
const result = await client2.apiKeys.remove(id);
|
|
2190
2204
|
console.log(JSON.stringify(result));
|
|
2191
2205
|
return { exitCode: 0 };
|
|
2192
2206
|
} catch (error) {
|
|
@@ -2224,11 +2238,11 @@ async function runListCommand6(args, env = process.env) {
|
|
|
2224
2238
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
2225
2239
|
}
|
|
2226
2240
|
try {
|
|
2227
|
-
const
|
|
2241
|
+
const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
|
|
2228
2242
|
const limitRaw = readFlag18(args, "--limit");
|
|
2229
2243
|
const cursor = readFlag18(args, "--cursor");
|
|
2230
2244
|
const email = readFlag18(args, "--email");
|
|
2231
|
-
const result = await
|
|
2245
|
+
const result = await client2.suppressions.list({
|
|
2232
2246
|
...limitRaw ? { limit: Number(limitRaw) } : {},
|
|
2233
2247
|
...cursor ? { cursor } : {},
|
|
2234
2248
|
...email ? { email } : {}
|
|
@@ -2252,9 +2266,9 @@ async function runAddCommand2(args, env = process.env) {
|
|
|
2252
2266
|
return { exitCode: 1, error: "Missing email. Pass --email user@example.com" };
|
|
2253
2267
|
}
|
|
2254
2268
|
try {
|
|
2255
|
-
const
|
|
2269
|
+
const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
|
|
2256
2270
|
const reason = readFlag18(args, "--reason");
|
|
2257
|
-
const result = await
|
|
2271
|
+
const result = await client2.suppressions.create({
|
|
2258
2272
|
email,
|
|
2259
2273
|
...reason ? { reason } : {}
|
|
2260
2274
|
});
|
|
@@ -2277,8 +2291,8 @@ async function runRemoveCommand(args, env = process.env) {
|
|
|
2277
2291
|
return { exitCode: 1, error: "Missing id or email. Pass --id <uuid> or --email user@example.com" };
|
|
2278
2292
|
}
|
|
2279
2293
|
try {
|
|
2280
|
-
const
|
|
2281
|
-
const result = await
|
|
2294
|
+
const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
|
|
2295
|
+
const result = await client2.suppressions.remove(idOrEmail);
|
|
2282
2296
|
console.log(JSON.stringify(result));
|
|
2283
2297
|
return { exitCode: 0 };
|
|
2284
2298
|
} catch (error) {
|
|
@@ -2315,8 +2329,8 @@ async function runDeleteCommand4(args, env = process.env) {
|
|
|
2315
2329
|
const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional8(args);
|
|
2316
2330
|
if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
|
|
2317
2331
|
try {
|
|
2318
|
-
const
|
|
2319
|
-
console.log(JSON.stringify(await
|
|
2332
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2333
|
+
console.log(JSON.stringify(await client2.templates.remove(idOrAlias)));
|
|
2320
2334
|
return { exitCode: 0 };
|
|
2321
2335
|
} catch (error) {
|
|
2322
2336
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2344,8 +2358,8 @@ async function runDuplicateCommand(args, env = process.env) {
|
|
|
2344
2358
|
if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
|
|
2345
2359
|
const name = readFlag19(args, "--name");
|
|
2346
2360
|
try {
|
|
2347
|
-
const
|
|
2348
|
-
console.log(JSON.stringify(await
|
|
2361
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2362
|
+
console.log(JSON.stringify(await client2.templates.duplicate(idOrAlias, name ? { name } : {})));
|
|
2349
2363
|
return { exitCode: 0 };
|
|
2350
2364
|
} catch (error) {
|
|
2351
2365
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2372,8 +2386,8 @@ async function runGetCommand6(args, env = process.env) {
|
|
|
2372
2386
|
const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional10(args);
|
|
2373
2387
|
if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
|
|
2374
2388
|
try {
|
|
2375
|
-
const
|
|
2376
|
-
console.log(JSON.stringify(await
|
|
2389
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2390
|
+
console.log(JSON.stringify(await client2.templates.get(idOrAlias)));
|
|
2377
2391
|
return { exitCode: 0 };
|
|
2378
2392
|
} catch (error) {
|
|
2379
2393
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2399,11 +2413,11 @@ async function runListCommand7(args, env = process.env) {
|
|
|
2399
2413
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
2400
2414
|
}
|
|
2401
2415
|
try {
|
|
2402
|
-
const
|
|
2416
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2403
2417
|
const limitRaw = readFlag19(args, "--limit");
|
|
2404
2418
|
const cursor = readFlag19(args, "--cursor");
|
|
2405
2419
|
const status = readFlag19(args, "--status");
|
|
2406
|
-
const result = await
|
|
2420
|
+
const result = await client2.templates.list({
|
|
2407
2421
|
...limitRaw ? { limit: Number(limitRaw) } : {},
|
|
2408
2422
|
...cursor ? { cursor } : {},
|
|
2409
2423
|
...status ? { status } : {}
|
|
@@ -2424,8 +2438,8 @@ async function runPublishCommand(args, env = process.env) {
|
|
|
2424
2438
|
const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional11(args);
|
|
2425
2439
|
if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
|
|
2426
2440
|
try {
|
|
2427
|
-
const
|
|
2428
|
-
console.log(JSON.stringify(await
|
|
2441
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2442
|
+
console.log(JSON.stringify(await client2.templates.publish(idOrAlias)));
|
|
2429
2443
|
return { exitCode: 0 };
|
|
2430
2444
|
} catch (error) {
|
|
2431
2445
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2600,10 +2614,10 @@ async function runPushCommand(args, env = process.env, deps = {}) {
|
|
|
2600
2614
|
return { exitCode: 1, error: `${file} produced no content to push.` };
|
|
2601
2615
|
}
|
|
2602
2616
|
const createClient2 = deps.createClient ?? createTemplatesClient;
|
|
2603
|
-
const
|
|
2617
|
+
const client2 = await createClient2(apiKey, options.baseUrl);
|
|
2604
2618
|
let existed = true;
|
|
2605
2619
|
try {
|
|
2606
|
-
await
|
|
2620
|
+
await client2.templates.get(alias);
|
|
2607
2621
|
} catch (error) {
|
|
2608
2622
|
if (statusOf(error) !== 404) throw error;
|
|
2609
2623
|
existed = false;
|
|
@@ -2618,7 +2632,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
|
|
|
2618
2632
|
};
|
|
2619
2633
|
let result;
|
|
2620
2634
|
if (existed) {
|
|
2621
|
-
result = await
|
|
2635
|
+
result = await client2.templates.update(alias, body);
|
|
2622
2636
|
} else {
|
|
2623
2637
|
if (!subject) {
|
|
2624
2638
|
return {
|
|
@@ -2626,7 +2640,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
|
|
|
2626
2640
|
error: `Template "${alias}" does not exist yet. Pass --subject to create it.`
|
|
2627
2641
|
};
|
|
2628
2642
|
}
|
|
2629
|
-
result = await
|
|
2643
|
+
result = await client2.templates.create({
|
|
2630
2644
|
name: name || alias,
|
|
2631
2645
|
subject,
|
|
2632
2646
|
alias,
|
|
@@ -2634,7 +2648,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
|
|
|
2634
2648
|
});
|
|
2635
2649
|
}
|
|
2636
2650
|
if (shouldPublish) {
|
|
2637
|
-
result = await
|
|
2651
|
+
result = await client2.templates.publish(alias);
|
|
2638
2652
|
}
|
|
2639
2653
|
console.log(JSON.stringify({ ...result, pushed: { file, alias, created: !existed } }));
|
|
2640
2654
|
return { exitCode: 0 };
|
|
@@ -2667,8 +2681,8 @@ async function runCreateCommand3(args, env = process.env) {
|
|
|
2667
2681
|
return { exitCode: 1, error: 'Missing body. Pass --html "<p>Hi</p>" or --text "Hi"' };
|
|
2668
2682
|
}
|
|
2669
2683
|
try {
|
|
2670
|
-
const
|
|
2671
|
-
const result = await
|
|
2684
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2685
|
+
const result = await client2.templates.create({
|
|
2672
2686
|
name,
|
|
2673
2687
|
subject,
|
|
2674
2688
|
...html ? { html } : {},
|
|
@@ -2723,8 +2737,8 @@ async function runUpdateCommand4(args, env = process.env) {
|
|
|
2723
2737
|
};
|
|
2724
2738
|
}
|
|
2725
2739
|
try {
|
|
2726
|
-
const
|
|
2727
|
-
const result = await
|
|
2740
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2741
|
+
const result = await client2.templates.update(idOrAlias, {
|
|
2728
2742
|
...name ? { name } : {},
|
|
2729
2743
|
...subject ? { subject } : {},
|
|
2730
2744
|
...html ? { html } : {},
|
|
@@ -2787,8 +2801,8 @@ async function runFromStarterCommand(args, env = process.env) {
|
|
|
2787
2801
|
};
|
|
2788
2802
|
}
|
|
2789
2803
|
try {
|
|
2790
|
-
const
|
|
2791
|
-
console.log(JSON.stringify(await
|
|
2804
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2805
|
+
console.log(JSON.stringify(await client2.templates.fromStarter(alias)));
|
|
2792
2806
|
return { exitCode: 0 };
|
|
2793
2807
|
} catch (error) {
|
|
2794
2808
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2801,8 +2815,8 @@ async function runListStartersCommand(args, env = process.env) {
|
|
|
2801
2815
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
2802
2816
|
}
|
|
2803
2817
|
try {
|
|
2804
|
-
const
|
|
2805
|
-
console.log(JSON.stringify(await
|
|
2818
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2819
|
+
console.log(JSON.stringify(await client2.templates.listStarters()));
|
|
2806
2820
|
return { exitCode: 0 };
|
|
2807
2821
|
} catch (error) {
|
|
2808
2822
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2833,8 +2847,8 @@ async function runVersionsCommand(args, env = process.env) {
|
|
|
2833
2847
|
return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
|
|
2834
2848
|
}
|
|
2835
2849
|
try {
|
|
2836
|
-
const
|
|
2837
|
-
console.log(JSON.stringify(await
|
|
2850
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2851
|
+
console.log(JSON.stringify(await client2.templates.listVersions(idOrAlias)));
|
|
2838
2852
|
return { exitCode: 0 };
|
|
2839
2853
|
} catch (error) {
|
|
2840
2854
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2856,8 +2870,8 @@ async function runRestoreCommand(args, env = process.env) {
|
|
|
2856
2870
|
};
|
|
2857
2871
|
}
|
|
2858
2872
|
try {
|
|
2859
|
-
const
|
|
2860
|
-
console.log(JSON.stringify(await
|
|
2873
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2874
|
+
console.log(JSON.stringify(await client2.templates.restoreVersion(idOrAlias, version2)));
|
|
2861
2875
|
return { exitCode: 0 };
|
|
2862
2876
|
} catch (error) {
|
|
2863
2877
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2879,8 +2893,8 @@ async function runTestSendCommand(args, env = process.env) {
|
|
|
2879
2893
|
};
|
|
2880
2894
|
}
|
|
2881
2895
|
try {
|
|
2882
|
-
const
|
|
2883
|
-
console.log(JSON.stringify(await
|
|
2896
|
+
const client2 = await createTemplatesClient(apiKey, options.baseUrl);
|
|
2897
|
+
console.log(JSON.stringify(await client2.templates.testSend(idOrAlias, { from, to })));
|
|
2884
2898
|
return { exitCode: 0 };
|
|
2885
2899
|
} catch (error) {
|
|
2886
2900
|
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -2915,8 +2929,8 @@ async function runTwilioStatusCommand(args, env = process.env) {
|
|
|
2915
2929
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
2916
2930
|
}
|
|
2917
2931
|
try {
|
|
2918
|
-
const
|
|
2919
|
-
const result = await
|
|
2932
|
+
const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
|
|
2933
|
+
const result = await client2.integrations.getTwilio();
|
|
2920
2934
|
console.log(JSON.stringify(result));
|
|
2921
2935
|
return { exitCode: 0 };
|
|
2922
2936
|
} catch (error) {
|
|
@@ -2946,8 +2960,8 @@ async function runTwilioConnectCommand(args, env = process.env) {
|
|
|
2946
2960
|
};
|
|
2947
2961
|
}
|
|
2948
2962
|
try {
|
|
2949
|
-
const
|
|
2950
|
-
const result = await
|
|
2963
|
+
const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
|
|
2964
|
+
const result = await client2.integrations.connectTwilio({
|
|
2951
2965
|
accountSid: accountSid.trim(),
|
|
2952
2966
|
authToken: authToken.trim(),
|
|
2953
2967
|
...defaultFrom.trim() ? { defaultFrom: defaultFrom.trim() } : {},
|
|
@@ -2966,8 +2980,8 @@ async function runTwilioDisconnectCommand(args, env = process.env) {
|
|
|
2966
2980
|
return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
|
|
2967
2981
|
}
|
|
2968
2982
|
try {
|
|
2969
|
-
const
|
|
2970
|
-
const result = await
|
|
2983
|
+
const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
|
|
2984
|
+
const result = await client2.integrations.disconnectTwilio();
|
|
2971
2985
|
console.log(JSON.stringify(result));
|
|
2972
2986
|
return { exitCode: 0 };
|
|
2973
2987
|
} catch (error) {
|
|
@@ -3120,6 +3134,7 @@ var KEY_ENV = {
|
|
|
3120
3134
|
mailgun: "MAILGUN_API_KEY"
|
|
3121
3135
|
};
|
|
3122
3136
|
var LABELS = { sendgrid: "SendGrid", postmark: "Postmark", mailgun: "Mailgun" };
|
|
3137
|
+
var VALUE_FLAGS2 = /* @__PURE__ */ new Set(["--api-key", "--base-url"]);
|
|
3123
3138
|
function readFlag21(args, flag) {
|
|
3124
3139
|
const index = args.indexOf(flag);
|
|
3125
3140
|
if (index === -1) return void 0;
|
|
@@ -3148,6 +3163,10 @@ function formatMigrationSummary(m) {
|
|
|
3148
3163
|
lines.push(
|
|
3149
3164
|
m.dry_run ? ` Suppressions ${n(s.found)}${m.suppressions.estimated ? "+ (first page of each list)" : ""}` : ` Suppressions ${n(s.imported)} added, ${n(s.already_suppressed)} already suppressed`
|
|
3150
3165
|
);
|
|
3166
|
+
if (s.product_opt_out) lines.push(` ${n(s.product_opt_out)} of them product email opt-outs (transactional mail still reaches them)`);
|
|
3167
|
+
for (const [reason, count] of Object.entries(m.suppressions.skipped_reasons)) {
|
|
3168
|
+
lines.push(` ${n(count)} skipped: ${reason}`);
|
|
3169
|
+
}
|
|
3151
3170
|
}
|
|
3152
3171
|
if (m.errors.length) {
|
|
3153
3172
|
lines.push("", "Could not read:");
|
|
@@ -3163,6 +3182,17 @@ function formatMigrationSummary(m) {
|
|
|
3163
3182
|
for (const line of failed.slice(0, 20)) lines.push(` ${line}`);
|
|
3164
3183
|
if (failed.length > 20) lines.push(` \u2026and ${failed.length - 20} more (see the JSON report)`);
|
|
3165
3184
|
}
|
|
3185
|
+
const plans = (m.domains?.items ?? []).filter((d) => d.dns_plan);
|
|
3186
|
+
for (const d of plans) {
|
|
3187
|
+
const changes = d.dns_plan.changes.filter((c) => c.action === "add" || c.action === "update");
|
|
3188
|
+
lines.push("", `DNS changes for ${d.name}${changes.length ? "" : ": all published"}`);
|
|
3189
|
+
for (const c of changes) {
|
|
3190
|
+
lines.push(` ${c.action === "update" ? "edit" : "add "} ${c.type.padEnd(5)} ${c.host} ${c.value}`);
|
|
3191
|
+
if (c.action === "update" && c.current) lines.push(` now: ${c.current}`);
|
|
3192
|
+
}
|
|
3193
|
+
for (const c of d.dns_plan.changes.filter((c2) => c2.action === "keep")) lines.push(` keep ${c.type.padEnd(5)} ${c.host} (yours)`);
|
|
3194
|
+
lines.push(` ${d.dns_plan.keep_old_records}`);
|
|
3195
|
+
}
|
|
3166
3196
|
if (m.attention.length) {
|
|
3167
3197
|
lines.push("", "Next:");
|
|
3168
3198
|
for (const line of m.attention) lines.push(` - ${line}`);
|
|
@@ -3170,11 +3200,48 @@ function formatMigrationSummary(m) {
|
|
|
3170
3200
|
const node = m.code_changes?.find((c) => c.stack === "node");
|
|
3171
3201
|
if (node) lines.push("", "Code change (Node.js):", node.diff);
|
|
3172
3202
|
if (m.agent_prompt) lines.push("", "Prompt for your coding agent is in the JSON report (`agent_prompt`).");
|
|
3203
|
+
if (!m.dry_run && !m.has_more) lines.push("", `Report: groundmail migrate report ${m.id} --csv > import-report.csv`);
|
|
3173
3204
|
return lines.join("\n");
|
|
3174
3205
|
}
|
|
3206
|
+
async function client(args, env) {
|
|
3207
|
+
const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
|
|
3208
|
+
if (!apiKey) return null;
|
|
3209
|
+
const { Groundmail } = await import("groundmail");
|
|
3210
|
+
const baseUrl = readFlag21(args, "--base-url");
|
|
3211
|
+
return new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
3212
|
+
}
|
|
3213
|
+
async function runStoredCommand(sub, args, env) {
|
|
3214
|
+
const gm = await client(args, env);
|
|
3215
|
+
if (!gm) return { exitCode: 1, error: "Not signed in. Run `groundmail login`, or set GROUNDMAIL_API_KEY." };
|
|
3216
|
+
try {
|
|
3217
|
+
if (sub === "list") {
|
|
3218
|
+
const { data } = await gm.migrations.list();
|
|
3219
|
+
console.log(JSON.stringify({ data }));
|
|
3220
|
+
for (const m of data) console.error(`${m.id} ${LABELS[m.provider]} ${m.status} ${m.started_at.slice(0, 10)}`);
|
|
3221
|
+
if (!data.length) console.error("No imports yet. Previews are not stored.");
|
|
3222
|
+
return { exitCode: 0 };
|
|
3223
|
+
}
|
|
3224
|
+
const id = args.find((arg, i) => !arg.startsWith("--") && !VALUE_FLAGS2.has(args[i - 1] ?? ""));
|
|
3225
|
+
if (!id) return { exitCode: 1, error: "Usage: groundmail migrate report <import id> [--csv]" };
|
|
3226
|
+
if (args.includes("--csv")) {
|
|
3227
|
+
process.stdout.write(await gm.migrations.reportCsv(id));
|
|
3228
|
+
return { exitCode: 0 };
|
|
3229
|
+
}
|
|
3230
|
+
const { migration } = await gm.migrations.get(id);
|
|
3231
|
+
console.log(JSON.stringify(migration));
|
|
3232
|
+
console.error(formatMigrationSummary(migration));
|
|
3233
|
+
return { exitCode: 0 };
|
|
3234
|
+
} catch (error) {
|
|
3235
|
+
return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3175
3238
|
async function runMigrateCommand(provider, args, env = process.env) {
|
|
3239
|
+
if (provider === "list" || provider === "report") return runStoredCommand(provider, args, env);
|
|
3176
3240
|
if (!provider || !PROVIDERS.includes(provider)) {
|
|
3177
|
-
return {
|
|
3241
|
+
return {
|
|
3242
|
+
exitCode: 1,
|
|
3243
|
+
error: "Usage: groundmail migrate <sendgrid|postmark|mailgun> [--dry-run] [--only templates,suppressions], groundmail migrate list, or groundmail migrate report <id> [--csv]"
|
|
3244
|
+
};
|
|
3178
3245
|
}
|
|
3179
3246
|
const id = provider;
|
|
3180
3247
|
const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
|
|
@@ -3210,9 +3277,9 @@ async function runMigrateCommand(provider, args, env = process.env) {
|
|
|
3210
3277
|
try {
|
|
3211
3278
|
const { Groundmail } = await import("groundmail");
|
|
3212
3279
|
const baseUrl = readFlag21(args, "--base-url");
|
|
3213
|
-
const
|
|
3280
|
+
const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
|
|
3214
3281
|
console.error(`${params.dry_run ? "Previewing" : "Importing"} from ${LABELS[id]} (Beta)\u2026`);
|
|
3215
|
-
const report = await
|
|
3282
|
+
const report = await client2.migrations.run(params, {
|
|
3216
3283
|
onProgress: (m) => {
|
|
3217
3284
|
if (m.has_more) {
|
|
3218
3285
|
const s = m.suppressions?.totals;
|
|
@@ -3242,8 +3309,8 @@ async function runValidateCommand(args, env = process.env) {
|
|
|
3242
3309
|
return { exitCode: 1, error: "Missing email. Usage: groundmail validate user@example.com" };
|
|
3243
3310
|
}
|
|
3244
3311
|
try {
|
|
3245
|
-
const
|
|
3246
|
-
const result = await
|
|
3312
|
+
const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
|
|
3313
|
+
const result = await client2.validate(email);
|
|
3247
3314
|
console.log(JSON.stringify(result));
|
|
3248
3315
|
return { exitCode: result.verdict === "invalid" ? 2 : 0 };
|
|
3249
3316
|
} catch (error) {
|
|
@@ -3272,7 +3339,7 @@ var USAGE_LINES = [
|
|
|
3272
3339
|
" groundmail received-emails get inb_...",
|
|
3273
3340
|
' groundmail emails send --from you@domain.com --to user@example.com --subject "Hello" --html "<p>Hi</p>" [--category transactional|product] [--unsubscribe]',
|
|
3274
3341
|
" groundmail emails batch --file ./emails.json",
|
|
3275
|
-
" groundmail emails list [--limit 25] [--cursor \u2026]",
|
|
3342
|
+
" groundmail emails list [--limit 25] [--cursor \u2026] [--test | --live]",
|
|
3276
3343
|
" groundmail emails insights [--window 7d|30d]",
|
|
3277
3344
|
" groundmail emails get --id msg_\u2026",
|
|
3278
3345
|
" groundmail emails cancel --id msg_\u2026",
|
|
@@ -3310,11 +3377,13 @@ var USAGE_LINES = [
|
|
|
3310
3377
|
' groundmail templates duplicate --id tpl_\u2026 [--name "Copy"]',
|
|
3311
3378
|
" groundmail templates delete --id tpl_\u2026",
|
|
3312
3379
|
" groundmail keys list",
|
|
3313
|
-
" groundmail keys create [--name Default] [--scopes emails:send,domains:read] [--allowed-domains example.com]",
|
|
3380
|
+
" groundmail keys create [--name Default] [--scopes emails:send,domains:read] [--allowed-domains example.com] [--test] --test: a gm_test_ key, sends are simulated",
|
|
3314
3381
|
" groundmail keys delete --id <api-key-id>",
|
|
3315
3382
|
" groundmail migrate sendgrid [--dry-run] [--only templates,suppressions,domains,webhooks] [--region eu] import from SendGrid (Beta)",
|
|
3316
3383
|
" groundmail migrate postmark [--dry-run] [--only \u2026] import from Postmark (Beta)",
|
|
3317
3384
|
" groundmail migrate mailgun [--dry-run] [--only \u2026] [--region eu] import from Mailgun (Beta)",
|
|
3385
|
+
" groundmail migrate list your recent imports",
|
|
3386
|
+
" groundmail migrate report <id> [--csv] an import report (JSON, or CSV to stdout)",
|
|
3318
3387
|
" groundmail integrations twilio status",
|
|
3319
3388
|
" groundmail integrations twilio connect --account-sid AC\u2026 --auth-token \u2026 --from +15551234567",
|
|
3320
3389
|
" groundmail integrations twilio disconnect"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groundmail-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Groundmail CLI — send transactional email from the terminal",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"prepublishOnly": "npm run build"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"groundmail": "0.
|
|
41
|
+
"groundmail": "0.17.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsup": "^8.5.0",
|