@dashai/cli 0.18.1 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import pc from 'picocolors';
2
3
  import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, watch, readdirSync, chmodSync, renameSync, mkdtempSync, statSync } from 'fs';
3
4
  import { tmpdir, platform, homedir } from 'os';
4
5
  import { resolve, join, relative, dirname, basename, sep } from 'path';
5
- import pc from 'picocolors';
6
6
  import { spawn, spawnSync } from 'child_process';
7
7
  import { intro, log, select, isCancel, cancel, spinner, outro, text, multiselect, confirm } from '@clack/prompts';
8
8
  import { Command, Option } from 'commander';
@@ -20,6 +20,41 @@ var __export = (target, all) => {
20
20
  for (var name in all)
21
21
  __defProp(target, name, { get: all[name], enumerable: true });
22
22
  };
23
+ function success(msg) {
24
+ process.stderr.write(`${pc.green("\u2713")} ${msg}
25
+ `);
26
+ }
27
+ function info(msg) {
28
+ process.stderr.write(`${pc.cyan("\u2139")} ${msg}
29
+ `);
30
+ }
31
+ function warn(msg) {
32
+ process.stderr.write(`${pc.yellow("\u26A0")} ${msg}
33
+ `);
34
+ }
35
+ function fail(msg) {
36
+ process.stderr.write(`${pc.red("\u2717")} ${msg}
37
+ `);
38
+ }
39
+ function out(msg) {
40
+ process.stdout.write(`${msg}
41
+ `);
42
+ }
43
+ function kv(key, value, padTo = 14) {
44
+ const padded = key.padEnd(padTo);
45
+ process.stdout.write(`${pc.bold(padded)} ${value}
46
+ `);
47
+ }
48
+ function code(s) {
49
+ return pc.cyan(s);
50
+ }
51
+ function dim(s) {
52
+ return pc.dim(s);
53
+ }
54
+ var init_output = __esm({
55
+ "src/lib/output.ts"() {
56
+ }
57
+ });
23
58
  function configDir() {
24
59
  if (process.env.XDG_CONFIG_HOME) {
25
60
  return join(process.env.XDG_CONFIG_HOME, DIR_NAME);
@@ -499,41 +534,6 @@ var init_api_client = __esm({
499
534
  };
500
535
  }
501
536
  });
502
- function success(msg) {
503
- process.stderr.write(`${pc.green("\u2713")} ${msg}
504
- `);
505
- }
506
- function info(msg) {
507
- process.stderr.write(`${pc.cyan("\u2139")} ${msg}
508
- `);
509
- }
510
- function warn(msg) {
511
- process.stderr.write(`${pc.yellow("\u26A0")} ${msg}
512
- `);
513
- }
514
- function fail(msg) {
515
- process.stderr.write(`${pc.red("\u2717")} ${msg}
516
- `);
517
- }
518
- function out(msg) {
519
- process.stdout.write(`${msg}
520
- `);
521
- }
522
- function kv(key, value, padTo = 14) {
523
- const padded = key.padEnd(padTo);
524
- process.stdout.write(`${pc.bold(padded)} ${value}
525
- `);
526
- }
527
- function code(s) {
528
- return pc.cyan(s);
529
- }
530
- function dim(s) {
531
- return pc.dim(s);
532
- }
533
- var init_output = __esm({
534
- "src/lib/output.ts"() {
535
- }
536
- });
537
537
 
538
538
  // src/lib/connect-status.ts
539
539
  async function reportConnectStatus(opts) {
@@ -5278,7 +5278,81 @@ var init_set_type = __esm({
5278
5278
  }
5279
5279
  });
5280
5280
 
5281
+ // src/lib/excess-args.ts
5282
+ init_output();
5283
+ var SMART_DASH_RE = /^[‒–—―−]/;
5284
+ var ExcessArgumentsError = class extends Error {
5285
+ constructor(message) {
5286
+ super(message);
5287
+ this.name = "ExcessArgumentsError";
5288
+ }
5289
+ };
5290
+ function commandPath(cmd) {
5291
+ const parts = [];
5292
+ let cursor = cmd;
5293
+ while (cursor) {
5294
+ parts.unshift(cursor.name());
5295
+ cursor = cursor.parent;
5296
+ }
5297
+ return parts.join(" ");
5298
+ }
5299
+ function excessOperandsError(actionCommand) {
5300
+ const registered = actionCommand.registeredArguments;
5301
+ if (registered.length > 0 && registered[registered.length - 1].variadic) {
5302
+ return null;
5303
+ }
5304
+ const operands = actionCommand.args;
5305
+ const stray = operands.slice(registered.length);
5306
+ const accepted = operands.slice(0, registered.length);
5307
+ const smartDashAccepted = accepted.filter((s) => SMART_DASH_RE.test(s));
5308
+ if (stray.length === 0 && smartDashAccepted.length === 0) return null;
5309
+ const path = commandPath(actionCommand);
5310
+ const expects = registered.length === 0 ? "takes no positional arguments" : `takes at most ${registered.length} positional argument${registered.length > 1 ? "s" : ""} (${registered.map((a) => `${a.required ? "<" : "["}${a.name()}${a.required ? ">" : "]"}`).join(" ")})`;
5311
+ const lines = [];
5312
+ if (stray.length > 0) {
5313
+ lines.push(
5314
+ `Unexpected argument${stray.length > 1 ? "s" : ""} ${stray.map((s) => `"${s}"`).join(", ")} \u2014 ${code(path)} ${expects}.`
5315
+ );
5316
+ }
5317
+ for (const tok of smartDashAccepted) {
5318
+ const slot = registered[accepted.indexOf(tok)];
5319
+ lines.push(
5320
+ `"${tok}" was read as the ${slot ? `<${slot.name()}>` : "positional"} argument but looks like a flag typed with a typographic dash (\u2013 / \u2014) instead of ASCII "--".`
5321
+ );
5322
+ }
5323
+ if ([...stray, ...smartDashAccepted].some((s) => SMART_DASH_RE.test(s))) {
5324
+ lines.push(
5325
+ `A token starts with a typographic dash (\u2013 / \u2014) instead of ASCII "--". If this command was copy-pasted, the editor/chat likely rewrote the double hyphen \u2014 retype the flag by hand (e.g. ${code("--force")}, ${code("--grant")}).`
5326
+ );
5327
+ }
5328
+ if (stray.some((s) => /^(module|datahub):/.test(s)) && actionCommand.options.some((o) => o.long === "--grant")) {
5329
+ lines.push(
5330
+ `Grant specs must be passed via the (repeatable) ${code("--grant")} flag, e.g. ${code("--grant module:employees:create,read")}.`
5331
+ );
5332
+ }
5333
+ if (stray.some((s) => s.startsWith("--"))) {
5334
+ lines.push(
5335
+ `Tokens after a bare ${code("--")} separator are treated as plain arguments, not flags \u2014 remove the ${code("--")}.`
5336
+ );
5337
+ }
5338
+ lines.push(
5339
+ "Refusing to continue: silently ignoring these arguments is how grantless (deny-all) API keys \u2014 or half-applied commands \u2014 happen by accident."
5340
+ );
5341
+ return lines.join("\n ");
5342
+ }
5343
+ function installExcessArgumentsGuard(program2) {
5344
+ program2.hook("preAction", (_thisCommand, actionCommand) => {
5345
+ const message = excessOperandsError(actionCommand);
5346
+ if (message === null) return;
5347
+ fail(message);
5348
+ throw new ExcessArgumentsError(message);
5349
+ });
5350
+ }
5351
+
5281
5352
  // src/bin.ts
5353
+ init_output();
5354
+
5355
+ // src/program.ts
5282
5356
  init_dev();
5283
5357
 
5284
5358
  // src/commands/login.ts
@@ -6676,7 +6750,7 @@ async function moduleDiffCommand(options) {
6676
6750
  return 0;
6677
6751
  }
6678
6752
 
6679
- // src/bin.ts
6753
+ // src/program.ts
6680
6754
  init_init();
6681
6755
 
6682
6756
  // src/commands/module/install.ts
@@ -9714,7 +9788,7 @@ function surfacePullFailure(err) {
9714
9788
  return 1;
9715
9789
  }
9716
9790
 
9717
- // src/bin.ts
9791
+ // src/program.ts
9718
9792
  init_scaffold();
9719
9793
 
9720
9794
  // src/commands/api-keys.ts
@@ -9722,32 +9796,6 @@ init_api_client();
9722
9796
  init_config();
9723
9797
  init_manifest_io();
9724
9798
  init_output();
9725
- var SMART_DASH_RE = /^[‒–—―−]/;
9726
- function strayArgsError(stray, usage) {
9727
- if (!stray || stray.length === 0) return null;
9728
- const lines = [
9729
- `Unexpected argument${stray.length > 1 ? "s" : ""} ${stray.map((s) => `"${s}"`).join(", ")} \u2014 ${usage}`
9730
- ];
9731
- if (stray.some((s) => SMART_DASH_RE.test(s))) {
9732
- lines.push(
9733
- `A token starts with a typographic dash (\u2013 / \u2014) instead of ASCII "--". If this command was copy-pasted, the editor/chat likely rewrote the double hyphen \u2014 retype the flag by hand (e.g. ${code("--grant")}, ${code("--full-access")}).`
9734
- );
9735
- }
9736
- if (stray.some((s) => /^(module|datahub):/.test(s))) {
9737
- lines.push(
9738
- `Grant specs must be passed via the (repeatable) ${code("--grant")} flag, e.g. ${code("--grant module:employees:create,read")}.`
9739
- );
9740
- }
9741
- if (stray.some((s) => s.startsWith("--"))) {
9742
- lines.push(
9743
- `Tokens after a bare ${code("--")} separator are treated as plain arguments, not flags \u2014 remove the ${code("--")}.`
9744
- );
9745
- }
9746
- lines.push(
9747
- "Refusing to continue: silently ignoring these arguments is how grantless (deny-all) keys get minted by accident."
9748
- );
9749
- return lines.join("\n ");
9750
- }
9751
9799
  function loadContext4(opts) {
9752
9800
  const cfg = readConfig();
9753
9801
  if (!cfg) {
@@ -9813,14 +9861,6 @@ async function resolveInstallKind(ctx) {
9813
9861
  return void 0;
9814
9862
  }
9815
9863
  async function apiKeysListCommand(options) {
9816
- const strayErr = strayArgsError(
9817
- options.stray,
9818
- "`dashwise api-keys list` takes no positional arguments."
9819
- );
9820
- if (strayErr) {
9821
- fail(strayErr);
9822
- return 1;
9823
- }
9824
9864
  let ctx;
9825
9865
  try {
9826
9866
  ctx = loadContext4(options);
@@ -9871,20 +9911,6 @@ async function apiKeysListCommand(options) {
9871
9911
  return 0;
9872
9912
  }
9873
9913
  async function apiKeysCreateCommand(nameArg, options) {
9874
- if (nameArg !== void 0 && SMART_DASH_RE.test(nameArg)) {
9875
- fail(
9876
- `"${nameArg}" was read as the key NAME but looks like a flag typed with a typographic dash (\u2013 / \u2014) instead of ASCII "--". If this command was copy-pasted, the editor/chat likely rewrote the double hyphen \u2014 retype the flag by hand (e.g. ${code("--grant")}, ${code("--full-access")}).`
9877
- );
9878
- return 1;
9879
- }
9880
- const strayErr = strayArgsError(
9881
- options.stray,
9882
- "`dashwise api-keys create` takes a single <name>."
9883
- );
9884
- if (strayErr) {
9885
- fail(strayErr);
9886
- return 1;
9887
- }
9888
9914
  const name = nameArg ?? options.name;
9889
9915
  if (!name) {
9890
9916
  fail("Usage: `dashwise api-keys create <name>` (e.g. `dashwise api-keys create production`)");
@@ -9973,14 +9999,6 @@ async function apiKeysCreateCommand(nameArg, options) {
9973
9999
  return 0;
9974
10000
  }
9975
10001
  async function apiKeysRevokeCommand(keyIdArg, options) {
9976
- const strayErr = strayArgsError(
9977
- options.stray,
9978
- "`dashwise api-keys revoke` takes a single <key-id> \u2014 extra ids would be silently skipped."
9979
- );
9980
- if (strayErr) {
9981
- fail(strayErr);
9982
- return 1;
9983
- }
9984
10002
  if (!keyIdArg) {
9985
10003
  fail("Usage: `dashwise api-keys revoke <key-id>` \u2014 id from `dashwise api-keys list`");
9986
10004
  return 1;
@@ -11430,7 +11448,7 @@ async function sleep4(ms, aborted) {
11430
11448
  }
11431
11449
  }
11432
11450
 
11433
- // src/bin.ts
11451
+ // src/program.ts
11434
11452
  init_output();
11435
11453
  var program = new Command();
11436
11454
  program.name("dashwise").description("DashWise CLI \u2014 log in, author modules, publish to the marketplace.").version(getVersion(), "-v, --version", "Show the CLI version + exit").option(
@@ -11443,6 +11461,7 @@ program.hook("preAction", () => {
11443
11461
  process.env.DASHWISE_API_URL = apiUrl.replace(/\/+$/, "");
11444
11462
  }
11445
11463
  });
11464
+ installExcessArgumentsGuard(program);
11446
11465
  program.command("login").description("Sign in via the device-code flow.").option("--no-prompt", 'Skip the "open browser" prompt; just print the URL.').option("--name <name>", "Suggested name for the minted token (default: dashwise-cli).").action(async (cmdOpts) => {
11447
11466
  const apiUrl = program.opts().apiUrl;
11448
11467
  const exit = await loginCommand({
@@ -11817,15 +11836,12 @@ apiKeysCmd.command("list").description(
11817
11836
  "Target a specific installation id instead of the cached dev install (production installs included). Find ids via `dashwise module status <slug>`.",
11818
11837
  parseIntOption
11819
11838
  ).option("--all", "Include revoked + expired keys in the output.").option("--json", "Emit JSON instead of the human-friendly table.").action(
11820
- async (cmdOpts, cmd) => {
11839
+ async (cmdOpts) => {
11821
11840
  process.exitCode = await apiKeysListCommand({
11822
11841
  ...cmdOpts.dir !== void 0 ? { dir: cmdOpts.dir } : {},
11823
11842
  ...cmdOpts.install !== void 0 ? { install: cmdOpts.install } : {},
11824
11843
  ...cmdOpts.all !== void 0 ? { all: cmdOpts.all } : {},
11825
- ...cmdOpts.json !== void 0 ? { json: cmdOpts.json } : {},
11826
- // Operands commander would otherwise SILENTLY drop (default
11827
- // allowExcessArguments) — the command hard-errors on them.
11828
- ...cmd.args.length > 0 ? { stray: cmd.args } : {}
11844
+ ...cmdOpts.json !== void 0 ? { json: cmdOpts.json } : {}
11829
11845
  });
11830
11846
  }
11831
11847
  );
@@ -11851,8 +11867,7 @@ apiKeysCmd.command("create [name]").description(
11851
11867
  "--raw-only",
11852
11868
  "Print only the plaintext key on stdout; chatter goes to stderr. Useful for shell capture: `KEY=$(dashwise api-keys create prod --raw-only)`"
11853
11869
  ).action(
11854
- async (nameArg, cmdOpts, cmd) => {
11855
- const stray = cmd.args.slice(1);
11870
+ async (nameArg, cmdOpts) => {
11856
11871
  process.exitCode = await apiKeysCreateCommand(nameArg, {
11857
11872
  ...cmdOpts.dir !== void 0 ? { dir: cmdOpts.dir } : {},
11858
11873
  ...cmdOpts.install !== void 0 ? { install: cmdOpts.install } : {},
@@ -11860,8 +11875,7 @@ apiKeysCmd.command("create [name]").description(
11860
11875
  ...cmdOpts.grant !== void 0 && cmdOpts.grant.length > 0 ? { grant: cmdOpts.grant } : {},
11861
11876
  ...cmdOpts.fullAccess !== void 0 ? { fullAccess: cmdOpts.fullAccess } : {},
11862
11877
  ...cmdOpts.expires !== void 0 ? { expires: cmdOpts.expires } : {},
11863
- ...cmdOpts.rawOnly !== void 0 ? { rawOnly: cmdOpts.rawOnly } : {},
11864
- ...stray.length > 0 ? { stray } : {}
11878
+ ...cmdOpts.rawOnly !== void 0 ? { rawOnly: cmdOpts.rawOnly } : {}
11865
11879
  });
11866
11880
  }
11867
11881
  );
@@ -11872,13 +11886,11 @@ apiKeysCmd.command("revoke [key-id]").description(
11872
11886
  "Target a specific installation id instead of the cached dev install (production installs included). Find ids via `dashwise module status <slug>`.",
11873
11887
  parseIntOption
11874
11888
  ).option("-y, --yes", "Skip the per-key confirmation message (for CI / scripts).").action(
11875
- async (keyIdArg, cmdOpts, cmd) => {
11876
- const stray = cmd.args.slice(1);
11889
+ async (keyIdArg, cmdOpts) => {
11877
11890
  process.exitCode = await apiKeysRevokeCommand(keyIdArg, {
11878
11891
  ...cmdOpts.dir !== void 0 ? { dir: cmdOpts.dir } : {},
11879
11892
  ...cmdOpts.install !== void 0 ? { install: cmdOpts.install } : {},
11880
- ...cmdOpts.yes !== void 0 ? { yes: cmdOpts.yes } : {},
11881
- ...stray.length > 0 ? { stray } : {}
11893
+ ...cmdOpts.yes !== void 0 ? { yes: cmdOpts.yes } : {}
11882
11894
  });
11883
11895
  }
11884
11896
  );
@@ -12213,19 +12225,8 @@ fieldCmd.command("set-type <table-slug> <field-slug> <new-type>").description(
12213
12225
  );
12214
12226
  }
12215
12227
  );
12216
- (async () => {
12217
- try {
12218
- await program.parseAsync(process.argv);
12219
- } catch (err) {
12220
- fail(`Unhandled error: ${err.message ?? String(err)}`);
12221
- if (process.env.DASHWISE_DEBUG) {
12222
- console.error(err);
12223
- }
12224
- process.exitCode = 1;
12225
- }
12226
- })();
12227
12228
  function getVersion() {
12228
- return "0.18.1";
12229
+ return "0.18.2";
12229
12230
  }
12230
12231
  function parseIntOption(value) {
12231
12232
  const n = Number.parseInt(value, 10);
@@ -12237,5 +12238,22 @@ function parseIntOption(value) {
12237
12238
  function collectRepeated(value, previous) {
12238
12239
  return [...previous, value];
12239
12240
  }
12241
+
12242
+ // src/bin.ts
12243
+ (async () => {
12244
+ try {
12245
+ await program.parseAsync(process.argv);
12246
+ } catch (err) {
12247
+ if (err instanceof ExcessArgumentsError) {
12248
+ process.exitCode = 1;
12249
+ return;
12250
+ }
12251
+ fail(`Unhandled error: ${err.message ?? String(err)}`);
12252
+ if (process.env.DASHWISE_DEBUG) {
12253
+ console.error(err);
12254
+ }
12255
+ process.exitCode = 1;
12256
+ }
12257
+ })();
12240
12258
  //# sourceMappingURL=bin.js.map
12241
12259
  //# sourceMappingURL=bin.js.map