run402 1.69.4 → 1.69.5

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/ai.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { resolveProjectId } from "./config.mjs";
2
2
  import { getSdk } from "./sdk.mjs";
3
3
  import { reportSdkError, fail } from "./sdk-errors.mjs";
4
- import { resolvePositionalProject } from "./argparse.mjs";
4
+ import { assertKnownFlags, flagValue, normalizeArgv, resolvePositionalProject } from "./argparse.mjs";
5
5
 
6
6
  const HELP = `run402 ai — AI translation and moderation tools
7
7
 
@@ -103,20 +103,19 @@ Examples:
103
103
  `,
104
104
  };
105
105
 
106
- function parseFlag(args, flag) {
107
- for (let i = 0; i < args.length; i++) {
108
- if (args[i] === flag && args[i + 1]) return args[i + 1];
109
- }
110
- return null;
111
- }
112
-
113
106
  // translate has value-bearing flags (--to, --from, --context, --project) that
114
107
  // must not be mistaken for positional bare args when prefix-matching.
115
108
  const TRANSLATE_VALUE_FLAGS = ["--to", "--from", "--context", "--project"];
116
109
 
117
110
  async function translate(args) {
111
+ args = normalizeArgv(args);
112
+ assertKnownFlags(args, TRANSLATE_VALUE_FLAGS, TRANSLATE_VALUE_FLAGS);
113
+
118
114
  // --project <id> wins over positional, mirroring previous behavior.
119
- const projectOpt = parseFlag(args, "--project");
115
+ const projectOpt = flagValue(args, "--project");
116
+ const to = flagValue(args, "--to");
117
+ const from = flagValue(args, "--from");
118
+ const context = flagValue(args, "--context");
120
119
  let projectId;
121
120
  let rest;
122
121
  if (projectOpt) {
@@ -139,10 +138,6 @@ async function translate(args) {
139
138
  break;
140
139
  }
141
140
 
142
- const to = parseFlag(args, "--to");
143
- const from = parseFlag(args, "--from");
144
- const context = parseFlag(args, "--context");
145
-
146
141
  if (!text) {
147
142
  fail({
148
143
  code: "BAD_USAGE",
@@ -165,7 +160,10 @@ async function translate(args) {
165
160
  const MODERATE_VALUE_FLAGS = ["--project"];
166
161
 
167
162
  async function moderate(args) {
168
- const projectOpt = parseFlag(args, "--project");
163
+ args = normalizeArgv(args);
164
+ assertKnownFlags(args, MODERATE_VALUE_FLAGS, MODERATE_VALUE_FLAGS);
165
+
166
+ const projectOpt = flagValue(args, "--project");
169
167
  let projectId;
170
168
  let rest;
171
169
  if (projectOpt) {
@@ -203,7 +201,10 @@ async function moderate(args) {
203
201
  }
204
202
 
205
203
  async function usage(args) {
206
- const projectOpt = parseFlag(args, "--project");
204
+ args = normalizeArgv(args);
205
+ assertKnownFlags(args, MODERATE_VALUE_FLAGS, MODERATE_VALUE_FLAGS);
206
+
207
+ const projectOpt = flagValue(args, "--project");
207
208
  let projectId;
208
209
  if (projectOpt) {
209
210
  projectId = resolveProjectId(projectOpt);
package/lib/allowance.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { readAllowance, saveAllowance, ALLOWANCE_FILE } from "./config.mjs";
2
2
  import { getSdk } from "./sdk.mjs";
3
3
  import { reportSdkError, fail } from "./sdk-errors.mjs";
4
+ import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs } from "./argparse.mjs";
4
5
 
5
6
  const HELP = `run402 allowance — Manage your agent allowance
6
7
 
@@ -258,17 +259,25 @@ async function checkout(args) {
258
259
  hint: "Run: run402 allowance create",
259
260
  });
260
261
  }
261
- let amount = null;
262
- for (let i = 0; i < args.length; i++) {
263
- if (args[i] === "--amount" && args[i + 1]) amount = parseInt(args[++i], 10);
262
+ const parsedArgs = normalizeArgv(args);
263
+ assertKnownFlags(parsedArgs, ["--amount", "--help", "-h"], ["--amount"]);
264
+ const bare = positionalArgs(parsedArgs, ["--amount"]);
265
+ if (bare.length > 0) {
266
+ fail({
267
+ code: "BAD_USAGE",
268
+ message: `Unexpected argument for allowance checkout: ${bare[0]}`,
269
+ details: { argument: bare[0] },
270
+ });
264
271
  }
265
- if (!amount) {
272
+ const amountRaw = flagValue(parsedArgs, "--amount");
273
+ if (amountRaw === null) {
266
274
  fail({
267
275
  code: "BAD_USAGE",
268
276
  message: "Missing --amount <usd_micros>",
269
277
  hint: "e.g. --amount 5000000 for $5",
270
278
  });
271
279
  }
280
+ const amount = parseIntegerFlag("--amount", amountRaw, { min: 1 });
272
281
  try {
273
282
  const data = await getSdk().billing.createCheckout(w.address, amount);
274
283
  console.log(JSON.stringify(data, null, 2));
@@ -286,10 +295,17 @@ async function history(args) {
286
295
  hint: "Run: run402 allowance create",
287
296
  });
288
297
  }
289
- let limit = 20;
290
- for (let i = 0; i < args.length; i++) {
291
- if (args[i] === "--limit" && args[i + 1]) limit = parseInt(args[++i], 10);
298
+ const parsedArgs = normalizeArgv(args);
299
+ assertKnownFlags(parsedArgs, ["--limit", "--help", "-h"], ["--limit"]);
300
+ const bare = positionalArgs(parsedArgs, ["--limit"]);
301
+ if (bare.length > 0) {
302
+ fail({
303
+ code: "BAD_USAGE",
304
+ message: `Unexpected argument for allowance history: ${bare[0]}`,
305
+ details: { argument: bare[0] },
306
+ });
292
307
  }
308
+ const limit = parseIntegerFlag("--limit", flagValue(parsedArgs, "--limit"), { min: 1, def: 20 });
293
309
  try {
294
310
  const data = await getSdk().billing.history(w.address, limit);
295
311
  console.log(JSON.stringify(data, null, 2));
package/lib/argparse.mjs CHANGED
@@ -75,6 +75,13 @@ export function parseIntegerFlag(name, value, { min = 1, max = Number.POSITIVE_I
75
75
  });
76
76
  }
77
77
  const n = Number.parseInt(raw, 10);
78
+ if (!Number.isSafeInteger(n)) {
79
+ fail({
80
+ code: "BAD_FLAG",
81
+ message: `${name} must be a safe integer, got: ${raw}`,
82
+ details: { flag: name, value: raw },
83
+ });
84
+ }
78
85
  if (n < min) {
79
86
  fail({
80
87
  code: "BAD_FLAG",
package/lib/auth.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { resolveProjectId } from "./config.mjs";
2
2
  import { getSdk } from "./sdk.mjs";
3
3
  import { reportSdkError, fail } from "./sdk-errors.mjs";
4
+ import { assertKnownFlags, hasHelp, normalizeArgv } from "./argparse.mjs";
4
5
 
5
6
  const HELP = `run402 auth — Manage project user authentication
6
7
 
@@ -230,6 +231,61 @@ Examples:
230
231
  `,
231
232
  };
232
233
 
234
+ const AUTH_FLAGS = {
235
+ "magic-link": {
236
+ known: ["--email", "--redirect", "--intent", "--state", "--project", "--help", "-h"],
237
+ values: ["--email", "--redirect", "--intent", "--state", "--project"],
238
+ },
239
+ "create-user": {
240
+ known: ["--email", "--admin", "--invite", "--redirect", "--state", "--project", "--help", "-h"],
241
+ values: ["--email", "--admin", "--redirect", "--state", "--project"],
242
+ },
243
+ "invite-user": {
244
+ known: ["--email", "--redirect", "--admin", "--state", "--project", "--help", "-h"],
245
+ values: ["--email", "--redirect", "--admin", "--state", "--project"],
246
+ },
247
+ verify: {
248
+ known: ["--token", "--project", "--help", "-h"],
249
+ values: ["--token", "--project"],
250
+ },
251
+ "set-password": {
252
+ known: ["--token", "--new", "--current", "--project", "--help", "-h"],
253
+ values: ["--token", "--new", "--current", "--project"],
254
+ },
255
+ settings: {
256
+ known: ["--allow-password-set", "--preferred", "--public-signup", "--require-admin-passkey", "--project", "--help", "-h"],
257
+ values: ["--allow-password-set", "--preferred", "--public-signup", "--require-admin-passkey", "--project"],
258
+ },
259
+ "passkey-register-options": {
260
+ known: ["--token", "--app-origin", "--project", "--help", "-h"],
261
+ values: ["--token", "--app-origin", "--project"],
262
+ },
263
+ "passkey-register-verify": {
264
+ known: ["--token", "--challenge", "--response", "--label", "--project", "--help", "-h"],
265
+ values: ["--token", "--challenge", "--response", "--label", "--project"],
266
+ },
267
+ "passkey-login-options": {
268
+ known: ["--app-origin", "--email", "--project", "--help", "-h"],
269
+ values: ["--app-origin", "--email", "--project"],
270
+ },
271
+ "passkey-login-verify": {
272
+ known: ["--challenge", "--response", "--project", "--help", "-h"],
273
+ values: ["--challenge", "--response", "--project"],
274
+ },
275
+ passkeys: {
276
+ known: ["--token", "--project", "--help", "-h"],
277
+ values: ["--token", "--project"],
278
+ },
279
+ "delete-passkey": {
280
+ known: ["--token", "--id", "--project", "--help", "-h"],
281
+ values: ["--token", "--id", "--project"],
282
+ },
283
+ providers: {
284
+ known: ["--project", "--help", "-h"],
285
+ values: ["--project"],
286
+ },
287
+ };
288
+
233
289
  function parseFlag(args, flag) {
234
290
  for (let i = 0; i < args.length; i++) {
235
291
  if (args[i] === flag && args[i + 1]) return args[i + 1];
@@ -557,10 +613,15 @@ async function providers(args) {
557
613
 
558
614
  export async function run(sub, args) {
559
615
  if (!sub || sub === "--help" || sub === "-h") { console.log(HELP); process.exit(0); }
560
- if (Array.isArray(args) && (args.includes("--help") || args.includes("-h"))) {
616
+ args = normalizeArgv(args);
617
+ if (Array.isArray(args) && hasHelp(args)) {
561
618
  console.log(SUB_HELP[sub] || HELP);
562
619
  process.exit(0);
563
620
  }
621
+ const flagSpec = AUTH_FLAGS[sub];
622
+ if (flagSpec) {
623
+ assertKnownFlags(args, flagSpec.known, flagSpec.values);
624
+ }
564
625
  switch (sub) {
565
626
  case "magic-link": await magicLink(args); break;
566
627
  case "verify": await verify(args); break;
package/lib/billing.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { getSdk } from "./sdk.mjs";
2
2
  import { reportSdkError, fail } from "./sdk-errors.mjs";
3
+ import { parseIntegerFlag } from "./argparse.mjs";
3
4
 
4
5
  const HELP = `run402 billing — Email billing accounts, Stripe tier checkout, email packs
5
6
 
@@ -128,6 +129,23 @@ function parseFlag(args, flag) {
128
129
  return null;
129
130
  }
130
131
 
132
+ function requireSingleBillingIdentifier(email, wallet) {
133
+ if (email && wallet) {
134
+ fail({
135
+ code: "BAD_USAGE",
136
+ message: "Provide either --email or --wallet, not both.",
137
+ hint: "[--email <e> | --wallet <w>]",
138
+ });
139
+ }
140
+ if (!email && !wallet) {
141
+ fail({
142
+ code: "BAD_USAGE",
143
+ message: "Must provide --email or --wallet",
144
+ hint: "[--email <e> | --wallet <w>]",
145
+ });
146
+ }
147
+ }
148
+
131
149
  async function createEmail(args) {
132
150
  const email = args[0];
133
151
  if (!email) {
@@ -174,9 +192,7 @@ async function tierCheckout(args) {
174
192
  }
175
193
  const email = parseFlag(args, "--email");
176
194
  const wallet = parseFlag(args, "--wallet");
177
- if (!email && !wallet) {
178
- fail({ code: "BAD_USAGE", message: "Must provide --email or --wallet" });
179
- }
195
+ requireSingleBillingIdentifier(email, wallet);
180
196
  try {
181
197
  const data = await getSdk().billing.tierCheckout(tier, { email: email ?? undefined, wallet: wallet ?? undefined });
182
198
  console.log(JSON.stringify(data, null, 2));
@@ -188,9 +204,7 @@ async function tierCheckout(args) {
188
204
  async function buyPack(args) {
189
205
  const email = parseFlag(args, "--email");
190
206
  const wallet = parseFlag(args, "--wallet");
191
- if (!email && !wallet) {
192
- fail({ code: "BAD_USAGE", message: "Must provide --email or --wallet" });
193
- }
207
+ requireSingleBillingIdentifier(email, wallet);
194
208
  try {
195
209
  const data = await getSdk().billing.buyEmailPack({ email: email ?? undefined, wallet: wallet ?? undefined });
196
210
  console.log(JSON.stringify(data, null, 2));
@@ -210,11 +224,14 @@ async function autoRecharge(args) {
210
224
  });
211
225
  }
212
226
  const thresholdStr = parseFlag(args, "--threshold");
227
+ const threshold = args.includes("--threshold")
228
+ ? parseIntegerFlag("--threshold", thresholdStr, { min: 0 })
229
+ : undefined;
213
230
  try {
214
231
  await getSdk().billing.setAutoRecharge({
215
232
  billingAccountId: accountId,
216
233
  enabled: state === "on",
217
- threshold: thresholdStr ? Number(thresholdStr) : undefined,
234
+ threshold,
218
235
  });
219
236
  console.log(JSON.stringify({ status: "ok", billing_account_id: accountId, enabled: state === "on" }));
220
237
  } catch (err) {
package/lib/contracts.mjs CHANGED
@@ -135,6 +135,15 @@ function parseFlag(args, flag) {
135
135
  function hasFlag(args, flag) {
136
136
  return args.includes(flag);
137
137
  }
138
+ function validateWeiFlag(flag, value) {
139
+ if (!/^\d+$/.test(String(value))) {
140
+ fail({
141
+ code: "BAD_FLAG",
142
+ message: `${flag} must be a decimal non-negative integer string in wei`,
143
+ details: { flag, value: String(value) },
144
+ });
145
+ }
146
+ }
138
147
 
139
148
  async function provisionWallet(projectId, args) {
140
149
  const chain = parseFlag(args, "--chain");
@@ -210,6 +219,7 @@ async function setAlert(projectId, walletId, args) {
210
219
  if (!threshold) {
211
220
  fail({ code: "BAD_USAGE", message: "Missing --threshold-wei <n>" });
212
221
  }
222
+ validateWeiFlag("--threshold-wei", threshold);
213
223
  try {
214
224
  await getSdk().contracts.setLowBalanceAlert(projectId, walletId, threshold);
215
225
  console.log(JSON.stringify({ status: "ok", wallet_id: walletId, threshold_wei: threshold }));
@@ -233,6 +243,7 @@ async function call(projectId, walletId, args) {
233
243
  hint: "Cost: chain gas + $0.000005 KMS sign fee.",
234
244
  });
235
245
  }
246
+ if (value !== null) validateWeiFlag("--value-wei", value);
236
247
  const abiFragment = parseFlagJson("--abi", abi);
237
248
  const callArgs = parseFlagJson("--args", argsJson);
238
249
  try {
package/lib/email.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { resolveProjectId } from "./config.mjs";
2
2
  import { getSdk } from "./sdk.mjs";
3
3
  import { reportSdkError, fail, parseFlagJson } from "./sdk-errors.mjs";
4
+ import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs } from "./argparse.mjs";
4
5
 
5
6
  const HELP = `run402 email — Send emails from your project
6
7
 
@@ -152,17 +153,39 @@ Examples:
152
153
  `,
153
154
  };
154
155
 
155
- function parseFlag(args, flag) {
156
+ function strictFlagValue(args, flag) {
157
+ const value = flagValue(args, flag);
158
+ if (typeof value === "string" && value.startsWith("--")) {
159
+ fail({
160
+ code: "BAD_FLAG",
161
+ message: `${flag} requires a value`,
162
+ details: { flag },
163
+ });
164
+ }
165
+ return value;
166
+ }
167
+
168
+ function validateArgs(args, knownFlags, flagsWithValues = knownFlags) {
169
+ assertKnownFlags(args, knownFlags, flagsWithValues);
170
+ const valueFlags = new Set(flagsWithValues);
156
171
  for (let i = 0; i < args.length; i++) {
157
- if (args[i] === flag && args[i + 1]) return args[i + 1];
172
+ const flag = args[i];
173
+ if (!valueFlags.has(flag)) continue;
174
+ if (i + 1 >= args.length || (typeof args[i + 1] === "string" && args[i + 1].startsWith("--"))) {
175
+ fail({
176
+ code: "BAD_FLAG",
177
+ message: `${flag} requires a value`,
178
+ details: { flag },
179
+ });
180
+ }
181
+ i += 1;
158
182
  }
159
- return null;
160
183
  }
161
184
 
162
185
  function parseVars(args) {
163
186
  const vars = {};
164
187
  for (let i = 0; i < args.length; i++) {
165
- if (args[i] === "--vars" && args[i + 1]) {
188
+ if (args[i] === "--vars") {
166
189
  const raw = args[++i];
167
190
  const parsed = parseFlagJson("--vars", raw);
168
191
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -175,7 +198,7 @@ function parseVars(args) {
175
198
  }
176
199
  }
177
200
  for (let i = 0; i < args.length; i++) {
178
- if (args[i] === "--var" && args[i + 1]) {
201
+ if (args[i] === "--var") {
179
202
  const raw = args[++i];
180
203
  const eq = raw.indexOf("=");
181
204
  if (eq > 0) vars[raw.slice(0, eq)] = raw.slice(eq + 1);
@@ -185,12 +208,9 @@ function parseVars(args) {
185
208
  }
186
209
 
187
210
  async function create(args) {
188
- let slug = null;
189
- let projectOpt = null;
190
- for (let i = 0; i < args.length; i++) {
191
- if (args[i] === "--project" && args[i + 1]) { projectOpt = args[++i]; }
192
- else if (!args[i].startsWith("--") && !slug) { slug = args[i]; }
193
- }
211
+ validateArgs(args, ["--project"]);
212
+ const slug = positionalArgs(args, ["--project"])[0] ?? null;
213
+ const projectOpt = strictFlagValue(args, "--project");
194
214
  const projectId = resolveProjectId(projectOpt);
195
215
  if (!slug) {
196
216
  fail({
@@ -209,13 +229,15 @@ async function create(args) {
209
229
  }
210
230
 
211
231
  async function send(args) {
212
- const template = parseFlag(args, "--template");
213
- const to = parseFlag(args, "--to");
214
- const subject = parseFlag(args, "--subject");
215
- const html = parseFlag(args, "--html");
216
- const text = parseFlag(args, "--text");
217
- const fromName = parseFlag(args, "--from-name");
218
- const projectId = resolveProjectId(parseFlag(args, "--project"));
232
+ const valueFlags = ["--template", "--to", "--subject", "--html", "--text", "--from-name", "--project", "--vars", "--var"];
233
+ validateArgs(args, valueFlags);
234
+ const template = strictFlagValue(args, "--template");
235
+ const to = strictFlagValue(args, "--to");
236
+ const subject = strictFlagValue(args, "--subject");
237
+ const html = strictFlagValue(args, "--html");
238
+ const text = strictFlagValue(args, "--text");
239
+ const fromName = strictFlagValue(args, "--from-name");
240
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
219
241
  const variables = parseVars(args);
220
242
 
221
243
  if (!to) {
@@ -239,12 +261,14 @@ async function send(args) {
239
261
  }
240
262
 
241
263
  async function list(args) {
242
- const projectId = resolveProjectId(parseFlag(args, "--project"));
243
- const limit = parseFlag(args, "--limit");
244
- const after = parseFlag(args, "--after");
264
+ const valueFlags = ["--project", "--limit", "--after"];
265
+ validateArgs(args, valueFlags);
266
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
267
+ const limit = strictFlagValue(args, "--limit");
268
+ const after = strictFlagValue(args, "--after");
245
269
  try {
246
270
  const data = await getSdk().email.list(projectId, {
247
- limit: limit ? Number(limit) : undefined,
271
+ limit: limit ? parseIntegerFlag("--limit", limit) : undefined,
248
272
  after: after ?? undefined,
249
273
  });
250
274
  console.log(JSON.stringify(data, null, 2));
@@ -254,13 +278,9 @@ async function list(args) {
254
278
  }
255
279
 
256
280
  async function get(args) {
257
- let messageId = null;
258
- let projectOpt = null;
259
- for (let i = 0; i < args.length; i++) {
260
- if (args[i] === "--project" && args[i + 1]) { projectOpt = args[++i]; }
261
- else if (!args[i].startsWith("--") && !messageId) { messageId = args[i]; }
262
- }
263
- const projectId = resolveProjectId(projectOpt);
281
+ validateArgs(args, ["--project"]);
282
+ const messageId = positionalArgs(args, ["--project"])[0] ?? null;
283
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
264
284
  if (!messageId) {
265
285
  fail({
266
286
  code: "BAD_USAGE",
@@ -277,15 +297,11 @@ async function get(args) {
277
297
  }
278
298
 
279
299
  async function getRaw(args) {
280
- let messageId = null;
281
- let projectOpt = null;
282
- let outputFile = null;
283
- for (let i = 0; i < args.length; i++) {
284
- if (args[i] === "--project" && args[i + 1]) { projectOpt = args[++i]; }
285
- else if (args[i] === "--output" && args[i + 1]) { outputFile = args[++i]; }
286
- else if (!args[i].startsWith("--") && !messageId) { messageId = args[i]; }
287
- }
288
- const projectId = resolveProjectId(projectOpt);
300
+ const valueFlags = ["--project", "--output"];
301
+ validateArgs(args, valueFlags);
302
+ const messageId = positionalArgs(args, valueFlags)[0] ?? null;
303
+ const outputFile = strictFlagValue(args, "--output");
304
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
289
305
  if (!messageId) {
290
306
  fail({
291
307
  code: "BAD_USAGE",
@@ -311,19 +327,14 @@ async function getRaw(args) {
311
327
  }
312
328
 
313
329
  async function reply(args) {
314
- let messageId = null;
315
- let projectOpt = null;
316
- for (let i = 0; i < args.length; i++) {
317
- const a = args[i];
318
- if (a === "--project" && args[i + 1]) { projectOpt = args[++i]; }
319
- else if (a === "--html" || a === "--text" || a === "--subject" || a === "--from-name") { i++; }
320
- else if (!a.startsWith("--") && !messageId) { messageId = a; }
321
- }
322
- const html = parseFlag(args, "--html");
323
- const text = parseFlag(args, "--text");
324
- const subjectOverride = parseFlag(args, "--subject");
325
- const fromName = parseFlag(args, "--from-name");
326
- const projectId = resolveProjectId(projectOpt);
330
+ const valueFlags = ["--project", "--html", "--text", "--subject", "--from-name"];
331
+ validateArgs(args, valueFlags);
332
+ const messageId = positionalArgs(args, valueFlags)[0] ?? null;
333
+ const html = strictFlagValue(args, "--html");
334
+ const text = strictFlagValue(args, "--text");
335
+ const subjectOverride = strictFlagValue(args, "--subject");
336
+ const fromName = strictFlagValue(args, "--from-name");
337
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
327
338
 
328
339
  if (!messageId) {
329
340
  fail({
@@ -371,15 +382,9 @@ async function reply(args) {
371
382
  }
372
383
 
373
384
  async function deleteMailbox(args) {
374
- let positional = null;
375
- let projectOpt = null;
376
- for (let i = 0; i < args.length; i++) {
377
- const a = args[i];
378
- if (a === "--project" && args[i + 1]) { projectOpt = args[++i]; }
379
- else if (a === "--confirm") { /* flag */ }
380
- else if (!a.startsWith("--") && !positional) { positional = a; }
381
- }
382
- const projectId = resolveProjectId(projectOpt);
385
+ validateArgs(args, ["--project", "--confirm"], ["--project"]);
386
+ const positional = positionalArgs(args, ["--project"])[0] ?? null;
387
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
383
388
  const confirmed = args.includes("--confirm");
384
389
 
385
390
  if (!confirmed) {
@@ -398,7 +403,8 @@ async function deleteMailbox(args) {
398
403
  }
399
404
 
400
405
  async function status(args) {
401
- const projectId = resolveProjectId(parseFlag(args, "--project"));
406
+ validateArgs(args, ["--project"]);
407
+ const projectId = resolveProjectId(strictFlagValue(args, "--project"));
402
408
  try {
403
409
  const mb = await getSdk().email.getMailbox(projectId);
404
410
  console.log(JSON.stringify({ status: "ok", mailbox_id: mb.mailbox_id, address: mb.address, slug: mb.slug }));
@@ -408,6 +414,7 @@ async function status(args) {
408
414
  }
409
415
 
410
416
  export async function run(sub, args) {
417
+ args = normalizeArgv(args);
411
418
  if (!sub || sub === '--help' || sub === '-h') { console.log(HELP); process.exit(0); }
412
419
  if (Array.isArray(args) && (args.includes("--help") || args.includes("-h")) && sub !== "webhooks") { console.log(SUB_HELP[sub] || HELP); process.exit(0); }
413
420
  switch (sub) {