@curviate/cli 0.19.0 → 0.21.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 (29) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/dist/{account-EGJJNBXW.js → account-A3FOYUKC.js} +29 -29
  3. package/dist/{chunk-42VUUKQ3.js → chunk-56ORAZJO.js} +4 -1
  4. package/dist/{chunk-TMU3CSPR.js → chunk-CUTMZWL6.js} +5 -1
  5. package/dist/chunk-HOQ7EUHJ.js +50 -0
  6. package/dist/{chunk-M33MI53G.js → chunk-LMVDURUZ.js} +23 -1
  7. package/dist/{chunk-KVV6LZ7E.js → chunk-Q7XG2VIF.js} +60 -24
  8. package/dist/chunk-ZYURL5VK.js +83 -0
  9. package/dist/cli.js +51 -36
  10. package/dist/{comment-VT6PO4MN.js → comment-RPLZHFJQ.js} +9 -9
  11. package/dist/{company-XEEBBCRZ.js → company-DFJK2RHM.js} +23 -22
  12. package/dist/{config-P5CPF5WC.js → config-FPWWYG7G.js} +3 -2
  13. package/dist/{connect-6PU7QCOL.js → connect-ELSSMOIC.js} +37 -15
  14. package/dist/{feed-KAUDRE5K.js → feed-23Z7OQNL.js} +4 -3
  15. package/dist/{group-LPVVJ2JX.js → group-52MP24W3.js} +8 -7
  16. package/dist/{inbox-BXCWHGWP.js → inbox-G6KNWWLI.js} +10 -9
  17. package/dist/{inboxes-MTPWLP5F.js → inboxes-NTTYCQPM.js} +5 -4
  18. package/dist/{job-EIXBJXLW.js → job-WOPIAHOR.js} +8 -7
  19. package/dist/{login-GDLWR542.js → login-ZLDDIAFW.js} +14 -15
  20. package/dist/{message-UWMRE2SJ.js → message-KJXY5RCD.js} +7 -4
  21. package/dist/{notification-RYFDHM3G.js → notification-MNEABNVW.js} +6 -5
  22. package/dist/{post-HK6HHIKV.js → post-A7YZWBFG.js} +12 -12
  23. package/dist/{profile-PES67647.js → profile-XOMDIYSY.js} +14 -13
  24. package/dist/{recruiter-MVPSTH2V.js → recruiter-CCLG4PM4.js} +38 -35
  25. package/dist/{sales-nav-TMXWDKSE.js → sales-nav-5ZRE2UAQ.js} +20 -19
  26. package/dist/{search-O2LACGHE.js → search-NDESJC3Y.js} +16 -14
  27. package/dist/{webhook-QFSZN3P2.js → webhook-TNZF3FMN.js} +51 -19
  28. package/package.json +2 -2
  29. package/dist/chunk-U7Y4EXHT.js +0 -33
package/CHANGELOG.md CHANGED
@@ -8,6 +8,139 @@ a new command or flag is a minor; a breaking command/flag/exit-code change is a
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.21.0] - 2026-08-04
12
+
13
+ A correctness release for every argument that reads from stdin. Upgrade
14
+ immediately if you are on 0.20.0: on that version the documented quick-start
15
+ login silently stored a placeholder instead of your API key, so the very first
16
+ command after it failed and blamed your key.
17
+
18
+ ### Fixed
19
+
20
+ - **`curviate login --api-key -` now stores the piped key.** It previously
21
+ reported success and exited 0 while writing the literal string
22
+ `__curviate_stdin__` into your config, so every later command answered 401 and
23
+ attributed the failure to your API key. That is the first command in the
24
+ quick-start, so a new install failed on first contact with a misleading cause.
25
+
26
+ - **Eleven further arguments documented as accepting `-` now read stdin.** Each
27
+ compared its raw value against `-`, but the dispatcher had already substituted
28
+ an internal placeholder by that point, so the branch was unreachable and the
29
+ placeholder was consumed as your data. Affected: `--filters` on the eight
30
+ search and list commands, and `--body` on the three recruiter and webhook
31
+ commands, which answered `--filters is not valid JSON` or
32
+ `--body only accepts '-'` to a caller who had passed exactly that.
33
+
34
+ ### Changed
35
+
36
+ - **A bare `-` is only special on an argument that declares a stdin contract.**
37
+ Every other argument now receives a literal `-`, restored between the parser
38
+ and the handler. Previously the substitution was indiscriminate, so a bare `-`
39
+ became the internal placeholder at any argument, including places where it
40
+ then travelled to the wire as a value. If you were relying on `-` being read
41
+ from stdin on an argument whose help text does not describe that behaviour, it
42
+ no longer is; the arguments that document the contract are unchanged.
43
+
44
+ - **The internal placeholder can no longer leave the process.** The request
45
+ transport and the config writer both refuse it as a defence in depth backstop,
46
+ and report what to do instead, so no future argument can leak it into a
47
+ request or a config file.
48
+
49
+ ## [0.20.0] - 2026-08-03
50
+
51
+ A safety and correctness release. Upgrade promptly: it closes a path by which a
52
+ mistyped command sent a message, and it is the first release in which
53
+ `curviate webhook verify` works at all.
54
+
55
+ ### Fixed
56
+
57
+ - **An unknown subcommand under `message` no longer becomes a send.**
58
+ `curviate message search "sophie"` did not error. `message` accepts both
59
+ subcommands and a bare `message <chat_id> "<text>"` form, and an unregistered
60
+ first token fell through to the bare form, so it bound `chatId="search"`,
61
+ `text="sophie"` and **sent a message**. That applied to any unknown or
62
+ mistyped subcommand: with `search` it 404s, but with a real chat id in that
63
+ position, or a paste that lands one there, it messaged a real person.
64
+
65
+ An unknown subcommand now exits 2 with usage and issues **no request at all**.
66
+ The legitimate `curviate message <chat_id> "<text>"` form is unchanged, and
67
+ `curviate message send <chat_id> "<text>"` is always available for a chat id
68
+ the check does not recognise.
69
+
70
+ To search your messages, the command is `curviate inbox search`.
71
+
72
+ - **A mistyped `connect` subcommand no longer sends a connection invitation.**
73
+ Same shape: `curviate connect <id>` sends an invitation, so `connect snet`
74
+ (for `sent`) invited whoever owns the slug `snet`. A first argument that is a
75
+ near-miss of a `connect` subcommand is now refused with a suggestion. If the
76
+ slug really was intended, pass the full profile URL or the provider id.
77
+
78
+ - **`curviate webhook verify` now verifies real deliveries.** It inherited a
79
+ defect from `@curviate/sdk`: the platform sends the event name in `event` and
80
+ the SDK required a `type` field no delivery has ever carried, so verification
81
+ failed on 100% of genuine webhooks and reported `malformed_header`, pointing
82
+ at the header and the secret when both were correct. Fixed by the `@curviate/sdk`
83
+ 0.19.0 dependency bump. A body that verifies but cannot be parsed now reports
84
+ `malformed_payload`.
85
+
86
+ - **`webhook verify --body` accepts the raw body inline, as a file path, or on
87
+ stdin.** Every documented invocation failed before this: the flag value was
88
+ handed straight to the filesystem, so inline JSON was opened as a filename
89
+ (`ENOENT`/`ENAMETOOLONG`), and `--body -` opened the internal placeholder the
90
+ argument parser substitutes for a bare dash. Only a file path ever worked, and
91
+ the failure surfaced as exit `1` with a raw filesystem error rather than a
92
+ usage error. A body is now recognised by its leading `{`, `-` reads stdin on
93
+ every platform, and anything unreadable exits `2` naming all three accepted
94
+ forms. A trailing newline added by a shell redirect, `curl -o`, or an editor
95
+ save is ignored; newlines inside the body are preserved.
96
+
97
+ - **`webhook verify --help` named the wrong signature header.** It said
98
+ `X-Curviate-Signature`; the platform sends `Curviate-Signature`, so a reader
99
+ who copied the name read for a header that is never present. The same help
100
+ also claimed `--header` falls back to stdin, which it never did. Both flags
101
+ are now marked required, so omitting one is a usage error instead of a
102
+ signature failure that points at a secret which was never wrong.
103
+
104
+ - **`group list` help said `--profile`; the flag is `--target`.** `--profile` is
105
+ the global config-profile selector, so following the help text selected a
106
+ config profile and silently returned your own groups instead of the target
107
+ member's.
108
+
109
+ - **`job publish` and `recruiter job publish` help said `--budget-*`.** The glob
110
+ is not a flag anyone can type; the help now names `--budget-amount`,
111
+ `--budget-currency`, and `--budget-scope`.
112
+
113
+ - **Em dashes removed from all CLI output** (error messages, help text, usage
114
+ blocks), including the `no API key` error.
115
+
116
+ ### Changed
117
+
118
+ - `@curviate/sdk` dependency bumped to `^0.19.0`. If you also call the SDK
119
+ directly, note that its webhook event discriminant moved from `event.type` to
120
+ `event.event`; see the SDK's 0.19.0 changelog.
121
+
122
+ ### Added
123
+
124
+ - Two mechanical guards in the test suite, both derived from the live command
125
+ tree rather than a hand-maintained list, so this class of defect cannot
126
+ quietly return:
127
+ - a fall-through audit that forces an explicit safe/read-only/write-bearing
128
+ verdict on every command group that mixes subcommands with a positional
129
+ fallback, and
130
+ - a help-vs-args check that fails when any command's help text names a flag
131
+ that command does not declare (resolving cross-references, so a reference
132
+ to another command's flag is checked against that command).
133
+
134
+ - Two further mechanical guards, in the same spirit:
135
+ - an em-dash check that walks the TypeScript syntax tree, so it inspects
136
+ string and template literals only and leaves comments exempt structurally
137
+ rather than by a fragile line-based heuristic, and
138
+ - a pre-publish binary gate that runs every documented `webhook verify --body`
139
+ form against a recorded delivery: the exact body bytes and the exact
140
+ signature header the platform put on the wire, replayed verbatim and never
141
+ re-signed. Tampering with a single field is still rejected, so the gate
142
+ proves the verdict as well as the plumbing.
143
+
11
144
  ## [0.19.0] - 2026-07-29
12
145
 
13
146
  A minor release closing the remaining SDK-parity gap: 25 new commands across seven
@@ -5,9 +5,6 @@ import {
5
5
  import {
6
6
  AUTH_NEEDED
7
7
  } from "./chunk-M6UDWFHX.js";
8
- import {
9
- defaultReadStdin
10
- } from "./chunk-U7Y4EXHT.js";
11
8
  import {
12
9
  slimAccountGet,
13
10
  slimAccountList,
@@ -26,12 +23,15 @@ import {
26
23
  renderSuccess,
27
24
  renderUnexpectedError,
28
25
  resolveEffectiveConfig
29
- } from "./chunk-M33MI53G.js";
26
+ } from "./chunk-LMVDURUZ.js";
30
27
  import {
31
28
  GLOBAL_FLAGS,
32
29
  READ_SINGLE_FLAGS,
33
30
  WRITE_SINGLE_FLAGS
34
- } from "./chunk-TMU3CSPR.js";
31
+ } from "./chunk-CUTMZWL6.js";
32
+ import {
33
+ defaultReadStdin
34
+ } from "./chunk-ZYURL5VK.js";
35
35
 
36
36
  // src/commands/account.ts
37
37
  import { defineCommand } from "citty";
@@ -90,15 +90,15 @@ function checkCredentialConflicts(flags, out) {
90
90
  const passwordStdin = flags["password-stdin"] ?? false;
91
91
  const liAtStdin = flags["li-at-stdin"] ?? false;
92
92
  if (flags.password !== void 0 && passwordStdin) {
93
- failConflict(out, "--password and --password-stdin cannot both be set \u2014 choose one source.");
93
+ failConflict(out, "--password and --password-stdin cannot both be set. Choose one source.");
94
94
  }
95
95
  if (flags["li-at"] !== void 0 && liAtStdin) {
96
- failConflict(out, "--li-at and --li-at-stdin cannot both be set \u2014 choose one source.");
96
+ failConflict(out, "--li-at and --li-at-stdin cannot both be set. Choose one source.");
97
97
  }
98
98
  if (passwordStdin && liAtStdin) {
99
99
  failConflict(
100
100
  out,
101
- "--password-stdin and --li-at-stdin cannot both be set \u2014 stdin can feed only one secret per invocation."
101
+ "--password-stdin and --li-at-stdin cannot both be set. stdin can feed only one secret per invocation."
102
102
  );
103
103
  }
104
104
  if (liAtStdin && flags["auth-method"] === "credentials") {
@@ -164,7 +164,7 @@ function challengeDescription(type) {
164
164
  case "two_factor_app":
165
165
  return "Enter the current code from your authenticator app.";
166
166
  case "mobile_app_approval":
167
- return "Open your LinkedIn mobile app and approve this sign-in \u2014 this will continue automatically once you tap approve.";
167
+ return "Open your LinkedIn mobile app and approve this sign-in. This will continue automatically once you tap approve.";
168
168
  }
169
169
  }
170
170
  function printChallengeCopy(type, out) {
@@ -293,7 +293,7 @@ async function buildAuthBody(flags, ctx) {
293
293
  // of --email — an email-less body still fails downstream validation,
294
294
  // as expected, rather than the flag being silently ignored.
295
295
  allowInteractiveStdinRead: !ctx.previewMode,
296
- failMessage: "no password \u2014 pass --password, --password-stdin, or set CURVIATE_LINKEDIN_PASSWORD",
296
+ failMessage: "no password. Pass --password, --password-stdin, or set CURVIATE_LINKEDIN_PASSWORD",
297
297
  prompt: { isTTY: ctx.isTTY, readline: ctx.readline, promptText: "LinkedIn password: " },
298
298
  out: ctx.out
299
299
  });
@@ -314,7 +314,7 @@ async function buildAuthBody(flags, ctx) {
314
314
  readSingleLine: ctx.readSingleLine,
315
315
  required: true,
316
316
  allowInteractive: !ctx.previewMode,
317
- failMessage: "no li_at \u2014 pass --li-at, --li-at-stdin, or set CURVIATE_LINKEDIN_LI_AT",
317
+ failMessage: "no li_at. Pass --li-at, --li-at-stdin, or set CURVIATE_LINKEDIN_LI_AT",
318
318
  out: ctx.out
319
319
  });
320
320
  const liA = await resolveSecret({
@@ -377,7 +377,7 @@ function printConnected(result, ctx) {
377
377
  }
378
378
  function printInvalidCodeRetryHint(err, out) {
379
379
  const attemptsRemaining = err.attempts_remaining;
380
- const message = typeof attemptsRemaining === "number" ? `That code was not accepted \u2014 ${attemptsRemaining} attempt(s) remaining.` : "That code was not accepted \u2014 please try again.";
380
+ const message = typeof attemptsRemaining === "number" ? `That code was not accepted. ${attemptsRemaining} attempt(s) remaining.` : "That code was not accepted. Please try again.";
381
381
  out.stderr.write(`${message}
382
382
  `);
383
383
  }
@@ -620,7 +620,7 @@ async function runAccountConnectSessionPoll(client, flags, out, io = {}) {
620
620
  }
621
621
  renderSuccess(outcome.result, outOpts, out);
622
622
  out.stderr.write(
623
- `Still waiting for the account to connect \u2014 the wait window elapsed. Check again: curviate account connect-session poll --session ${flags.session} --wait
623
+ `Still waiting for the account to connect. The wait window elapsed. Check again: curviate account connect-session poll --session ${flags.session} --wait
624
624
  `
625
625
  );
626
626
  process.exit(AUTH_NEEDED);
@@ -851,7 +851,7 @@ async function runAccountCheckpointPoll(client, flags, out, io = {}) {
851
851
  }
852
852
  renderSuccess(outcome.result, outOpts, out);
853
853
  out.stderr.write(
854
- `Still waiting for approval \u2014 the wait window elapsed. Check again: curviate account checkpoint poll ${accountId} --wait
854
+ `Still waiting for approval. The wait window elapsed. Check again: curviate account checkpoint poll ${accountId} --wait
855
855
  `
856
856
  );
857
857
  process.exit(AUTH_NEEDED);
@@ -868,7 +868,7 @@ var accountListCommand = defineCommand({
868
868
  profile: flags.profile
869
869
  });
870
870
  if (!cfg.apiKey) {
871
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
871
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
872
872
  process.exit(3);
873
873
  }
874
874
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -892,7 +892,7 @@ var accountGetCommand = defineCommand({
892
892
  profile: flags.profile
893
893
  });
894
894
  if (!cfg.apiKey) {
895
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
895
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
896
896
  process.exit(3);
897
897
  }
898
898
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -924,10 +924,10 @@ var accountLinkCommand = defineCommand({
924
924
  "proxy-password": { type: "string", description: `Proxy auth password. ${OPTIONAL_SECRET_WARNING("CURVIATE_PROXY_PASSWORD")}` },
925
925
  "user-agent": { type: "string", description: "Browser User-Agent to pin for this account." },
926
926
  "recruiter-contract-id": { type: "string", description: "Recruiter contract to bind to (Recruiter tier only)." },
927
- "account-id": { type: "string", description: "Existing account id (acc_\u2026) to re-authenticate IN PLACE \u2014 passing it makes this an in-place reconnect of that account. Omit to connect a NEW account into --seat-id." },
927
+ "account-id": { type: "string", description: "Existing account id (acc_\u2026) to re-authenticate IN PLACE. Passing it makes this an in-place reconnect of that account. Omit to connect a NEW account into --seat-id." },
928
928
  "no-interactive": {
929
929
  type: "boolean",
930
- description: "Never prompt for a checkpoint code \u2014 on a checkpoint, always render the envelope and exit 12, even on a TTY.",
930
+ description: "Never prompt for a checkpoint code. On a checkpoint, always render the envelope and exit 12, even on a TTY.",
931
931
  default: false
932
932
  }
933
933
  },
@@ -940,7 +940,7 @@ var accountLinkCommand = defineCommand({
940
940
  profile: flags.profile
941
941
  });
942
942
  if (!cfg.apiKey) {
943
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
943
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
944
944
  process.exit(3);
945
945
  }
946
946
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -951,7 +951,7 @@ var accountLinkCommand = defineCommand({
951
951
  var accountConnectSessionPollCommand = defineCommand({
952
952
  meta: {
953
953
  name: "poll",
954
- description: "Poll the status of an in-progress connect (auth intent) for completion. Without --wait: a single poll \u2014 the JSON `status` field (pending | resolved | expired | failed) tells you what to do next. With --wait: block on the same adaptive cadence as `account link` until a terminal state."
954
+ description: "Poll the status of an in-progress connect (auth intent) for completion. Without --wait: a single poll. The JSON `status` field (pending | resolved | expired | failed) tells you what to do next. With --wait: block on the same adaptive cadence as `account link` until a terminal state."
955
955
  },
956
956
  args: {
957
957
  ...WRITE_SINGLE_FLAGS,
@@ -982,7 +982,7 @@ var accountConnectSessionPollCommand = defineCommand({
982
982
  profile: flags.profile
983
983
  });
984
984
  if (!cfg.apiKey) {
985
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
985
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
986
986
  process.exit(3);
987
987
  }
988
988
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1004,7 +1004,7 @@ var accountUpdateCommand = defineCommand({
1004
1004
  args: {
1005
1005
  ...WRITE_SINGLE_FLAGS,
1006
1006
  "account-id": { type: "positional", description: "Account id (acc_\u2026)." },
1007
- metadata: { type: "string", description: `Custom metadata as a JSON object (flat string\u2192string map) \u2014 replaces the store wholesale. Example: '{"team":"growth"}'.` },
1007
+ metadata: { type: "string", description: `Custom metadata as a JSON object (flat string\u2192string map). Replaces the store wholesale. Example: '{"team":"growth"}'.` },
1008
1008
  "clear-proxy": { type: "boolean", description: "Clear the custom proxy (revert to automatic proxy protection). Mutually exclusive with --proxy-host.", default: false },
1009
1009
  "proxy-protocol": { type: "string", description: "Proxy protocol: http | https | socks5." },
1010
1010
  "proxy-host": { type: "string", description: "Proxy host or IP." },
@@ -1021,7 +1021,7 @@ var accountUpdateCommand = defineCommand({
1021
1021
  profile: flags.profile
1022
1022
  });
1023
1023
  if (!cfg.apiKey) {
1024
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1024
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
1025
1025
  process.exit(3);
1026
1026
  }
1027
1027
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1044,7 +1044,7 @@ var accountDisconnectCommand = defineCommand({
1044
1044
  profile: flags.profile
1045
1045
  });
1046
1046
  if (!cfg.apiKey) {
1047
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1047
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
1048
1048
  process.exit(3);
1049
1049
  }
1050
1050
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1075,7 +1075,7 @@ var accountCheckpointSolveCommand = defineCommand({
1075
1075
  profile: flags.profile
1076
1076
  });
1077
1077
  if (!cfg.apiKey) {
1078
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1078
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
1079
1079
  process.exit(3);
1080
1080
  }
1081
1081
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1105,7 +1105,7 @@ var accountCheckpointPollCommand = defineCommand({
1105
1105
  // --timeout`. Default: the time remaining to the checkpoint's own expiry.
1106
1106
  timeout: {
1107
1107
  type: "string",
1108
- description: "Wait-loop timeout in milliseconds (requires --wait; default: time remaining to the checkpoint's expiry). Note the unit: this is milliseconds \u2014 `inbox sync-chat --timeout` is seconds."
1108
+ description: "Wait-loop timeout in milliseconds (requires --wait; default: time remaining to the checkpoint's expiry). Note the unit: this is milliseconds; `inbox sync-chat --timeout` is seconds."
1109
1109
  }
1110
1110
  },
1111
1111
  async run({ args }) {
@@ -1116,7 +1116,7 @@ var accountCheckpointPollCommand = defineCommand({
1116
1116
  profile: flags.profile
1117
1117
  });
1118
1118
  if (!cfg.apiKey) {
1119
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1119
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
1120
1120
  process.exit(3);
1121
1121
  }
1122
1122
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1127,7 +1127,7 @@ var accountCheckpointPollCommand = defineCommand({
1127
1127
  var accountCheckpointRequestCommand = defineCommand({
1128
1128
  meta: {
1129
1129
  name: "request",
1130
- description: "Re-request the challenge notification for a pending checkpoint (e.g. re-send an OTP email, SMS code, or mobile-app approval push). Not every challenge type supports it \u2014 an authenticator- app code has nothing to re-send. The response's `resent` boolean tells you honestly whether a new notification actually went out; the command still exits 0 either way."
1130
+ description: "Re-request the challenge notification for a pending checkpoint (e.g. re-send an OTP email, SMS code, or mobile-app approval push). Not every challenge type supports it; an authenticator- app code has nothing to re-send. The response's `resent` boolean tells you honestly whether a new notification actually went out; the command still exits 0 either way."
1131
1131
  },
1132
1132
  args: {
1133
1133
  ...WRITE_SINGLE_FLAGS,
@@ -1145,7 +1145,7 @@ var accountCheckpointRequestCommand = defineCommand({
1145
1145
  profile: flags.profile
1146
1146
  });
1147
1147
  if (!cfg.apiKey) {
1148
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1148
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
1149
1149
  process.exit(3);
1150
1150
  }
1151
1151
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ isStdinToken
4
+ } from "./chunk-ZYURL5VK.js";
2
5
 
3
6
  // src/lib/search-filters.ts
4
7
  import { readFile } from "fs/promises";
@@ -23,7 +26,7 @@ async function assembleFilters(flags, readers = DEFAULT_FILTER_READERS) {
23
26
  } catch {
24
27
  return { error: `cannot read ${source}` };
25
28
  }
26
- } else if (flags.filters === "-") {
29
+ } else if (isStdinToken(flags.filters)) {
27
30
  source = "--filters - (stdin)";
28
31
  raw = await readers.readStdin();
29
32
  } else if (flags.filters !== void 0) {
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ assertNoStdinPlaceholder
4
+ } from "./chunk-ZYURL5VK.js";
2
5
 
3
6
  // src/lib/config.ts
4
7
  import {
@@ -37,6 +40,7 @@ async function writeConfig(cfg) {
37
40
  } catch {
38
41
  }
39
42
  const content = JSON.stringify(cfg, null, 2) + "\n";
43
+ assertNoStdinPlaceholder("the configuration about to be written", [content]);
40
44
  const tmpPath = join(
41
45
  tmpdir(),
42
46
  `curviate-cfg-${randomBytes(6).toString("hex")}.tmp`
@@ -87,7 +91,7 @@ async function renameProfile(oldName, newName) {
87
91
  }
88
92
  if (cfg.profiles[newName]) {
89
93
  throw new Error(
90
- `Profile "${newName}" already exists \u2014 remove it first or choose another name.`
94
+ `Profile "${newName}" already exists. Remove it first or choose another name.`
91
95
  );
92
96
  }
93
97
  cfg.profiles[newName] = cfg.profiles[oldName];
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/bare-form-guard.ts
4
+ var COMMAND_WORD_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
5
+ function looksLikeCommandWord(token) {
6
+ return COMMAND_WORD_RE.test(token);
7
+ }
8
+ function editDistance(a, b) {
9
+ const m = a.length;
10
+ const n = b.length;
11
+ if (m === 0) return n;
12
+ if (n === 0) return m;
13
+ const d = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
14
+ for (let i = 0; i <= m; i++) d[i][0] = i;
15
+ for (let j = 0; j <= n; j++) d[0][j] = j;
16
+ for (let i = 1; i <= m; i++) {
17
+ for (let j = 1; j <= n; j++) {
18
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
19
+ let best = Math.min(
20
+ d[i - 1][j] + 1,
21
+ // deletion
22
+ d[i][j - 1] + 1,
23
+ // insertion
24
+ d[i - 1][j - 1] + cost
25
+ // substitution
26
+ );
27
+ if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
28
+ best = Math.min(best, d[i - 2][j - 2] + 1);
29
+ }
30
+ d[i][j] = best;
31
+ }
32
+ }
33
+ return d[m][n];
34
+ }
35
+ function nearestSubcommand(token, subcommandNames) {
36
+ let best = null;
37
+ for (const name of subcommandNames) {
38
+ const threshold = name.length < 6 ? 1 : 2;
39
+ const isPrefix = token.length >= 2 && token.length < name.length && name.startsWith(token);
40
+ const distance = isPrefix ? 1 : editDistance(token, name);
41
+ if (distance > threshold) continue;
42
+ if (best === null || distance < best.distance) best = { name, distance };
43
+ }
44
+ return best?.name ?? null;
45
+ }
46
+
47
+ export {
48
+ looksLikeCommandWord,
49
+ nearestSubcommand
50
+ };
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readConfig
4
- } from "./chunk-TMU3CSPR.js";
4
+ } from "./chunk-CUTMZWL6.js";
5
+ import {
6
+ assertNoStdinPlaceholder
7
+ } from "./chunk-ZYURL5VK.js";
5
8
 
6
9
  // src/lib/resolve.ts
7
10
  var DEFAULT_BASE_URL = "https://api.curviate.com";
@@ -20,9 +23,28 @@ async function resolveEffectiveConfig(flags) {
20
23
 
21
24
  // src/lib/client.ts
22
25
  import { Curviate } from "@curviate/sdk";
26
+ function headerStrings(headers) {
27
+ if (!headers) return [];
28
+ if (headers instanceof Headers) {
29
+ const out = [];
30
+ headers.forEach((value, key) => out.push(key, value));
31
+ return out;
32
+ }
33
+ if (Array.isArray(headers)) return headers.flat().map(String);
34
+ return Object.entries(headers).flat().map(String);
35
+ }
36
+ var guardedFetch = (input, init) => {
37
+ assertNoStdinPlaceholder("the request about to be sent", [
38
+ String(input instanceof Request ? input.url : input),
39
+ ...headerStrings(init?.headers),
40
+ typeof init?.body === "string" ? init.body : void 0
41
+ ]);
42
+ return fetch(input, init);
43
+ };
23
44
  function createClient(config) {
24
45
  return new Curviate({
25
46
  apiKey: config.apiKey.trim(),
47
+ fetch: guardedFetch,
26
48
  ...config.baseUrl !== void 0 ? { baseUrl: config.baseUrl } : {},
27
49
  ...config.timeout !== void 0 ? { timeout: config.timeout } : {}
28
50
  });