@artblocks/abx-cli 0.1.0-alpha.3 → 0.1.0-alpha.31

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 (152) hide show
  1. package/CHANGELOG.md +3694 -0
  2. package/assets/renderer-scaffold/README.md +2 -2
  3. package/assets/renderer-scaffold/src/MyRenderer.sol +2 -2
  4. package/assets/renderer-scaffold/src/interfaces/IAbxFieldRenderer.sol +1 -1
  5. package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +17 -0
  6. package/assets/renderer-scaffold/test/MyRenderer.t.sol +51 -2
  7. package/dist/bin.d.ts +27 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +64 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/commands/deploy.d.ts +242 -0
  12. package/dist/commands/deploy.d.ts.map +1 -0
  13. package/dist/commands/deploy.js +4764 -0
  14. package/dist/commands/deploy.js.map +1 -0
  15. package/dist/commands/project.d.ts +257 -0
  16. package/dist/commands/project.d.ts.map +1 -0
  17. package/dist/commands/project.js +1299 -0
  18. package/dist/commands/project.js.map +1 -0
  19. package/dist/commands/reads.d.ts +64 -0
  20. package/dist/commands/reads.d.ts.map +1 -0
  21. package/dist/commands/reads.js +701 -0
  22. package/dist/commands/reads.js.map +1 -0
  23. package/dist/commands/scaffold.d.ts +73 -0
  24. package/dist/commands/scaffold.d.ts.map +1 -0
  25. package/dist/commands/scaffold.js +679 -0
  26. package/dist/commands/scaffold.js.map +1 -0
  27. package/dist/commands/service.d.ts +41 -0
  28. package/dist/commands/service.d.ts.map +1 -0
  29. package/dist/commands/service.js +618 -0
  30. package/dist/commands/service.js.map +1 -0
  31. package/dist/commands/storage.d.ts +51 -0
  32. package/dist/commands/storage.d.ts.map +1 -0
  33. package/dist/commands/storage.js +370 -0
  34. package/dist/commands/storage.js.map +1 -0
  35. package/dist/commands/submit-app.d.ts +58 -0
  36. package/dist/commands/submit-app.d.ts.map +1 -0
  37. package/dist/commands/submit-app.js +512 -0
  38. package/dist/commands/submit-app.js.map +1 -0
  39. package/dist/config.d.ts +90 -2
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +285 -11
  42. package/dist/config.js.map +1 -1
  43. package/dist/conformance.d.ts +31 -0
  44. package/dist/conformance.d.ts.map +1 -0
  45. package/dist/conformance.js +393 -0
  46. package/dist/conformance.js.map +1 -0
  47. package/dist/deps.d.ts +6 -39
  48. package/dist/deps.d.ts.map +1 -1
  49. package/dist/deps.js +4 -68
  50. package/dist/deps.js.map +1 -1
  51. package/dist/errors.d.ts +20 -0
  52. package/dist/errors.d.ts.map +1 -0
  53. package/dist/errors.js +25 -0
  54. package/dist/errors.js.map +1 -0
  55. package/dist/flag-allowlists.d.ts +53 -0
  56. package/dist/flag-allowlists.d.ts.map +1 -0
  57. package/dist/flag-allowlists.js +157 -0
  58. package/dist/flag-allowlists.js.map +1 -0
  59. package/dist/flags.d.ts +45 -0
  60. package/dist/flags.d.ts.map +1 -1
  61. package/dist/flags.js +117 -1
  62. package/dist/flags.js.map +1 -1
  63. package/dist/jsonout.d.ts +37 -0
  64. package/dist/jsonout.d.ts.map +1 -0
  65. package/dist/jsonout.js +68 -0
  66. package/dist/jsonout.js.map +1 -0
  67. package/dist/kind.d.ts +61 -0
  68. package/dist/kind.d.ts.map +1 -0
  69. package/dist/kind.js +111 -0
  70. package/dist/kind.js.map +1 -0
  71. package/dist/main.js +699 -4736
  72. package/dist/main.js.map +1 -1
  73. package/dist/mintpage.d.ts +17 -2
  74. package/dist/mintpage.d.ts.map +1 -1
  75. package/dist/mintpage.js +241 -54
  76. package/dist/mintpage.js.map +1 -1
  77. package/dist/output.d.ts +179 -0
  78. package/dist/output.d.ts.map +1 -0
  79. package/dist/output.js +756 -0
  80. package/dist/output.js.map +1 -0
  81. package/dist/ownerops.d.ts +302 -51
  82. package/dist/ownerops.d.ts.map +1 -1
  83. package/dist/ownerops.js +1780 -357
  84. package/dist/ownerops.js.map +1 -1
  85. package/dist/preview.d.ts +81 -0
  86. package/dist/preview.d.ts.map +1 -0
  87. package/dist/preview.js +535 -0
  88. package/dist/preview.js.map +1 -0
  89. package/dist/prompt.d.ts +17 -0
  90. package/dist/prompt.d.ts.map +1 -0
  91. package/dist/prompt.js +19 -0
  92. package/dist/prompt.js.map +1 -0
  93. package/dist/provision.d.ts.map +1 -1
  94. package/dist/provision.js +16 -8
  95. package/dist/provision.js.map +1 -1
  96. package/dist/remote.d.ts +153 -52
  97. package/dist/remote.d.ts.map +1 -1
  98. package/dist/remote.js +406 -46
  99. package/dist/remote.js.map +1 -1
  100. package/dist/riskgate.d.ts +58 -0
  101. package/dist/riskgate.d.ts.map +1 -0
  102. package/dist/riskgate.js +212 -0
  103. package/dist/riskgate.js.map +1 -0
  104. package/dist/scaffold.d.ts +10 -0
  105. package/dist/scaffold.d.ts.map +1 -0
  106. package/dist/scaffold.js +52 -0
  107. package/dist/scaffold.js.map +1 -0
  108. package/dist/schema.d.ts +36 -1
  109. package/dist/schema.d.ts.map +1 -1
  110. package/dist/schema.js +121 -26
  111. package/dist/schema.js.map +1 -1
  112. package/dist/script-chunks.d.ts +8 -0
  113. package/dist/script-chunks.d.ts.map +1 -0
  114. package/dist/script-chunks.js +35 -0
  115. package/dist/script-chunks.js.map +1 -0
  116. package/dist/served.d.ts +30 -0
  117. package/dist/served.d.ts.map +1 -0
  118. package/dist/served.js +112 -0
  119. package/dist/served.js.map +1 -0
  120. package/dist/signer.d.ts +13 -0
  121. package/dist/signer.d.ts.map +1 -1
  122. package/dist/signer.js +84 -15
  123. package/dist/signer.js.map +1 -1
  124. package/dist/update-check.d.ts +83 -4
  125. package/dist/update-check.d.ts.map +1 -1
  126. package/dist/update-check.js +140 -19
  127. package/dist/update-check.js.map +1 -1
  128. package/package.json +12 -8
  129. package/skill/SKILL.md +351 -151
  130. package/skill/reference/code-projects.md +183 -26
  131. package/skill/reference/creator-token.md +99 -0
  132. package/skill/reference/decisions.md +174 -0
  133. package/skill/reference/hosting.md +63 -19
  134. package/skill/reference/operating.md +116 -12
  135. package/skill/reference/setup.md +57 -6
  136. package/skill/reference/troubleshooting.md +42 -5
  137. package/dist/inspect.d.ts +0 -48
  138. package/dist/inspect.d.ts.map +0 -1
  139. package/dist/inspect.js +0 -184
  140. package/dist/inspect.js.map +0 -1
  141. package/dist/migrate.d.ts +0 -65
  142. package/dist/migrate.d.ts.map +0 -1
  143. package/dist/migrate.js +0 -180
  144. package/dist/migrate.js.map +0 -1
  145. package/dist/onchain-uri.d.ts +0 -97
  146. package/dist/onchain-uri.d.ts.map +0 -1
  147. package/dist/onchain-uri.js +0 -243
  148. package/dist/onchain-uri.js.map +0 -1
  149. package/dist/upload.d.ts +0 -28
  150. package/dist/upload.d.ts.map +0 -1
  151. package/dist/upload.js +0 -41
  152. package/dist/upload.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,QAAQ,CAAS;IACjB,cAAc,CAAU;IAEjC,YAAY,OAAe,EAAE,QAAQ,GAAG,CAAC,EAAE,cAAc,GAAG,KAAK;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Per-command flag allowlists — the one place that knows which flags each command accepts, so the
3
+ * dispatcher can surface a typo'd or unsupported flag instead of silently ignoring it (B30).
4
+ *
5
+ * WHY THIS FILE EXISTS, and why the obvious shortcut doesn't work
6
+ * --------------------------------------------------------------
7
+ * The CLI used to have three different behaviors for an unrecognized flag: `deploy*` REFUSED,
8
+ * `preview`/`tokens`/`storage status`/`attach` WARNED, and ~35 other commands said nothing at all —
9
+ * so `abx set-royalty --bsp 500` or `abx minter buy --quantiy 5` did something quietly different from
10
+ * what was asked. That silence is the worst failure mode the CLI has, because the creator's next
11
+ * action is to believe it worked.
12
+ *
13
+ * The tempting fix is to DERIVE each allowlist from the `usage` string every command already declares.
14
+ * An audit of all ~45 commands says that would be actively harmful: several shared helpers read flags
15
+ * that appear in NO usage string anywhere. `storageOverrides()` reads twelve
16
+ * (`--backend`, `--gateway`, `--public-base`, `--storage-signer`, …) and is pulled in by `add`,
17
+ * `render`, `effects`, `migrate`, `storage upload`, and `storage balance|topup`; `--remote-token` is
18
+ * read by `index`, `verify`, `forget`, `status`, and `migrate`. A usage-derived allowlist would warn on
19
+ * every one of those — a false warning on a VALID flag, which is worse than the silence it replaces,
20
+ * because a notice people learn to distrust stops working for the real cases too.
21
+ *
22
+ * So the sets below are explicit, and composed from the shared groups by name. A command absent from
23
+ * `COMMAND_FLAGS` is simply not checked — this can grow incrementally, and an unlisted command keeps
24
+ * exactly its old behavior rather than acquiring a half-right allowlist.
25
+ */
26
+ /**
27
+ * Flags EVERY owner write accepts: the signing lane (`laneFromFlags`), the opt-in confirm gate, the
28
+ * wallet-lane plumbing, the post-write reindex nudge (`reindexIfKnown` → `resolveRemote`), and
29
+ * `--json`. Sourced from `riskgate.ts` + `ownerops.ts`, never from a usage string.
30
+ */
31
+ export declare const SHARED_WRITE: readonly ["send", "sign", "unsigned", "dry-run", "yes", "confirm", "port", "sign-url-file", "remote", "remote-token", "json"];
32
+ /**
33
+ * What `storageOverrides()` (config.ts) reads. Any command that resolves a storage backend from flags
34
+ * accepts all twelve — and none of them are documented per-command, which is exactly why a
35
+ * usage-derived allowlist would have been wrong.
36
+ */
37
+ export declare const STORAGE_OVERRIDE: readonly ["backend", "endpoint", "bucket", "region", "prefix", "public-base", "gateway", "mode", "api-url", "upload-url", "provider", "storage-signer"];
38
+ /** `remoteFlag()` / `resolveRemote()` — a named service plus its token. */
39
+ export declare const REMOTE: readonly ["remote", "remote-token"];
40
+ /**
41
+ * Command → accepted flags. Keys are the dispatch names in `main.ts`; a two-word command is keyed by
42
+ * `"<cmd> <sub>"` (e.g. `"storage upload"`) and falls back to the bare command when no subcommand row
43
+ * exists. `deploy`/`deploy-series`/`deploy-code` are deliberately ABSENT: they already enforce their
44
+ * own exhaustive allowlists via `refuseStrayFlags`, and duplicating those sets here would be a second
45
+ * copy to drift.
46
+ */
47
+ export declare const COMMAND_FLAGS: Record<string, ReadonlySet<string>>;
48
+ /**
49
+ * The allowlist for a dispatched command, preferring a `"<cmd> <sub>"` row. Returns undefined when the
50
+ * command isn't listed, which means "don't check" — never "nothing is allowed".
51
+ */
52
+ export declare function allowlistFor(cmd: string, sub?: string): ReadonlySet<string> | undefined;
53
+ //# sourceMappingURL=flag-allowlists.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-allowlists.d.ts","sourceRoot":"","sources":["../src/flag-allowlists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,+HAYf,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,yJAanB,CAAC;AAEX,2EAA2E;AAC3E,eAAO,MAAM,MAAM,qCAAsC,CAAC;AAI1D;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAmF7D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAMvF"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Per-command flag allowlists — the one place that knows which flags each command accepts, so the
3
+ * dispatcher can surface a typo'd or unsupported flag instead of silently ignoring it (B30).
4
+ *
5
+ * WHY THIS FILE EXISTS, and why the obvious shortcut doesn't work
6
+ * --------------------------------------------------------------
7
+ * The CLI used to have three different behaviors for an unrecognized flag: `deploy*` REFUSED,
8
+ * `preview`/`tokens`/`storage status`/`attach` WARNED, and ~35 other commands said nothing at all —
9
+ * so `abx set-royalty --bsp 500` or `abx minter buy --quantiy 5` did something quietly different from
10
+ * what was asked. That silence is the worst failure mode the CLI has, because the creator's next
11
+ * action is to believe it worked.
12
+ *
13
+ * The tempting fix is to DERIVE each allowlist from the `usage` string every command already declares.
14
+ * An audit of all ~45 commands says that would be actively harmful: several shared helpers read flags
15
+ * that appear in NO usage string anywhere. `storageOverrides()` reads twelve
16
+ * (`--backend`, `--gateway`, `--public-base`, `--storage-signer`, …) and is pulled in by `add`,
17
+ * `render`, `effects`, `migrate`, `storage upload`, and `storage balance|topup`; `--remote-token` is
18
+ * read by `index`, `verify`, `forget`, `status`, and `migrate`. A usage-derived allowlist would warn on
19
+ * every one of those — a false warning on a VALID flag, which is worse than the silence it replaces,
20
+ * because a notice people learn to distrust stops working for the real cases too.
21
+ *
22
+ * So the sets below are explicit, and composed from the shared groups by name. A command absent from
23
+ * `COMMAND_FLAGS` is simply not checked — this can grow incrementally, and an unlisted command keeps
24
+ * exactly its old behavior rather than acquiring a half-right allowlist.
25
+ */
26
+ /**
27
+ * Flags EVERY owner write accepts: the signing lane (`laneFromFlags`), the opt-in confirm gate, the
28
+ * wallet-lane plumbing, the post-write reindex nudge (`reindexIfKnown` → `resolveRemote`), and
29
+ * `--json`. Sourced from `riskgate.ts` + `ownerops.ts`, never from a usage string.
30
+ */
31
+ export const SHARED_WRITE = [
32
+ 'send',
33
+ 'sign',
34
+ 'unsigned',
35
+ 'dry-run',
36
+ 'yes',
37
+ 'confirm',
38
+ 'port',
39
+ 'sign-url-file',
40
+ 'remote',
41
+ 'remote-token',
42
+ 'json',
43
+ ];
44
+ /**
45
+ * What `storageOverrides()` (config.ts) reads. Any command that resolves a storage backend from flags
46
+ * accepts all twelve — and none of them are documented per-command, which is exactly why a
47
+ * usage-derived allowlist would have been wrong.
48
+ */
49
+ export const STORAGE_OVERRIDE = [
50
+ 'backend',
51
+ 'endpoint',
52
+ 'bucket',
53
+ 'region',
54
+ 'prefix',
55
+ 'public-base',
56
+ 'gateway',
57
+ 'mode',
58
+ 'api-url',
59
+ 'upload-url',
60
+ 'provider',
61
+ 'storage-signer',
62
+ ];
63
+ /** `remoteFlag()` / `resolveRemote()` — a named service plus its token. */
64
+ export const REMOTE = ['remote', 'remote-token'];
65
+ const set = (...groups) => new Set(groups.flat());
66
+ /**
67
+ * Command → accepted flags. Keys are the dispatch names in `main.ts`; a two-word command is keyed by
68
+ * `"<cmd> <sub>"` (e.g. `"storage upload"`) and falls back to the bare command when no subcommand row
69
+ * exists. `deploy`/`deploy-series`/`deploy-code` are deliberately ABSENT: they already enforce their
70
+ * own exhaustive allowlists via `refuseStrayFlags`, and duplicating those sets here would be a second
71
+ * copy to drift.
72
+ */
73
+ export const COMMAND_FLAGS = {
74
+ // ── read-only ──
75
+ inspect: set(['dep']),
76
+ predict: set(['salt', 'for', 'factory', 'copies', 'script', 'code-dir', 'image-renderer', 'dir', 'image']),
77
+ tokenuri: set(['token', 'fetch', 'json']),
78
+ contracturi: set([]),
79
+ tokens: set(['json', 'limit', 'from', 'holder']),
80
+ state: set(['json']),
81
+ status: set(['watch'], REMOTE),
82
+ verify: set(['json', 'yes', 'generator'], REMOTE),
83
+ doctor: set(['for', 'fix', 'global', 'agent']),
84
+ serve: set(['port']),
85
+ 'skill install': set(['target', 'global', 'agent']),
86
+ 'skill path': set(['target', 'global', 'agent']),
87
+ // ── indexing / projection ──
88
+ add: set(['from-block', 'factory', 'label', 'description', 'external-url', 'full', 'yes', 'traits', 'attributes', 'no-wait', 'dry-run'], REMOTE, STORAGE_OVERRIDE),
89
+ index: set(['full', 'no-wait', 'yes'], REMOTE),
90
+ forget: set([], REMOTE),
91
+ migrate: set(['from', 'to', 'from-block', 'factory', 'label', 'yes'], REMOTE, STORAGE_OVERRIDE),
92
+ remote: set(['conformance', 'remote-token', 'chain-id', 'address', 'from-block']),
93
+ // ── rendering / effects ──
94
+ render: set(['force', 'effects-url'], REMOTE, STORAGE_OVERRIDE),
95
+ effects: set(['once', 'port', 'interval-ms', 'concurrency'], REMOTE, STORAGE_OVERRIDE),
96
+ 'mint-page': set(['dir', 'name', 'rpc', 'minter-contract']),
97
+ 'scaffold-renderer': set(['force']),
98
+ // ── hosting artifacts ──
99
+ 'deploy-resolver': set(['provider', 'domain', 'app', 'dir', 'from-source']),
100
+ 'deploy-effects': set(['provider', 'resolver-url', 'app', 'dir', 'interval-ms', 'env-id']),
101
+ // ── storage ──
102
+ // `show` honors the full override set now (it previews what a given set of flags WOULD resolve to);
103
+ // before that it read env-only, and the warning correctly fired because the flags really were ignored.
104
+ storage: set(['check'], STORAGE_OVERRIDE),
105
+ 'storage show': set(['check'], STORAGE_OVERRIDE),
106
+ 'storage upload': set(['key', 'json', 'dry-run'], STORAGE_OVERRIDE),
107
+ // `status` documents --json and --primary-only in its own usage string; without a row here it fell
108
+ // back to the bare `storage` row and warned "unrecognized flag(s), ignored: --json" while the flag
109
+ // visibly worked — a readout contradicting itself is worse than no readout.
110
+ 'storage status': set(['json', 'primary-only'], STORAGE_OVERRIDE),
111
+ 'storage balance': set(['for'], STORAGE_OVERRIDE),
112
+ 'storage topup': set(['usd'], STORAGE_OVERRIDE),
113
+ 'storage backup-key': set(['out']),
114
+ // ── owner writes (every one also takes SHARED_WRITE) ──
115
+ refresh: set(['token']), // sends no tx — SHARED_WRITE deliberately does NOT apply
116
+ 'set-minter': set(['minter'], SHARED_WRITE),
117
+ 'set-max-invocations': set(['max'], SHARED_WRITE),
118
+ 'ping-uri': set(['token-ids'], SHARED_WRITE),
119
+ 'configure-param': set(['file', 'remote'], SHARED_WRITE),
120
+ 'submit-app': set(['name', 'summary', 'description', 'mark', 'tone', 'category', 'stage', 'url', 'url-label', 'image', 'tags', 'registry', 'minter'], SHARED_WRITE),
121
+ 'set-schema': set(['schema', 'force'], SHARED_WRITE),
122
+ 'retire-param': set([], SHARED_WRITE),
123
+ 'set-param-hooks': set(['configure', 'augment', 'transfer', 'clear'], SHARED_WRITE),
124
+ 'set-dependency': set([], SHARED_WRITE),
125
+ 'remove-last-dependency': set([], SHARED_WRITE),
126
+ 'set-dependency-registry': set([], SHARED_WRITE),
127
+ 'lock-dependencies': set([], SHARED_WRITE),
128
+ 'lock-script': set([], SHARED_WRITE),
129
+ 'lock-param-hooks': set([], SHARED_WRITE),
130
+ 'set-primary-payee': set(['payee'], SHARED_WRITE),
131
+ pause: set([], SHARED_WRITE),
132
+ unpause: set([], SHARED_WRITE),
133
+ 'set-token-uri': set(['uri', 'override', 'token'], SHARED_WRITE),
134
+ 'set-contract-uri': set(['uri', 'override'], SHARED_WRITE),
135
+ 'set-royalty': set(['bps', 'receiver'], SHARED_WRITE),
136
+ 'set-royalty-cap': set(['cap'], SHARED_WRITE),
137
+ 'set-transfer-validator': set([], SHARED_WRITE),
138
+ 'set-seed-source': set([], SHARED_WRITE),
139
+ 'set-field': set(['field', 'text', 'value', 'representation', 'collection', 'token', 'file', 'compress', 'allow-unreadable-onchain'], SHARED_WRITE),
140
+ 'lock-field': set(['field', 'collection', 'token', 'force-field'], SHARED_WRITE),
141
+ 'set-renderer': set(['collection', 'off', 'renderer'], SHARED_WRITE),
142
+ 'lock-uri': set(['collection'], SHARED_WRITE),
143
+ 'set-admin': set(['to'], SHARED_WRITE),
144
+ };
145
+ /**
146
+ * The allowlist for a dispatched command, preferring a `"<cmd> <sub>"` row. Returns undefined when the
147
+ * command isn't listed, which means "don't check" — never "nothing is allowed".
148
+ */
149
+ export function allowlistFor(cmd, sub) {
150
+ if (sub) {
151
+ const withSub = COMMAND_FLAGS[`${cmd} ${sub}`];
152
+ if (withSub)
153
+ return withSub;
154
+ }
155
+ return COMMAND_FLAGS[cmd];
156
+ }
157
+ //# sourceMappingURL=flag-allowlists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-allowlists.js","sourceRoot":"","sources":["../src/flag-allowlists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,MAAM;IACN,MAAM;IACN,UAAU;IACV,SAAS;IACT,KAAK;IACL,SAAS;IACT,MAAM;IACN,eAAe;IACf,QAAQ;IACR,cAAc;IACd,MAAM;CACE,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,SAAS;IACT,MAAM;IACN,SAAS;IACT,YAAY;IACZ,UAAU;IACV,gBAAgB;CACR,CAAC;AAEX,2EAA2E;AAC3E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAU,CAAC;AAE1D,MAAM,GAAG,GAAG,CAAC,GAAG,MAAwC,EAAuB,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAEzG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAwC;IAChE,kBAAkB;IAClB,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1G,QAAQ,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IACjD,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACpB,eAAe,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEhD,8BAA8B;IAC9B,GAAG,EAAE,GAAG,CACN,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC,EAC9H,MAAM,EACN,gBAAgB,CACjB;IACD,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAC9C,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC;IAC/F,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAEjF,4BAA4B;IAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC;IAC/D,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC;IACtF,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAC3D,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAEnC,0BAA0B;IAC1B,iBAAiB,EAAE,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAC3E,gBAAgB,EAAE,GAAG,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAE1F,gBAAgB;IAChB,oGAAoG;IACpG,uGAAuG;IACvG,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IACzC,cAAc,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAChD,gBAAgB,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,gBAAgB,CAAC;IACnE,mGAAmG;IACnG,mGAAmG;IACnG,4EAA4E;IAC5E,gBAAgB,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,gBAAgB,CAAC;IACjE,iBAAiB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACjD,eAAe,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAC/C,oBAAoB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAElC,yDAAyD;IACzD,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,yDAAyD;IAClF,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IAC3C,qBAAqB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IACjD,UAAU,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC5C,iBAAiB,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxD,YAAY,EAAE,GAAG,CACf,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAClI,YAAY,CACb;IACD,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;IACpD,cAAc,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACrC,iBAAiB,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;IACnF,gBAAgB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACvC,wBAAwB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAC/C,yBAAyB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAChD,mBAAmB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1C,aAAa,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACpC,kBAAkB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACzC,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IACjD,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAC5B,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAC9B,eAAe,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;IAChE,kBAAkB,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1D,aAAa,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IACrD,iBAAiB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC7C,wBAAwB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IAC/C,iBAAiB,EAAE,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACxC,WAAW,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,0BAA0B,CAAC,EAAE,YAAY,CAAC;IACnJ,YAAY,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,YAAY,CAAC;IAChF,cAAc,EAAE,GAAG,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IACpE,UAAU,EAAE,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC7C,WAAW,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;CACvC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAY;IACpD,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QAC/C,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IACD,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC"}
package/dist/flags.d.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  * the first (a real footgun on a multi-param drop; a Select's options use `|` not `,`, so the
10
10
  * comma-join never collides with an option list).
11
11
  */
12
+ import { type Hex } from 'viem';
12
13
  export type Flags = Record<string, string | undefined>;
13
14
  /** Flags where every occurrence counts (values comma-join, in argv order). */
14
15
  export declare const REPEATABLE_FLAGS: ReadonlySet<string>;
@@ -18,7 +19,22 @@ export declare const REPEATABLE_FLAGS: ReadonlySet<string>;
18
19
  * `no-update-check` opts out of the startup update nudge (see update-check.ts).
19
20
  */
20
21
  export declare const GLOBAL_FLAGS: ReadonlySet<string>;
22
+ /** Whether `--dry-run` was passed. The one place that truthiness is decided — every write command
23
+ * (owner-op or deploy) reads it through here rather than hand-rolling `!!flags['dry-run']`, so a
24
+ * fresh command can't ship with a *slightly* different spelling of the same check (or skip it). */
25
+ export declare function isDryRun(flags: Flags): boolean;
26
+ /** Whether `--allow-unreadable-onchain` was passed — the override for the render-gas refusal
27
+ * (`guardOnChainSize` in ownerops.ts). Decided in one place for the same reason as
28
+ * {@link isDryRun}: every path that stages bytes on-chain has to read it identically. */
29
+ export declare function allowUnreadableOnchain(flags: Flags): boolean;
21
30
  export declare function parseFlags(args: string[]): Flags;
31
+ /**
32
+ * The bare (non-flag) arguments, with flag VALUES removed — the mirror of {@link parseFlags}, and
33
+ * deliberately next to it: the two must consume argv by the same rule or a flag's value looks like a
34
+ * positional. (Hand-rolling `args.filter(a => !a.startsWith('-'))` reads `--token 0` as a stray
35
+ * positional `0`, which is exactly the bug a stray-positional check is meant to catch.)
36
+ */
37
+ export declare function positionalArgs(args: string[]): string[];
22
38
  /**
23
39
  * The flag keys in `flags` that are NOT in `allowed` — for a non-fatal "unrecognized flag"
24
40
  * notice at a command's entry. {@link parseFlags} keeps any `--k` it sees, so a typo'd or
@@ -28,4 +44,33 @@ export declare function parseFlags(args: string[]): Flags;
28
44
  * scripted deploy (owner's stateless/scriptable line — see cli-ux-decisions).
29
45
  */
30
46
  export declare function unknownFlags(flags: Flags, allowed: Iterable<string>): string[];
47
+ /** Warn (never throw) on a flag the command doesn't recognize — a typo'd or unsupported flag
48
+ * otherwise no-ops INVISIBLY (the worst failure mode for a write-adjacent value like a mistyped
49
+ * --royalty-bps). Non-fatal, per the owner's scriptability line ([[cli-ux-decisions]]). */
50
+ export declare const FLAG_HINTS: Record<string, (cmd: string) => string | undefined>;
51
+ /**
52
+ * Unknown flags on a command that can SEND: refuse, don't warn.
53
+ *
54
+ * This used to warn and carry on, and `--chain sepolia` proved why that isn't enough — the warning was
55
+ * accurate, it scrolled past, and the deploy ran on the DEFAULT chain. On a dry run that costs a
56
+ * confused minute; on a funded send it is a wrong-chain deploy. "Prose that was ignored once will be
57
+ * ignored again" is the standing rule here, so the tx-sending commands stop instead.
58
+ *
59
+ * Safe to refuse rather than warn because a flag absent from the allowlist is, by construction, one
60
+ * the command never reads — verified per command by comparing every `flags.x` read in its body against
61
+ * its allowlist. So refusal cannot break a working flag; it only makes an already-ignored one loud.
62
+ *
63
+ * `--dry-run` refuses identically. A preview that accepts what the real send rejects is its own trap:
64
+ * you'd validate a command in preview and have it fail at the moment it matters.
65
+ */
66
+ export declare function refuseStrayFlags(flags: Flags, allowed: ReadonlySet<string>, cmd: string): void;
67
+ /** Unknown flags on a READ-ONLY command: warn, don't refuse. Nothing can be mis-sent, and a stray
68
+ * flag on `preview`/`inspect` shouldn't stop a creator mid-iteration. */
69
+ export declare function warnStrayFlags(flags: Flags, allowed: ReadonlySet<string>, cmd: string): void;
70
+ /** The wallet-lane owner-pinning guard: on `--sign` with no `--for`, whichever wallet connects
71
+ * becomes owner + royalty receiver + mint recipient (the launch-readiness "random wallet owns the
72
+ * collection" trap). Fires uniformly on deploy / deploy-series / deploy-code. */
73
+ export declare function warnSignWithoutFor(flags: Flags): void;
74
+ /** Validate an explicit --salt (a 32-byte hex). Undefined when absent. */
75
+ export declare function parseSaltFlag(raw: string | undefined): Hex | undefined;
31
76
  //# sourceMappingURL=flags.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEvD,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAA8B,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAAgC,CAAC;AAE9E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAchD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAG9E"}
1
+ {"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAC,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAG9B,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEvD,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAuC,CAAC;AAEzF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAAgC,CAAC;AAE9E;;oGAEoG;AACpG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE9C;AAED;;0FAE0F;AAC1F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE5D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAchD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWvD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAG9E;AAED;;4FAE4F;AAI5F,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAK1E,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAU9F;AAED;0EAC0E;AAC1E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAS5F;AAED;;kFAEkF;AAClF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAIrD;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,CAyBtE"}
package/dist/flags.js CHANGED
@@ -1,11 +1,24 @@
1
+ import { bold, info, warn } from './output.js';
1
2
  /** Flags where every occurrence counts (values comma-join, in argv order). */
2
- export const REPEATABLE_FLAGS = new Set(['dep', 'schema']);
3
+ export const REPEATABLE_FLAGS = new Set(['dep', 'schema', 'param']);
3
4
  /**
4
5
  * Flags valid on ANY command (handled centrally in main, not by a command handler), so
5
6
  * {@link unknownFlags} never flags them as unrecognized regardless of the per-command allowlist.
6
7
  * `no-update-check` opts out of the startup update nudge (see update-check.ts).
7
8
  */
8
9
  export const GLOBAL_FLAGS = new Set(['no-update-check']);
10
+ /** Whether `--dry-run` was passed. The one place that truthiness is decided — every write command
11
+ * (owner-op or deploy) reads it through here rather than hand-rolling `!!flags['dry-run']`, so a
12
+ * fresh command can't ship with a *slightly* different spelling of the same check (or skip it). */
13
+ export function isDryRun(flags) {
14
+ return !!flags['dry-run'];
15
+ }
16
+ /** Whether `--allow-unreadable-onchain` was passed — the override for the render-gas refusal
17
+ * (`guardOnChainSize` in ownerops.ts). Decided in one place for the same reason as
18
+ * {@link isDryRun}: every path that stages bytes on-chain has to read it identically. */
19
+ export function allowUnreadableOnchain(flags) {
20
+ return flags['allow-unreadable-onchain'] !== undefined;
21
+ }
9
22
  export function parseFlags(args) {
10
23
  const out = {};
11
24
  const set = (k, v) => {
@@ -25,6 +38,25 @@ export function parseFlags(args) {
25
38
  }
26
39
  return out;
27
40
  }
41
+ /**
42
+ * The bare (non-flag) arguments, with flag VALUES removed — the mirror of {@link parseFlags}, and
43
+ * deliberately next to it: the two must consume argv by the same rule or a flag's value looks like a
44
+ * positional. (Hand-rolling `args.filter(a => !a.startsWith('-'))` reads `--token 0` as a stray
45
+ * positional `0`, which is exactly the bug a stray-positional check is meant to catch.)
46
+ */
47
+ export function positionalArgs(args) {
48
+ const out = [];
49
+ for (let i = 0; i < args.length; i++) {
50
+ const a = args[i];
51
+ if (a.startsWith('--')) {
52
+ if (a.indexOf('=') === -1 && args[i + 1] && !args[i + 1].startsWith('--'))
53
+ i++; // this flag consumes the next token
54
+ continue;
55
+ }
56
+ out.push(a);
57
+ }
58
+ return out;
59
+ }
28
60
  /**
29
61
  * The flag keys in `flags` that are NOT in `allowed` — for a non-fatal "unrecognized flag"
30
62
  * notice at a command's entry. {@link parseFlags} keeps any `--k` it sees, so a typo'd or
@@ -37,4 +69,88 @@ export function unknownFlags(flags, allowed) {
37
69
  const ok = new Set(allowed);
38
70
  return Object.keys(flags).filter((k) => !ok.has(k) && !GLOBAL_FLAGS.has(k));
39
71
  }
72
+ /** Warn (never throw) on a flag the command doesn't recognize — a typo'd or unsupported flag
73
+ * otherwise no-ops INVISIBLY (the worst failure mode for a write-adjacent value like a mistyped
74
+ * --royalty-bps). Non-fatal, per the owner's scriptability line ([[cli-ux-decisions]]). */
75
+ // Targeted "did you mean" hints for the flags creators most often invent (seen across agent sessions).
76
+ // A stray flag is otherwise silently ignored, so a wrong-but-plausible one (a price/supply flag that
77
+ // doesn't exist) reads as "it worked." Command-aware so a flag valid elsewhere isn't mis-hinted.
78
+ export const FLAG_HINTS = {
79
+ count: (cmd) => (cmd === 'deploy-code' ? 'did you mean --max <N> (the supply cap)?' : undefined),
80
+ price: () => 'a sale price is NOT set at deploy — configure it after with `abx minter configure <addr> --price <eth>`.',
81
+ supply: () => 'did you mean --max <N> (the supply cap)?',
82
+ amount: () => 'a sale price/amount is set post-deploy via `abx minter configure`.',
83
+ };
84
+ /**
85
+ * Unknown flags on a command that can SEND: refuse, don't warn.
86
+ *
87
+ * This used to warn and carry on, and `--chain sepolia` proved why that isn't enough — the warning was
88
+ * accurate, it scrolled past, and the deploy ran on the DEFAULT chain. On a dry run that costs a
89
+ * confused minute; on a funded send it is a wrong-chain deploy. "Prose that was ignored once will be
90
+ * ignored again" is the standing rule here, so the tx-sending commands stop instead.
91
+ *
92
+ * Safe to refuse rather than warn because a flag absent from the allowlist is, by construction, one
93
+ * the command never reads — verified per command by comparing every `flags.x` read in its body against
94
+ * its allowlist. So refusal cannot break a working flag; it only makes an already-ignored one loud.
95
+ *
96
+ * `--dry-run` refuses identically. A preview that accepts what the real send rejects is its own trap:
97
+ * you'd validate a command in preview and have it fail at the moment it matters.
98
+ */
99
+ export function refuseStrayFlags(flags, allowed, cmd) {
100
+ const stray = unknownFlags(flags, allowed);
101
+ if (!stray.length)
102
+ return;
103
+ const hints = stray.map((f) => FLAG_HINTS[f]?.(cmd)).filter(Boolean);
104
+ throw new Error(`unrecognized flag(s): ${stray.map((f) => '--' + f).join(', ')} — this command would have ignored them silently, so it is refusing instead.\n` +
105
+ hints.map((h, i) => ` ↳ --${stray[i]}: ${h}`).join('\n') +
106
+ (hints.length ? '\n' : '') +
107
+ ` see \`abx help ${cmd}\` for the flags it accepts.`);
108
+ }
109
+ /** Unknown flags on a READ-ONLY command: warn, don't refuse. Nothing can be mis-sent, and a stray
110
+ * flag on `preview`/`inspect` shouldn't stop a creator mid-iteration. */
111
+ export function warnStrayFlags(flags, allowed, cmd) {
112
+ const stray = unknownFlags(flags, allowed);
113
+ if (stray.length) {
114
+ warn(`unrecognized flag(s), ignored: ${stray.map((f) => bold('--' + f)).join(', ')} — see \`abx help ${cmd}\`. (A misspelled or unsupported flag silently does nothing.)`);
115
+ for (const f of stray) {
116
+ const hint = FLAG_HINTS[f]?.(cmd);
117
+ if (hint)
118
+ info(` ↳ --${f}: ${hint}`);
119
+ }
120
+ }
121
+ }
122
+ /** The wallet-lane owner-pinning guard: on `--sign` with no `--for`, whichever wallet connects
123
+ * becomes owner + royalty receiver + mint recipient (the launch-readiness "random wallet owns the
124
+ * collection" trap). Fires uniformly on deploy / deploy-series / deploy-code. */
125
+ export function warnSignWithoutFor(flags) {
126
+ if (flags.sign !== undefined && !flags.for) {
127
+ warn(`--sign without --for: whichever wallet connects becomes ${bold('owner + royalty receiver + mint recipient')}. Pass ${bold('--for <your address>')} to PIN it — the sign page then refuses a mismatched wallet (the intended safety on the wallet lane).`);
128
+ }
129
+ }
130
+ /** Validate an explicit --salt (a 32-byte hex). Undefined when absent. */
131
+ export function parseSaltFlag(raw) {
132
+ if (!raw || raw === 'true')
133
+ return undefined;
134
+ if (!/^0x[0-9a-fA-F]{64}$/.test(raw)) {
135
+ throw new Error(`--salt must be a 32-byte hex (0x + 64 hex chars); got '${raw}'`);
136
+ }
137
+ // Warn here, at the one place every command parses the flag, rather than at the five places a
138
+ // deploy derives an address from it.
139
+ //
140
+ // The factory reads a salt's leading 20 bytes as an access guard: the caller's own address means
141
+ // only that signer may deploy with it; all-zero means anyone may. Omitting --salt gives you the
142
+ // former. Only `abx predict` ever explained this, while the deploy commands took an explicit
143
+ // --salt verbatim and said nothing — so a creator pinning a vanity salt with a zero prefix and
144
+ // announcing the predicted address was handing it to whoever deployed there first, and the
145
+ // front-runner becomes `owner()` (ownership is set by `initialize`, not by the prediction).
146
+ // Reviewed 2026-08; the attack was reproduced. Warn rather than refuse: a zero prefix is the
147
+ // correct choice for a deliberately shared, caller-independent deployment.
148
+ if (/^0{40}$/.test(raw.slice(2, 42))) {
149
+ warn('--salt has an all-zero guard prefix, so ANYONE may deploy to the address it predicts. ' +
150
+ 'Publish that address before you deploy and someone else can take it — and own it. ' +
151
+ 'Drop --salt for a salt pinned to your signer, or keep this only if a shared, ' +
152
+ 'caller-independent address is the point.');
153
+ }
154
+ return raw;
155
+ }
40
156
  //# sourceMappingURL=flags.js.map
package/dist/flags.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAaA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAE9E,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,MAAM,GAAG,GAAU,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE;QACnC,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAClC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;aAC/C,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;;YAC7E,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAY,EAAE,OAAyB;IAClE,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Flags } from './flags.js';
2
+ /**
3
+ * `--json`: make **stdout a machine channel**.
4
+ *
5
+ * The rule this enforces, from an integrator who drove the CLI from a server: *a value a program
6
+ * needs must be obtainable without parsing prose.* They had to regex-scrape ANSI-coloured stdout for
7
+ * every value — and an escape code ended up inside a locator, was written into a stored player URL,
8
+ * and 404'd in production. The cause was found only by inspecting stored bytes.
9
+ *
10
+ * So under `--json`, stdout carries exactly one JSON document and nothing else. Every narration line
11
+ * the command would print for a human goes to **stderr** instead — not suppressed, because a human
12
+ * watching a deploy still wants to see it, and a program redirecting stdout still gets a clean parse.
13
+ * The update-check already wrote to stderr for precisely this reason; this carries that instinct
14
+ * through to the values themselves.
15
+ *
16
+ * It works by swapping `console.log` for the duration rather than threading a `quiet` flag through
17
+ * every command body. That is deliberate: the alternative is touching dozens of call sites, where the
18
+ * one that gets missed is a stray line that corrupts a parse — the exact failure mode being fixed.
19
+ * `console.error`/`console.warn` are untouched (already stderr), and the payload is written through a
20
+ * captured reference to the real `console.log`, so nothing can intercept it back.
21
+ */
22
+ export declare function jsonMode(flags: Flags): boolean;
23
+ /**
24
+ * Run `body` and, under `--json`, print whatever it returns as the sole contents of stdout.
25
+ *
26
+ * `body` receives an `emit` it may call to contribute the payload incrementally — for a command that
27
+ * discovers its value midway (a deploy learning its address) and would otherwise have to restructure
28
+ * to return it at the end. The last `emit` wins; a returned value overrides both.
29
+ *
30
+ * Without `--json` this is a plain pass-through: zero behaviour change on the human path.
31
+ */
32
+ export declare function withJson<T extends Record<string, unknown>>(flags: Flags, body: (emit: (payload: T) => void) => Promise<T | void>): Promise<void>;
33
+ /** BigInt-safe JSON: bigints become decimal strings rather than throwing. Every on-chain number a
34
+ * payload carries (supply, a token id, a block) arrives as a bigint, and `JSON.stringify` refuses
35
+ * them outright — so a payload builder that forgets one would fail at the last line of a deploy. */
36
+ export declare function jsonSafe<T>(value: T): T;
37
+ //# sourceMappingURL=jsonout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonout.d.ts","sourceRoot":"","sources":["../src/jsonout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GACtD,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;qGAEqG;AACrG,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAEvC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * `--json`: make **stdout a machine channel**.
3
+ *
4
+ * The rule this enforces, from an integrator who drove the CLI from a server: *a value a program
5
+ * needs must be obtainable without parsing prose.* They had to regex-scrape ANSI-coloured stdout for
6
+ * every value — and an escape code ended up inside a locator, was written into a stored player URL,
7
+ * and 404'd in production. The cause was found only by inspecting stored bytes.
8
+ *
9
+ * So under `--json`, stdout carries exactly one JSON document and nothing else. Every narration line
10
+ * the command would print for a human goes to **stderr** instead — not suppressed, because a human
11
+ * watching a deploy still wants to see it, and a program redirecting stdout still gets a clean parse.
12
+ * The update-check already wrote to stderr for precisely this reason; this carries that instinct
13
+ * through to the values themselves.
14
+ *
15
+ * It works by swapping `console.log` for the duration rather than threading a `quiet` flag through
16
+ * every command body. That is deliberate: the alternative is touching dozens of call sites, where the
17
+ * one that gets missed is a stray line that corrupts a parse — the exact failure mode being fixed.
18
+ * `console.error`/`console.warn` are untouched (already stderr), and the payload is written through a
19
+ * captured reference to the real `console.log`, so nothing can intercept it back.
20
+ */
21
+ export function jsonMode(flags) {
22
+ return flags.json !== undefined;
23
+ }
24
+ /**
25
+ * Run `body` and, under `--json`, print whatever it returns as the sole contents of stdout.
26
+ *
27
+ * `body` receives an `emit` it may call to contribute the payload incrementally — for a command that
28
+ * discovers its value midway (a deploy learning its address) and would otherwise have to restructure
29
+ * to return it at the end. The last `emit` wins; a returned value overrides both.
30
+ *
31
+ * Without `--json` this is a plain pass-through: zero behaviour change on the human path.
32
+ */
33
+ export async function withJson(flags, body) {
34
+ let payload;
35
+ const emit = (p) => {
36
+ payload = p;
37
+ };
38
+ if (!jsonMode(flags)) {
39
+ await body(emit);
40
+ return;
41
+ }
42
+ const realLog = console.log;
43
+ // Route human narration to stderr. Mirrors console.log's own formatting closely enough for
44
+ // progress text; nothing structured goes through here.
45
+ console.log = (...args) => process.stderr.write(args.map((a) => String(a)).join(' ') + '\n');
46
+ try {
47
+ const returned = await body(emit);
48
+ const out = returned ?? payload;
49
+ // A command that emitted nothing is a bug in that command, not a silent empty object — say so on
50
+ // stderr and leave stdout empty rather than writing `{}` that a caller would trust.
51
+ if (out === undefined) {
52
+ process.stderr.write('abx: --json produced no payload for this command (please report it)\n');
53
+ process.exitCode = 1;
54
+ return;
55
+ }
56
+ realLog(JSON.stringify(out, null, 2));
57
+ }
58
+ finally {
59
+ console.log = realLog;
60
+ }
61
+ }
62
+ /** BigInt-safe JSON: bigints become decimal strings rather than throwing. Every on-chain number a
63
+ * payload carries (supply, a token id, a block) arrives as a bigint, and `JSON.stringify` refuses
64
+ * them outright — so a payload builder that forgets one would fail at the last line of a deploy. */
65
+ export function jsonSafe(value) {
66
+ return JSON.parse(JSON.stringify(value, (_k, v) => (typeof v === 'bigint' ? v.toString() : v)));
67
+ }
68
+ //# sourceMappingURL=jsonout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonout.js","sourceRoot":"","sources":["../src/jsonout.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAY;IACnC,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAY,EACZ,IAAuD;IAEvD,IAAI,OAAsB,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAI,EAAE,EAAE;QACpB,OAAO,GAAG,CAAC,CAAC;IACd,CAAC,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC;IAC5B,2FAA2F;IAC3F,uDAAuD;IACvD,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxG,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,GAAI,QAA0B,IAAI,OAAO,CAAC;QACnD,iGAAiG;QACjG,oFAAoF;QACpF,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;YAC9F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;qGAEqG;AACrG,MAAM,UAAU,QAAQ,CAAI,KAAQ;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAM,CAAC;AACvG,CAAC"}