@letterstory/cli 0.61.0 → 0.61.1

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/lib/cli.mjs CHANGED
@@ -55,7 +55,7 @@ import {
55
55
  } from "./commands.mjs";
56
56
 
57
57
  // Keep in sync with cli/package.json.
58
- export const VERSION = "0.61.0";
58
+ export const VERSION = "0.61.1";
59
59
 
60
60
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
61
61
  // can't accidentally swallow the id as --json's value.
@@ -807,10 +807,13 @@ Sequences (multi-step cold email sent from your mailers; approving or enrolling
807
807
  sequences get <sequence-id> Flow, enrollments, who replied at each step
808
808
  sequences create --name <n> (--flow '<json>'|--flow-file <path>) [--mailer <mailer-id>]...
809
809
  [--[no-]opt-out-footer] [--[no-]postal-address-footer] [--[no-]unsubscribe-links] [--[no-]detect-reply-opt-outs]
810
- New draft sequence (nothing sends yet; rails default on, opt-out line off)
810
+ [--send-window-start <HH:MM>] [--send-window-end <HH:MM>] [--send-window-timezone <IANA tz>]
811
+ New draft sequence (nothing sends yet; rails default on, opt-out line off;
812
+ sends 9:00-17:00 in each recipient's inferred timezone, else the sender's)
811
813
  sequences update <sequence-id> [--name <n>] [--flow '<json>'|--flow-file <path>]
812
814
  [--status draft|active|paused|archived] [--mailer <mailer-id>]...
813
815
  [--[no-]opt-out-footer] [--[no-]postal-address-footer] [--[no-]unsubscribe-links] [--[no-]detect-reply-opt-outs]
816
+ [--send-window-start <HH:MM>] [--send-window-end <HH:MM>] [--send-window-timezone <IANA tz>]
814
817
  sequences pause|resume <sequence-id> Stop / restart sending
815
818
  sequences enroll <sequence-id> (--list <list-id> | --email <addr>... | --recipients '<json>'|--recipients-file <path>)
816
819
  sequences stop <sequence-id> <enrollment-id> Stop one recipient
@@ -60,6 +60,31 @@ const SEQUENCE_RAIL_ARGS = {
60
60
  unsubscribe_links: { flag: "unsubscribe-links", type: "bool", negate: "no-unsubscribe-links" },
61
61
  detect_reply_opt_outs: { flag: "detect-reply-opt-outs", type: "bool", negate: "no-detect-reply-opt-outs" },
62
62
  };
63
+
64
+ // A send-window edge from --<flag> HH:MM (or a raw minute of day) → the
65
+ // schema's minute-of-day number.
66
+ function windowMinute(flag) {
67
+ return (flags) => {
68
+ const raw = flagStr(flags[flag]);
69
+ if (raw === undefined) return undefined;
70
+ if (/^\d+$/.test(raw)) return Number(raw);
71
+ const match = /^(\d{1,2}):(\d{2})$/.exec(raw);
72
+ if (!match || Number(match[1]) > 23 || Number(match[2]) > 59) {
73
+ throw new CliError(`--${flag} takes HH:MM or a minute of day 0–1439 (got ${raw})`);
74
+ }
75
+ return Number(match[1]) * 60 + Number(match[2]);
76
+ };
77
+ }
78
+
79
+ // The send window, shared by create and update: when emails may go out
80
+ // (default 9:00–17:00), in each recipient's inferred timezone, falling back to
81
+ // the sender's --send-window-timezone when the location is unknown. Equal
82
+ // start and end turns the window off.
83
+ const SEQUENCE_WINDOW_ARGS = {
84
+ send_window_start_minute: { value: windowMinute("send-window-start") },
85
+ send_window_end_minute: { value: windowMinute("send-window-end") },
86
+ send_window_timezone: "send-window-timezone",
87
+ };
63
88
  const PROSPECT_STATUSES = ["new", "contacted", "replied", "unsubscribed", "archived"];
64
89
  const mailerIds = {
65
90
  value: (flags) => {
@@ -101,6 +126,7 @@ export const ARGS = {
101
126
  },
102
127
  mailer_ids: mailerIds,
103
128
  ...SEQUENCE_RAIL_ARGS,
129
+ ...SEQUENCE_WINDOW_ARGS,
104
130
  },
105
131
  update_sequence: {
106
132
  sequence_id: { positional: 0, label: "sequence-id", required: true },
@@ -109,6 +135,7 @@ export const ARGS = {
109
135
  status: { flag: "status", enum: SEQUENCE_STATUSES },
110
136
  mailer_ids: mailerIds,
111
137
  ...SEQUENCE_RAIL_ARGS,
138
+ ...SEQUENCE_WINDOW_ARGS,
112
139
  },
113
140
  enroll_in_sequence: {
114
141
  sequence_id: { positional: 0, label: "sequence-id", required: true },
@@ -260,8 +287,8 @@ export const ARGS = {
260
287
 
261
288
  // Flags the computed `value` sources read (refuseUnknownFlags can't see them).
262
289
  const VALUE_FLAGS = {
263
- create_sequence: ["flow", "flow-file", "mailer"],
264
- update_sequence: ["flow", "flow-file", "mailer"],
290
+ create_sequence: ["flow", "flow-file", "mailer", "send-window-start", "send-window-end"],
291
+ update_sequence: ["flow", "flow-file", "mailer", "send-window-start", "send-window-end"],
265
292
  enroll_in_sequence: ["recipients", "recipients-file", "email"],
266
293
  update_review_item: ["body", "file"],
267
294
  import_prospects_csv: ["csv", "csv-file"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.61.0",
3
+ "version": "0.61.1",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",