@artblocks/abx-cli 0.1.0-alpha.15 → 0.1.0-alpha.17
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/CHANGELOG.md +1476 -0
- package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +17 -0
- package/assets/renderer-scaffold/test/MyRenderer.t.sol +51 -2
- package/dist/flags.d.ts +7 -0
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +19 -0
- package/dist/flags.js.map +1 -1
- package/dist/jsonout.d.ts +37 -0
- package/dist/jsonout.d.ts.map +1 -0
- package/dist/jsonout.js +68 -0
- package/dist/jsonout.js.map +1 -0
- package/dist/main.js +791 -42
- package/dist/main.js.map +1 -1
- package/dist/ownerops.d.ts +42 -1
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +238 -53
- package/dist/ownerops.js.map +1 -1
- package/dist/resume.d.ts +96 -0
- package/dist/resume.d.ts.map +1 -0
- package/dist/resume.js +95 -0
- package/dist/resume.js.map +1 -0
- package/dist/scaffold.d.ts +10 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +52 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/served.d.ts +46 -0
- package/dist/served.d.ts.map +1 -0
- package/dist/served.js +65 -0
- package/dist/served.js.map +1 -0
- package/package.json +7 -6
- package/skill/SKILL.md +7 -4
- package/skill/reference/code-projects.md +8 -6
- package/skill/reference/operating.md +2 -0
- package/skill/reference/setup.md +2 -1
- package/skill/reference/troubleshooting.md +13 -0
|
@@ -10,6 +10,13 @@ pragma solidity ^0.8.20;
|
|
|
10
10
|
/// The tokenData merge rule: a token-scope value overrides the contract-scope one. The
|
|
11
11
|
/// common pattern is `tokenParam` first, then `contractParam` as a fallback (see the
|
|
12
12
|
/// `_param` helper in MyRenderer.sol).
|
|
13
|
+
///
|
|
14
|
+
/// TWO READERS, PICK BY TYPE. Scalar types (`Bool`, `Select`, the ranges, `HexColor`,
|
|
15
|
+
/// `Timestamp`) live entirely in the `bytes32` — read them with `tokenParam` /
|
|
16
|
+
/// `contractParam`. The two payload types, **`Bytes` and `String`**, do NOT: their
|
|
17
|
+
/// `bytes32` is a keccak COMMITMENT (`valueIsHash == true`) and the content is fetched with
|
|
18
|
+
/// `tokenParamData` / `contractParamData` below. Reading a `Bytes` param with `tokenParam`
|
|
19
|
+
/// hands you a hash, not the artwork — that is the tell you want the data reader.
|
|
13
20
|
interface IAbxParams {
|
|
14
21
|
/// Returns the token-scope param: its bytes32 `value`, `valueIsHash` (true if it commits to
|
|
15
22
|
/// off-chain bytes — a literal scalar like a seed/HexColor is false), and `isSet` (does it exist).
|
|
@@ -23,4 +30,14 @@ interface IAbxParams {
|
|
|
23
30
|
external
|
|
24
31
|
view
|
|
25
32
|
returns (bytes32 value, bool valueIsHash, bool isSet);
|
|
33
|
+
|
|
34
|
+
/// @notice A `Bytes`/`String` token param's FULL content — the payload types' real reader.
|
|
35
|
+
/// Returns empty bytes for a literal scalar or an unset key, so an empty return is your
|
|
36
|
+
/// "fall back to a default" signal. When non-empty, `keccak256(returned bytes)` equals
|
|
37
|
+
/// the `value` that `tokenParam` reports — verify it if you want the commitment proof.
|
|
38
|
+
/// Up to ~24KB per key: enough to carry an actual artwork payload on-chain.
|
|
39
|
+
function tokenParamData(uint256 tokenId, bytes32 key) external view returns (bytes memory);
|
|
40
|
+
|
|
41
|
+
/// @notice The contract-scope (collection-wide) blob — the fallback when a token has none.
|
|
42
|
+
function contractParamData(bytes32 key) external view returns (bytes memory);
|
|
26
43
|
}
|
|
@@ -13,15 +13,38 @@ contract MockParams is IAbxParams {
|
|
|
13
13
|
mapping(uint256 => mapping(bytes32 => bool)) private ts;
|
|
14
14
|
mapping(bytes32 => bytes32) private cv;
|
|
15
15
|
mapping(bytes32 => bool) private cs;
|
|
16
|
+
// `Bytes`/`String` params: the bytes32 holds keccak(content), the content lives here.
|
|
17
|
+
mapping(uint256 => mapping(bytes32 => bytes)) private td;
|
|
18
|
+
mapping(bytes32 => bytes) private cd;
|
|
16
19
|
|
|
17
20
|
function setToken(uint256 id, bytes32 key, bytes32 val) external { tv[id][key] = val; ts[id][key] = true; }
|
|
18
21
|
function setContract(bytes32 key, bytes32 val) external { cv[key] = val; cs[key] = true; }
|
|
19
22
|
|
|
23
|
+
/// Set a payload-typed (`Bytes`/`String`) param the way the real contract does: the scalar slot
|
|
24
|
+
/// carries the keccak COMMITMENT and `valueIsHash` is true, so a renderer that reads the bytes32
|
|
25
|
+
/// gets a hash — the data reader is the only way to the content.
|
|
26
|
+
function setTokenData(uint256 id, bytes32 key, bytes memory content) external {
|
|
27
|
+
td[id][key] = content;
|
|
28
|
+
tv[id][key] = keccak256(content);
|
|
29
|
+
ts[id][key] = true;
|
|
30
|
+
}
|
|
31
|
+
function setContractData(bytes32 key, bytes memory content) external {
|
|
32
|
+
cd[key] = content;
|
|
33
|
+
cv[key] = keccak256(content);
|
|
34
|
+
cs[key] = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
20
37
|
function tokenParam(uint256 id, bytes32 key) external view returns (bytes32, bool, bool) {
|
|
21
|
-
return (tv[id][key],
|
|
38
|
+
return (tv[id][key], td[id][key].length > 0, ts[id][key]);
|
|
22
39
|
}
|
|
23
40
|
function contractParam(bytes32 key) external view returns (bytes32, bool, bool) {
|
|
24
|
-
return (cv[key],
|
|
41
|
+
return (cv[key], cd[key].length > 0, cs[key]);
|
|
42
|
+
}
|
|
43
|
+
function tokenParamData(uint256 id, bytes32 key) external view returns (bytes memory) {
|
|
44
|
+
return td[id][key];
|
|
45
|
+
}
|
|
46
|
+
function contractParamData(bytes32 key) external view returns (bytes memory) {
|
|
47
|
+
return cd[key];
|
|
25
48
|
}
|
|
26
49
|
}
|
|
27
50
|
|
|
@@ -107,4 +130,30 @@ contract MyRendererTest is Test {
|
|
|
107
130
|
(, bytes memory data) = img.render(address(params), tokenId, IMAGE);
|
|
108
131
|
assertTrue(data.length > 0);
|
|
109
132
|
}
|
|
133
|
+
|
|
134
|
+
/// READING A PAYLOAD PARAM (`Bytes`/`String`) — the pattern for carrying an actual artwork
|
|
135
|
+
/// payload on-chain. The scalar reader hands you a keccak COMMITMENT with `valueIsHash == true`;
|
|
136
|
+
/// the content only comes from `tokenParamData`. If your renderer reads a `Bytes` param through
|
|
137
|
+
/// `tokenParam` it will draw from a hash and produce garbage, silently — hence this test.
|
|
138
|
+
function test_bytesParam_readViaDataReader() public {
|
|
139
|
+
bytes memory grid = hex"00112233445566778899aabbccddeeff";
|
|
140
|
+
params.setTokenData(0, "grid", grid);
|
|
141
|
+
|
|
142
|
+
// The scalar surface: a commitment, explicitly flagged as one — NOT the content.
|
|
143
|
+
(bytes32 value, bool valueIsHash, bool isSet) = IAbxParams(address(params)).tokenParam(0, "grid");
|
|
144
|
+
assertTrue(isSet);
|
|
145
|
+
assertTrue(valueIsHash, "a Bytes param reports valueIsHash: read the data instead");
|
|
146
|
+
assertEq(value, keccak256(grid));
|
|
147
|
+
|
|
148
|
+
// The data surface: the real bytes, verifiable against that commitment.
|
|
149
|
+
bytes memory got = IAbxParams(address(params)).tokenParamData(0, "grid");
|
|
150
|
+
assertEq(got, grid);
|
|
151
|
+
assertEq(keccak256(got), value, "content must match the on-chain commitment");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// An unset payload param returns empty bytes — your "use a default" signal, never a revert.
|
|
155
|
+
function test_bytesParam_unsetIsEmpty() public view {
|
|
156
|
+
assertEq(IAbxParams(address(params)).tokenParamData(0, "grid").length, 0);
|
|
157
|
+
assertEq(IAbxParams(address(params)).contractParamData("grid").length, 0);
|
|
158
|
+
}
|
|
110
159
|
}
|
package/dist/flags.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export declare const REPEATABLE_FLAGS: ReadonlySet<string>;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare const GLOBAL_FLAGS: ReadonlySet<string>;
|
|
21
21
|
export declare function parseFlags(args: string[]): Flags;
|
|
22
|
+
/**
|
|
23
|
+
* The bare (non-flag) arguments, with flag VALUES removed — the mirror of {@link parseFlags}, and
|
|
24
|
+
* deliberately next to it: the two must consume argv by the same rule or a flag's value looks like a
|
|
25
|
+
* positional. (Hand-rolling `args.filter(a => !a.startsWith('-'))` reads `--token 0` as a stray
|
|
26
|
+
* positional `0`, which is exactly the bug a stray-positional check is meant to catch.)
|
|
27
|
+
*/
|
|
28
|
+
export declare function positionalArgs(args: string[]): string[];
|
|
22
29
|
/**
|
|
23
30
|
* The flag keys in `flags` that are NOT in `allowed` — for a non-fatal "unrecognized flag"
|
|
24
31
|
* notice at a command's entry. {@link parseFlags} keeps any `--k` it sees, so a typo'd or
|
package/dist/flags.d.ts.map
CHANGED
|
@@ -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,CAAuC,CAAC;AAEzF;;;;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,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,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"}
|
package/dist/flags.js
CHANGED
|
@@ -25,6 +25,25 @@ export function parseFlags(args) {
|
|
|
25
25
|
}
|
|
26
26
|
return out;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* The bare (non-flag) arguments, with flag VALUES removed — the mirror of {@link parseFlags}, and
|
|
30
|
+
* deliberately next to it: the two must consume argv by the same rule or a flag's value looks like a
|
|
31
|
+
* positional. (Hand-rolling `args.filter(a => !a.startsWith('-'))` reads `--token 0` as a stray
|
|
32
|
+
* positional `0`, which is exactly the bug a stray-positional check is meant to catch.)
|
|
33
|
+
*/
|
|
34
|
+
export function positionalArgs(args) {
|
|
35
|
+
const out = [];
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
const a = args[i];
|
|
38
|
+
if (a.startsWith('--')) {
|
|
39
|
+
if (a.indexOf('=') === -1 && args[i + 1] && !args[i + 1].startsWith('--'))
|
|
40
|
+
i++; // this flag consumes the next token
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
out.push(a);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
28
47
|
/**
|
|
29
48
|
* The flag keys in `flags` that are NOT in `allowed` — for a non-fatal "unrecognized flag"
|
|
30
49
|
* notice at a command's entry. {@link parseFlags} keeps any `--k` it sees, so a typo'd or
|
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,EAAE,OAAO,CAAC,CAAC,CAAC;AAEzF;;;;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"}
|
package/dist/jsonout.js
ADDED
|
@@ -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"}
|