groundmail-cli 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +164 -109
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -109,8 +109,8 @@ function createDefaultSendDeps(apiKey, baseUrl) {
109
109
  return {
110
110
  sendEmail: async (params) => {
111
111
  const { Groundmail } = await import("groundmail");
112
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
113
- return client.emails.send(params);
112
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
113
+ return client2.emails.send(params);
114
114
  }
115
115
  };
116
116
  }
@@ -179,10 +179,10 @@ async function runBatchCommandWithClient(args, env = process.env) {
179
179
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
180
180
  }
181
181
  const { Groundmail } = await import("groundmail");
182
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
182
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
183
183
  return runBatchCommand(args, {
184
184
  env,
185
- sendBatch: (emails) => client.emails.batch(emails)
185
+ sendBatch: (emails) => client2.emails.batch(emails)
186
186
  });
187
187
  }
188
188
  function parseBatchPayload(source) {
@@ -235,10 +235,10 @@ async function runCancelCommandWithClient(args, env = process.env) {
235
235
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
236
236
  }
237
237
  const { Groundmail } = await import("groundmail");
238
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
238
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
239
239
  return runCancelCommand(args, {
240
240
  env,
241
- cancelEmail: (id) => client.emails.cancel(id)
241
+ cancelEmail: (id) => client2.emails.cancel(id)
242
242
  });
243
243
  }
244
244
 
@@ -278,10 +278,10 @@ async function runResendCommandWithClient(args, env = process.env) {
278
278
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
279
279
  }
280
280
  const { Groundmail } = await import("groundmail");
281
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
281
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
282
282
  return runResendCommand(args, {
283
283
  env,
284
- resendEmail: (id) => client.emails.resend(id)
284
+ resendEmail: (id) => client2.emails.resend(id)
285
285
  });
286
286
  }
287
287
 
@@ -321,10 +321,10 @@ async function runGetCommandWithClient(args, env = process.env) {
321
321
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
322
322
  }
323
323
  const { Groundmail } = await import("groundmail");
324
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
324
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
325
325
  return runGetCommand(args, {
326
326
  env,
327
- getEmail: (id) => client.emails.get(id)
327
+ getEmail: (id) => client2.emails.get(id)
328
328
  });
329
329
  }
330
330
 
@@ -364,10 +364,10 @@ async function runInsightsCommandWithClient(args, env = process.env) {
364
364
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
365
365
  }
366
366
  const { Groundmail } = await import("groundmail");
367
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
367
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
368
368
  return runInsightsCommand(args, {
369
369
  env,
370
- getInsights: (window) => client.emails.insights(window)
370
+ getInsights: (window) => client2.emails.insights(window)
371
371
  });
372
372
  }
373
373
 
@@ -408,10 +408,10 @@ async function runListCommandWithClient(args, env = process.env) {
408
408
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
409
409
  }
410
410
  const { Groundmail } = await import("groundmail");
411
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
411
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
412
412
  return runListCommand(args, {
413
413
  env,
414
- listEmails: (params) => client.emails.list(params)
414
+ listEmails: (params) => client2.emails.list(params)
415
415
  });
416
416
  }
417
417
 
@@ -458,8 +458,8 @@ async function runSendEventCommand(args, env = process.env) {
458
458
  }
459
459
  }
460
460
  try {
461
- const client = await createClient(apiKey, baseUrl);
462
- const result = await client.events.trigger({
461
+ const client2 = await createClient(apiKey, baseUrl);
462
+ const result = await client2.events.trigger({
463
463
  name,
464
464
  email,
465
465
  user_id: userId,
@@ -542,8 +542,8 @@ async function runListCommand2(args, env = process.env) {
542
542
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
543
543
  }
544
544
  try {
545
- const client = await createAutomationsClient(apiKey, options.baseUrl);
546
- const result = await client.automations.list();
545
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
546
+ const result = await client2.automations.list();
547
547
  console.log(JSON.stringify(result));
548
548
  return { exitCode: 0 };
549
549
  } catch (error) {
@@ -561,8 +561,8 @@ async function runGetCommand2(args, env = process.env) {
561
561
  const id = readFlag9(args, "--id");
562
562
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
563
563
  try {
564
- const client = await createAutomationsClient(apiKey, options.baseUrl);
565
- const result = await client.automations.get(id);
564
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
565
+ const result = await client2.automations.get(id);
566
566
  console.log(JSON.stringify(result));
567
567
  return { exitCode: 0 };
568
568
  } catch (error) {
@@ -590,8 +590,8 @@ async function runCreateCommand(args, env = process.env) {
590
590
  return { exitCode: 1, error: "Required: --steps or steps in --file" };
591
591
  }
592
592
  try {
593
- const client = await createAutomationsClient(apiKey, options.baseUrl);
594
- const result = await client.automations.create({
593
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
594
+ const result = await client2.automations.create({
595
595
  name,
596
596
  trigger,
597
597
  steps
@@ -622,8 +622,8 @@ async function runUpdateCommand(args, env = process.env) {
622
622
  };
623
623
  }
624
624
  try {
625
- const client = await createAutomationsClient(apiKey, options.baseUrl);
626
- const result = await client.automations.update(id, {
625
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
626
+ const result = await client2.automations.update(id, {
627
627
  ...name ? { name } : {},
628
628
  ...trigger ? { trigger } : {},
629
629
  ...steps ? { steps } : {}
@@ -645,8 +645,8 @@ async function runActivateCommand(args, env = process.env) {
645
645
  const id = readFlag9(args, "--id");
646
646
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
647
647
  try {
648
- const client = await createAutomationsClient(apiKey, options.baseUrl);
649
- const result = await client.automations.activate(id);
648
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
649
+ const result = await client2.automations.activate(id);
650
650
  console.log(JSON.stringify(result));
651
651
  return { exitCode: 0 };
652
652
  } catch (error) {
@@ -662,8 +662,8 @@ async function runPauseCommand(args, env = process.env) {
662
662
  const id = readFlag9(args, "--id");
663
663
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
664
664
  try {
665
- const client = await createAutomationsClient(apiKey, options.baseUrl);
666
- const result = await client.automations.pause(id);
665
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
666
+ const result = await client2.automations.pause(id);
667
667
  console.log(JSON.stringify(result));
668
668
  return { exitCode: 0 };
669
669
  } catch (error) {
@@ -679,8 +679,8 @@ async function runDeleteCommand(args, env = process.env) {
679
679
  const id = readFlag9(args, "--id");
680
680
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
681
681
  try {
682
- const client = await createAutomationsClient(apiKey, options.baseUrl);
683
- const result = await client.automations.remove(id);
682
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
683
+ const result = await client2.automations.remove(id);
684
684
  console.log(JSON.stringify(result));
685
685
  return { exitCode: 0 };
686
686
  } catch (error) {
@@ -740,9 +740,9 @@ async function runAddCommand(args, env = process.env) {
740
740
  };
741
741
  }
742
742
  try {
743
- const client = await createDomainsClient(apiKey, options.baseUrl);
743
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
744
744
  const inbound = readFlag10(args, "--inbound");
745
- const result = await client.domains.create({
745
+ const result = await client2.domains.create({
746
746
  name,
747
747
  ...inbound === "true" || inbound === "1" ? { inbound_enabled: true } : {}
748
748
  });
@@ -788,12 +788,12 @@ async function runApplyCommand(args, env = process.env) {
788
788
  };
789
789
  }
790
790
  try {
791
- const client = await createDomainsClient(apiKey, options.baseUrl);
791
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
792
792
  const localCloudflare = env.CLOUDFLARE_API_TOKEN || env.CLOUDFLARE_API_KEY;
793
793
  const localVercel = env.VERCEL_API_TOKEN;
794
794
  const useStoredCloudflare = provider === "cloudflare" && !localCloudflare;
795
795
  const useStoredVercel = provider === "vercel" && !localVercel;
796
- const result = useStoredCloudflare || useStoredVercel ? await client.domains.apply(idOrName, { provider }) : await client.domains.applyDns({
796
+ const result = useStoredCloudflare || useStoredVercel ? await client2.domains.apply(idOrName, { provider }) : await client2.domains.applyDns({
797
797
  idOrName,
798
798
  provider,
799
799
  cloudflareApiToken: localCloudflare,
@@ -827,8 +827,8 @@ async function runDeleteCommand2(args, env = process.env) {
827
827
  const idOrName = options.id || options.name || readFirstPositional2(args);
828
828
  if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains delete example.com" };
829
829
  try {
830
- const client = await createDomainsClient(apiKey, options.baseUrl);
831
- console.log(JSON.stringify(await client.domains.delete(idOrName)));
830
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
831
+ console.log(JSON.stringify(await client2.domains.delete(idOrName)));
832
832
  return { exitCode: 0 };
833
833
  } catch (error) {
834
834
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -855,8 +855,8 @@ async function runGetCommand3(args, env = process.env) {
855
855
  const idOrName = options.id || options.name || readFirstPositional3(args);
856
856
  if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains get example.com" };
857
857
  try {
858
- const client = await createDomainsClient(apiKey, options.baseUrl);
859
- console.log(JSON.stringify(await client.domains.get(idOrName)));
858
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
859
+ console.log(JSON.stringify(await client2.domains.get(idOrName)));
860
860
  return { exitCode: 0 };
861
861
  } catch (error) {
862
862
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -882,8 +882,8 @@ async function runListCommand3(args, env = process.env) {
882
882
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
883
883
  }
884
884
  try {
885
- const client = await createDomainsClient(apiKey, options.baseUrl);
886
- const result = await client.domains.list();
885
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
886
+ const result = await client2.domains.list();
887
887
  console.log(JSON.stringify(result));
888
888
  return { exitCode: 0 };
889
889
  } catch (error) {
@@ -954,8 +954,8 @@ async function runUpdateCommand2(args, env = process.env) {
954
954
  error: "No updates provided. Pass --inbound true|false, --tls-mode opportunistic|enforced, --open-tracking true|false, or --click-tracking true|false."
955
955
  };
956
956
  }
957
- const client = await createDomainsClient(apiKey, options.baseUrl);
958
- console.log(JSON.stringify(await client.domains.update(idOrName, payload)));
957
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
958
+ console.log(JSON.stringify(await client2.domains.update(idOrName, payload)));
959
959
  return { exitCode: 0 };
960
960
  } catch (error) {
961
961
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -977,8 +977,8 @@ async function runVerifyCommand(args, env = process.env) {
977
977
  };
978
978
  }
979
979
  try {
980
- const client = await createDomainsClient(apiKey, options.baseUrl);
981
- const result = await client.domains.verify(idOrName);
980
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
981
+ const result = await client2.domains.verify(idOrName);
982
982
  console.log(JSON.stringify(result));
983
983
  if (result.verified) {
984
984
  console.error(`Domain ${result.domain.name} verified.`);
@@ -1034,8 +1034,8 @@ async function runGetCommand4(args, env = process.env) {
1034
1034
  return { exitCode: 1, error: "Missing id. Usage: groundmail received-emails get inb_..." };
1035
1035
  }
1036
1036
  try {
1037
- const client = await createReceivedEmailsClient(apiKey, options.baseUrl);
1038
- console.log(JSON.stringify(await client.receivedEmails.get(id)));
1037
+ const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
1038
+ console.log(JSON.stringify(await client2.receivedEmails.get(id)));
1039
1039
  return { exitCode: 0 };
1040
1040
  } catch (error) {
1041
1041
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1050,10 +1050,10 @@ async function runListCommand4(args, env = process.env) {
1050
1050
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1051
1051
  }
1052
1052
  try {
1053
- const client = await createReceivedEmailsClient(apiKey, options.baseUrl);
1053
+ const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
1054
1054
  console.log(
1055
1055
  JSON.stringify(
1056
- await client.receivedEmails.list({
1056
+ await client2.receivedEmails.list({
1057
1057
  limit: readFlag11(args, "--limit") ? Number(readFlag11(args, "--limit")) : void 0,
1058
1058
  cursor: readFlag11(args, "--cursor"),
1059
1059
  domain: readFlag11(args, "--domain")
@@ -1098,8 +1098,8 @@ async function runCreateCommand2(args, env = process.env) {
1098
1098
  return { exitCode: 1, error: "Required flag: --url" };
1099
1099
  }
1100
1100
  try {
1101
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1102
- const result = await client.webhooks.create({ url });
1101
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1102
+ const result = await client2.webhooks.create({ url });
1103
1103
  console.log(JSON.stringify(result));
1104
1104
  return { exitCode: 0 };
1105
1105
  } catch (error) {
@@ -1116,8 +1116,8 @@ async function runGetCommand5(args, env = process.env) {
1116
1116
  const id = readFlag13(args, "--id") || readFirstPositional6(args);
1117
1117
  if (!id) return { exitCode: 1, error: "Missing webhook id. Pass --id wh_\u2026" };
1118
1118
  try {
1119
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1120
- console.log(JSON.stringify(await client.webhooks.get(id)));
1119
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1120
+ console.log(JSON.stringify(await client2.webhooks.get(id)));
1121
1121
  return { exitCode: 0 };
1122
1122
  } catch (error) {
1123
1123
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1151,8 +1151,8 @@ async function runDeleteCommand3(args, env = process.env) {
1151
1151
  return { exitCode: 1, error: "Required flag: --id" };
1152
1152
  }
1153
1153
  try {
1154
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1155
- const result = await client.webhooks.delete(id);
1154
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1155
+ const result = await client2.webhooks.delete(id);
1156
1156
  console.log(JSON.stringify(result));
1157
1157
  return { exitCode: 0 };
1158
1158
  } catch (error) {
@@ -1168,8 +1168,8 @@ async function runListCommand5(args, env = process.env) {
1168
1168
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1169
1169
  }
1170
1170
  try {
1171
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1172
- const result = await client.webhooks.list();
1171
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1172
+ const result = await client2.webhooks.list();
1173
1173
  console.log(JSON.stringify(result));
1174
1174
  return { exitCode: 0 };
1175
1175
  } catch (error) {
@@ -1198,8 +1198,8 @@ async function runUpdateCommand3(args, env = process.env) {
1198
1198
  ...enabled.value !== void 0 ? { enabled: enabled.value } : {}
1199
1199
  };
1200
1200
  try {
1201
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1202
- console.log(JSON.stringify(await client.webhooks.update(id, payload)));
1201
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1202
+ console.log(JSON.stringify(await client2.webhooks.update(id, payload)));
1203
1203
  return { exitCode: 0 };
1204
1204
  } catch (error) {
1205
1205
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1247,11 +1247,11 @@ async function runListKeysCommandWithClient(args, env = process.env) {
1247
1247
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1248
1248
  }
1249
1249
  const { Groundmail } = await import("groundmail");
1250
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
1250
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
1251
1251
  try {
1252
1252
  const limitRaw = readFlag15(args, "--limit");
1253
1253
  const cursor = readFlag15(args, "--cursor");
1254
- const result = await client.apiKeys.list({
1254
+ const result = await client2.apiKeys.list({
1255
1255
  ...limitRaw ? { limit: Number(limitRaw) } : {},
1256
1256
  ...cursor ? { cursor } : {}
1257
1257
  });
@@ -1288,7 +1288,7 @@ function trimUrl(value) {
1288
1288
  }
1289
1289
 
1290
1290
  // package.json
1291
- var version = "0.18.1";
1291
+ var version = "0.19.0";
1292
1292
 
1293
1293
  // src/user-agent.ts
1294
1294
  function buildUserAgent(own) {
@@ -2184,9 +2184,9 @@ async function runDeleteKeyCommandWithClient(args, env = process.env) {
2184
2184
  return { exitCode: 1, error: "Required: --id <api-key-id>" };
2185
2185
  }
2186
2186
  const { Groundmail } = await import("groundmail");
2187
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
2187
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
2188
2188
  try {
2189
- const result = await client.apiKeys.remove(id);
2189
+ const result = await client2.apiKeys.remove(id);
2190
2190
  console.log(JSON.stringify(result));
2191
2191
  return { exitCode: 0 };
2192
2192
  } catch (error) {
@@ -2224,11 +2224,11 @@ async function runListCommand6(args, env = process.env) {
2224
2224
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2225
2225
  }
2226
2226
  try {
2227
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2227
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2228
2228
  const limitRaw = readFlag18(args, "--limit");
2229
2229
  const cursor = readFlag18(args, "--cursor");
2230
2230
  const email = readFlag18(args, "--email");
2231
- const result = await client.suppressions.list({
2231
+ const result = await client2.suppressions.list({
2232
2232
  ...limitRaw ? { limit: Number(limitRaw) } : {},
2233
2233
  ...cursor ? { cursor } : {},
2234
2234
  ...email ? { email } : {}
@@ -2252,9 +2252,9 @@ async function runAddCommand2(args, env = process.env) {
2252
2252
  return { exitCode: 1, error: "Missing email. Pass --email user@example.com" };
2253
2253
  }
2254
2254
  try {
2255
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2255
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2256
2256
  const reason = readFlag18(args, "--reason");
2257
- const result = await client.suppressions.create({
2257
+ const result = await client2.suppressions.create({
2258
2258
  email,
2259
2259
  ...reason ? { reason } : {}
2260
2260
  });
@@ -2277,8 +2277,8 @@ async function runRemoveCommand(args, env = process.env) {
2277
2277
  return { exitCode: 1, error: "Missing id or email. Pass --id <uuid> or --email user@example.com" };
2278
2278
  }
2279
2279
  try {
2280
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2281
- const result = await client.suppressions.remove(idOrEmail);
2280
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2281
+ const result = await client2.suppressions.remove(idOrEmail);
2282
2282
  console.log(JSON.stringify(result));
2283
2283
  return { exitCode: 0 };
2284
2284
  } catch (error) {
@@ -2315,8 +2315,8 @@ async function runDeleteCommand4(args, env = process.env) {
2315
2315
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional8(args);
2316
2316
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2317
2317
  try {
2318
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2319
- console.log(JSON.stringify(await client.templates.remove(idOrAlias)));
2318
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2319
+ console.log(JSON.stringify(await client2.templates.remove(idOrAlias)));
2320
2320
  return { exitCode: 0 };
2321
2321
  } catch (error) {
2322
2322
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2344,8 +2344,8 @@ async function runDuplicateCommand(args, env = process.env) {
2344
2344
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2345
2345
  const name = readFlag19(args, "--name");
2346
2346
  try {
2347
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2348
- console.log(JSON.stringify(await client.templates.duplicate(idOrAlias, name ? { name } : {})));
2347
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2348
+ console.log(JSON.stringify(await client2.templates.duplicate(idOrAlias, name ? { name } : {})));
2349
2349
  return { exitCode: 0 };
2350
2350
  } catch (error) {
2351
2351
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2372,8 +2372,8 @@ async function runGetCommand6(args, env = process.env) {
2372
2372
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional10(args);
2373
2373
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2374
2374
  try {
2375
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2376
- console.log(JSON.stringify(await client.templates.get(idOrAlias)));
2375
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2376
+ console.log(JSON.stringify(await client2.templates.get(idOrAlias)));
2377
2377
  return { exitCode: 0 };
2378
2378
  } catch (error) {
2379
2379
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2399,11 +2399,11 @@ async function runListCommand7(args, env = process.env) {
2399
2399
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2400
2400
  }
2401
2401
  try {
2402
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2402
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2403
2403
  const limitRaw = readFlag19(args, "--limit");
2404
2404
  const cursor = readFlag19(args, "--cursor");
2405
2405
  const status = readFlag19(args, "--status");
2406
- const result = await client.templates.list({
2406
+ const result = await client2.templates.list({
2407
2407
  ...limitRaw ? { limit: Number(limitRaw) } : {},
2408
2408
  ...cursor ? { cursor } : {},
2409
2409
  ...status ? { status } : {}
@@ -2424,8 +2424,8 @@ async function runPublishCommand(args, env = process.env) {
2424
2424
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional11(args);
2425
2425
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2426
2426
  try {
2427
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2428
- console.log(JSON.stringify(await client.templates.publish(idOrAlias)));
2427
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2428
+ console.log(JSON.stringify(await client2.templates.publish(idOrAlias)));
2429
2429
  return { exitCode: 0 };
2430
2430
  } catch (error) {
2431
2431
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2600,10 +2600,10 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2600
2600
  return { exitCode: 1, error: `${file} produced no content to push.` };
2601
2601
  }
2602
2602
  const createClient2 = deps.createClient ?? createTemplatesClient;
2603
- const client = await createClient2(apiKey, options.baseUrl);
2603
+ const client2 = await createClient2(apiKey, options.baseUrl);
2604
2604
  let existed = true;
2605
2605
  try {
2606
- await client.templates.get(alias);
2606
+ await client2.templates.get(alias);
2607
2607
  } catch (error) {
2608
2608
  if (statusOf(error) !== 404) throw error;
2609
2609
  existed = false;
@@ -2618,7 +2618,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2618
2618
  };
2619
2619
  let result;
2620
2620
  if (existed) {
2621
- result = await client.templates.update(alias, body);
2621
+ result = await client2.templates.update(alias, body);
2622
2622
  } else {
2623
2623
  if (!subject) {
2624
2624
  return {
@@ -2626,7 +2626,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2626
2626
  error: `Template "${alias}" does not exist yet. Pass --subject to create it.`
2627
2627
  };
2628
2628
  }
2629
- result = await client.templates.create({
2629
+ result = await client2.templates.create({
2630
2630
  name: name || alias,
2631
2631
  subject,
2632
2632
  alias,
@@ -2634,7 +2634,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2634
2634
  });
2635
2635
  }
2636
2636
  if (shouldPublish) {
2637
- result = await client.templates.publish(alias);
2637
+ result = await client2.templates.publish(alias);
2638
2638
  }
2639
2639
  console.log(JSON.stringify({ ...result, pushed: { file, alias, created: !existed } }));
2640
2640
  return { exitCode: 0 };
@@ -2667,8 +2667,8 @@ async function runCreateCommand3(args, env = process.env) {
2667
2667
  return { exitCode: 1, error: 'Missing body. Pass --html "<p>Hi</p>" or --text "Hi"' };
2668
2668
  }
2669
2669
  try {
2670
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2671
- const result = await client.templates.create({
2670
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2671
+ const result = await client2.templates.create({
2672
2672
  name,
2673
2673
  subject,
2674
2674
  ...html ? { html } : {},
@@ -2723,8 +2723,8 @@ async function runUpdateCommand4(args, env = process.env) {
2723
2723
  };
2724
2724
  }
2725
2725
  try {
2726
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2727
- const result = await client.templates.update(idOrAlias, {
2726
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2727
+ const result = await client2.templates.update(idOrAlias, {
2728
2728
  ...name ? { name } : {},
2729
2729
  ...subject ? { subject } : {},
2730
2730
  ...html ? { html } : {},
@@ -2787,8 +2787,8 @@ async function runFromStarterCommand(args, env = process.env) {
2787
2787
  };
2788
2788
  }
2789
2789
  try {
2790
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2791
- console.log(JSON.stringify(await client.templates.fromStarter(alias)));
2790
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2791
+ console.log(JSON.stringify(await client2.templates.fromStarter(alias)));
2792
2792
  return { exitCode: 0 };
2793
2793
  } catch (error) {
2794
2794
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2801,8 +2801,8 @@ async function runListStartersCommand(args, env = process.env) {
2801
2801
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2802
2802
  }
2803
2803
  try {
2804
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2805
- console.log(JSON.stringify(await client.templates.listStarters()));
2804
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2805
+ console.log(JSON.stringify(await client2.templates.listStarters()));
2806
2806
  return { exitCode: 0 };
2807
2807
  } catch (error) {
2808
2808
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2833,8 +2833,8 @@ async function runVersionsCommand(args, env = process.env) {
2833
2833
  return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2834
2834
  }
2835
2835
  try {
2836
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2837
- console.log(JSON.stringify(await client.templates.listVersions(idOrAlias)));
2836
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2837
+ console.log(JSON.stringify(await client2.templates.listVersions(idOrAlias)));
2838
2838
  return { exitCode: 0 };
2839
2839
  } catch (error) {
2840
2840
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2856,8 +2856,8 @@ async function runRestoreCommand(args, env = process.env) {
2856
2856
  };
2857
2857
  }
2858
2858
  try {
2859
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2860
- console.log(JSON.stringify(await client.templates.restoreVersion(idOrAlias, version2)));
2859
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2860
+ console.log(JSON.stringify(await client2.templates.restoreVersion(idOrAlias, version2)));
2861
2861
  return { exitCode: 0 };
2862
2862
  } catch (error) {
2863
2863
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2879,8 +2879,8 @@ async function runTestSendCommand(args, env = process.env) {
2879
2879
  };
2880
2880
  }
2881
2881
  try {
2882
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2883
- console.log(JSON.stringify(await client.templates.testSend(idOrAlias, { from, to })));
2882
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2883
+ console.log(JSON.stringify(await client2.templates.testSend(idOrAlias, { from, to })));
2884
2884
  return { exitCode: 0 };
2885
2885
  } catch (error) {
2886
2886
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2915,8 +2915,8 @@ async function runTwilioStatusCommand(args, env = process.env) {
2915
2915
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2916
2916
  }
2917
2917
  try {
2918
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2919
- const result = await client.integrations.getTwilio();
2918
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2919
+ const result = await client2.integrations.getTwilio();
2920
2920
  console.log(JSON.stringify(result));
2921
2921
  return { exitCode: 0 };
2922
2922
  } catch (error) {
@@ -2946,8 +2946,8 @@ async function runTwilioConnectCommand(args, env = process.env) {
2946
2946
  };
2947
2947
  }
2948
2948
  try {
2949
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2950
- const result = await client.integrations.connectTwilio({
2949
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2950
+ const result = await client2.integrations.connectTwilio({
2951
2951
  accountSid: accountSid.trim(),
2952
2952
  authToken: authToken.trim(),
2953
2953
  ...defaultFrom.trim() ? { defaultFrom: defaultFrom.trim() } : {},
@@ -2966,8 +2966,8 @@ async function runTwilioDisconnectCommand(args, env = process.env) {
2966
2966
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2967
2967
  }
2968
2968
  try {
2969
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2970
- const result = await client.integrations.disconnectTwilio();
2969
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2970
+ const result = await client2.integrations.disconnectTwilio();
2971
2971
  console.log(JSON.stringify(result));
2972
2972
  return { exitCode: 0 };
2973
2973
  } catch (error) {
@@ -3120,6 +3120,7 @@ var KEY_ENV = {
3120
3120
  mailgun: "MAILGUN_API_KEY"
3121
3121
  };
3122
3122
  var LABELS = { sendgrid: "SendGrid", postmark: "Postmark", mailgun: "Mailgun" };
3123
+ var VALUE_FLAGS2 = /* @__PURE__ */ new Set(["--api-key", "--base-url"]);
3123
3124
  function readFlag21(args, flag) {
3124
3125
  const index = args.indexOf(flag);
3125
3126
  if (index === -1) return void 0;
@@ -3148,6 +3149,10 @@ function formatMigrationSummary(m) {
3148
3149
  lines.push(
3149
3150
  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
3151
  );
3152
+ if (s.product_opt_out) lines.push(` ${n(s.product_opt_out)} of them product email opt-outs (transactional mail still reaches them)`);
3153
+ for (const [reason, count] of Object.entries(m.suppressions.skipped_reasons)) {
3154
+ lines.push(` ${n(count)} skipped: ${reason}`);
3155
+ }
3151
3156
  }
3152
3157
  if (m.errors.length) {
3153
3158
  lines.push("", "Could not read:");
@@ -3163,6 +3168,17 @@ function formatMigrationSummary(m) {
3163
3168
  for (const line of failed.slice(0, 20)) lines.push(` ${line}`);
3164
3169
  if (failed.length > 20) lines.push(` \u2026and ${failed.length - 20} more (see the JSON report)`);
3165
3170
  }
3171
+ const plans = (m.domains?.items ?? []).filter((d) => d.dns_plan);
3172
+ for (const d of plans) {
3173
+ const changes = d.dns_plan.changes.filter((c) => c.action === "add" || c.action === "update");
3174
+ lines.push("", `DNS changes for ${d.name}${changes.length ? "" : ": all published"}`);
3175
+ for (const c of changes) {
3176
+ lines.push(` ${c.action === "update" ? "edit" : "add "} ${c.type.padEnd(5)} ${c.host} ${c.value}`);
3177
+ if (c.action === "update" && c.current) lines.push(` now: ${c.current}`);
3178
+ }
3179
+ for (const c of d.dns_plan.changes.filter((c2) => c2.action === "keep")) lines.push(` keep ${c.type.padEnd(5)} ${c.host} (yours)`);
3180
+ lines.push(` ${d.dns_plan.keep_old_records}`);
3181
+ }
3166
3182
  if (m.attention.length) {
3167
3183
  lines.push("", "Next:");
3168
3184
  for (const line of m.attention) lines.push(` - ${line}`);
@@ -3170,11 +3186,48 @@ function formatMigrationSummary(m) {
3170
3186
  const node = m.code_changes?.find((c) => c.stack === "node");
3171
3187
  if (node) lines.push("", "Code change (Node.js):", node.diff);
3172
3188
  if (m.agent_prompt) lines.push("", "Prompt for your coding agent is in the JSON report (`agent_prompt`).");
3189
+ if (!m.dry_run && !m.has_more) lines.push("", `Report: groundmail migrate report ${m.id} --csv > import-report.csv`);
3173
3190
  return lines.join("\n");
3174
3191
  }
3192
+ async function client(args, env) {
3193
+ const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
3194
+ if (!apiKey) return null;
3195
+ const { Groundmail } = await import("groundmail");
3196
+ const baseUrl = readFlag21(args, "--base-url");
3197
+ return new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3198
+ }
3199
+ async function runStoredCommand(sub, args, env) {
3200
+ const gm = await client(args, env);
3201
+ if (!gm) return { exitCode: 1, error: "Not signed in. Run `groundmail login`, or set GROUNDMAIL_API_KEY." };
3202
+ try {
3203
+ if (sub === "list") {
3204
+ const { data } = await gm.migrations.list();
3205
+ console.log(JSON.stringify({ data }));
3206
+ for (const m of data) console.error(`${m.id} ${LABELS[m.provider]} ${m.status} ${m.started_at.slice(0, 10)}`);
3207
+ if (!data.length) console.error("No imports yet. Previews are not stored.");
3208
+ return { exitCode: 0 };
3209
+ }
3210
+ const id = args.find((arg, i) => !arg.startsWith("--") && !VALUE_FLAGS2.has(args[i - 1] ?? ""));
3211
+ if (!id) return { exitCode: 1, error: "Usage: groundmail migrate report <import id> [--csv]" };
3212
+ if (args.includes("--csv")) {
3213
+ process.stdout.write(await gm.migrations.reportCsv(id));
3214
+ return { exitCode: 0 };
3215
+ }
3216
+ const { migration } = await gm.migrations.get(id);
3217
+ console.log(JSON.stringify(migration));
3218
+ console.error(formatMigrationSummary(migration));
3219
+ return { exitCode: 0 };
3220
+ } catch (error) {
3221
+ return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
3222
+ }
3223
+ }
3175
3224
  async function runMigrateCommand(provider, args, env = process.env) {
3225
+ if (provider === "list" || provider === "report") return runStoredCommand(provider, args, env);
3176
3226
  if (!provider || !PROVIDERS.includes(provider)) {
3177
- return { exitCode: 1, error: "Usage: groundmail migrate <sendgrid|postmark|mailgun> [--dry-run] [--only templates,suppressions]" };
3227
+ return {
3228
+ exitCode: 1,
3229
+ error: "Usage: groundmail migrate <sendgrid|postmark|mailgun> [--dry-run] [--only templates,suppressions], groundmail migrate list, or groundmail migrate report <id> [--csv]"
3230
+ };
3178
3231
  }
3179
3232
  const id = provider;
3180
3233
  const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
@@ -3210,9 +3263,9 @@ async function runMigrateCommand(provider, args, env = process.env) {
3210
3263
  try {
3211
3264
  const { Groundmail } = await import("groundmail");
3212
3265
  const baseUrl = readFlag21(args, "--base-url");
3213
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3266
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3214
3267
  console.error(`${params.dry_run ? "Previewing" : "Importing"} from ${LABELS[id]} (Beta)\u2026`);
3215
- const report = await client.migrations.run(params, {
3268
+ const report = await client2.migrations.run(params, {
3216
3269
  onProgress: (m) => {
3217
3270
  if (m.has_more) {
3218
3271
  const s = m.suppressions?.totals;
@@ -3242,8 +3295,8 @@ async function runValidateCommand(args, env = process.env) {
3242
3295
  return { exitCode: 1, error: "Missing email. Usage: groundmail validate user@example.com" };
3243
3296
  }
3244
3297
  try {
3245
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
3246
- const result = await client.validate(email);
3298
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
3299
+ const result = await client2.validate(email);
3247
3300
  console.log(JSON.stringify(result));
3248
3301
  return { exitCode: result.verdict === "invalid" ? 2 : 0 };
3249
3302
  } catch (error) {
@@ -3315,6 +3368,8 @@ var USAGE_LINES = [
3315
3368
  " groundmail migrate sendgrid [--dry-run] [--only templates,suppressions,domains,webhooks] [--region eu] import from SendGrid (Beta)",
3316
3369
  " groundmail migrate postmark [--dry-run] [--only \u2026] import from Postmark (Beta)",
3317
3370
  " groundmail migrate mailgun [--dry-run] [--only \u2026] [--region eu] import from Mailgun (Beta)",
3371
+ " groundmail migrate list your recent imports",
3372
+ " groundmail migrate report <id> [--csv] an import report (JSON, or CSV to stdout)",
3318
3373
  " groundmail integrations twilio status",
3319
3374
  " groundmail integrations twilio connect --account-sid AC\u2026 --auth-token \u2026 --from +15551234567",
3320
3375
  " groundmail integrations twilio disconnect"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail-cli",
3
- "version": "0.18.1",
3
+ "version": "0.19.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.15.1"
41
+ "groundmail": "0.16.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "tsup": "^8.5.0",