@mysten-incubation/devstack 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +1 -1
  2. package/dashboard-ui/assets/{grpc-a4usE3Nk.js → grpc-CpkDu4SA.js} +1 -1
  3. package/dashboard-ui/assets/{index-CRYJ4pru.js → index-jLPRmjst.js} +39 -33
  4. package/dashboard-ui/index.html +1 -1
  5. package/dist/api/inference-network.d.mts +5 -5
  6. package/dist/api/inference-network.mjs +5 -5
  7. package/dist/api/inference-network.mjs.map +1 -1
  8. package/dist/api/run-stack-internal.mjs +2 -3
  9. package/dist/api/run-stack-internal.mjs.map +1 -1
  10. package/dist/build-integrations/dapp-kit/index.d.mts +12 -0
  11. package/dist/build-integrations/dapp-kit/index.mjs +14 -1
  12. package/dist/build-integrations/dapp-kit/index.mjs.map +1 -1
  13. package/dist/build-integrations/playwright/config.d.mts +2 -1
  14. package/dist/build-integrations/playwright/config.mjs +1 -1
  15. package/dist/build-integrations/playwright/config.mjs.map +1 -1
  16. package/dist/build-integrations/playwright/errors.d.mts +1 -1
  17. package/dist/build-integrations/playwright/errors.mjs.map +1 -1
  18. package/dist/build-integrations/playwright/index.d.mts +2 -2
  19. package/dist/build-integrations/playwright/index.mjs +2 -2
  20. package/dist/build-integrations/playwright/wallet-context.d.mts +2 -1
  21. package/dist/build-integrations/playwright/wallet-context.mjs +141 -41
  22. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  23. package/dist/build-integrations/runtime/dapp-kit-slot.mjs +1 -1
  24. package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
  25. package/dist/build-integrations/vite/index.d.mts +82 -40
  26. package/dist/build-integrations/vite/index.mjs +281 -112
  27. package/dist/build-integrations/vite/index.mjs.map +1 -1
  28. package/dist/build-integrations/vitest/config.mjs +3 -4
  29. package/dist/build-integrations/vitest/config.mjs.map +1 -1
  30. package/dist/build-integrations/vitest/global-setup.mjs +8 -8
  31. package/dist/build-integrations/vitest/global-setup.mjs.map +1 -1
  32. package/dist/cli/doctor-probes.mjs +7 -2
  33. package/dist/cli/doctor-probes.mjs.map +1 -1
  34. package/dist/cli/main.mjs +5 -4
  35. package/dist/cli/main.mjs.map +1 -1
  36. package/dist/cli/wirings/apply.mjs +0 -1
  37. package/dist/cli/wirings/apply.mjs.map +1 -1
  38. package/dist/cli/wirings/codegen.mjs +37 -38
  39. package/dist/cli/wirings/codegen.mjs.map +1 -1
  40. package/dist/cli/wirings/dump-deployment.mjs +141 -0
  41. package/dist/cli/wirings/dump-deployment.mjs.map +1 -0
  42. package/dist/cli/wirings/snapshot.mjs +0 -1
  43. package/dist/cli/wirings/snapshot.mjs.map +1 -1
  44. package/dist/cli/wirings/up.mjs +7 -0
  45. package/dist/cli/wirings/up.mjs.map +1 -1
  46. package/dist/contracts/codegenable.d.mts +22 -25
  47. package/dist/contracts/codegenable.mjs +35 -4
  48. package/dist/contracts/codegenable.mjs.map +1 -1
  49. package/dist/contracts/config-bindings.mjs +43 -18
  50. package/dist/contracts/config-bindings.mjs.map +1 -1
  51. package/dist/index.mjs +1 -1
  52. package/dist/orchestrators/boot.d.mts +0 -10
  53. package/dist/orchestrators/boot.mjs +24 -54
  54. package/dist/orchestrators/boot.mjs.map +1 -1
  55. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  56. package/dist/orchestrators/codegen/config-runtime.mjs +137 -112
  57. package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -1
  58. package/dist/orchestrators/codegen/deployment-network-file.mjs +130 -0
  59. package/dist/orchestrators/codegen/deployment-network-file.mjs.map +1 -0
  60. package/dist/orchestrators/codegen/deployment-strict.mjs +77 -0
  61. package/dist/orchestrators/codegen/deployment-strict.mjs.map +1 -0
  62. package/dist/orchestrators/codegen/deployment.d.mts +63 -0
  63. package/dist/orchestrators/codegen/deployment.mjs +153 -0
  64. package/dist/orchestrators/codegen/deployment.mjs.map +1 -0
  65. package/dist/orchestrators/codegen/errors.mjs +7 -9
  66. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  67. package/dist/orchestrators/codegen/format.mjs +20 -1
  68. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  69. package/dist/orchestrators/codegen/paths.mjs +1 -8
  70. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  71. package/dist/orchestrators/codegen/service.mjs +369 -141
  72. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  73. package/dist/orchestrators/layers.mjs +0 -1
  74. package/dist/orchestrators/layers.mjs.map +1 -1
  75. package/dist/orchestrators/network-options.d.mts +37 -35
  76. package/dist/orchestrators/network-options.mjs +13 -10
  77. package/dist/orchestrators/network-options.mjs.map +1 -1
  78. package/dist/plugins/account/codegen.d.mts +3 -4
  79. package/dist/plugins/account/codegen.mjs +5 -7
  80. package/dist/plugins/account/codegen.mjs.map +1 -1
  81. package/dist/plugins/account/index.mjs +1 -3
  82. package/dist/plugins/account/index.mjs.map +1 -1
  83. package/dist/plugins/coin/codegen.mjs +5 -5
  84. package/dist/plugins/coin/codegen.mjs.map +1 -1
  85. package/dist/plugins/coin/index.mjs.map +1 -1
  86. package/dist/plugins/dashboard/domain.mjs +18 -1
  87. package/dist/plugins/dashboard/domain.mjs.map +1 -1
  88. package/dist/plugins/dashboard/schema/root.mjs +5 -3
  89. package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
  90. package/dist/plugins/dashboard/schema/types.mjs +15 -2
  91. package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
  92. package/dist/plugins/deepbook/codegen.mjs +4 -4
  93. package/dist/plugins/deepbook/codegen.mjs.map +1 -1
  94. package/dist/plugins/deepbook/index.d.mts +7 -3
  95. package/dist/plugins/deepbook/index.mjs +3 -3
  96. package/dist/plugins/deepbook/index.mjs.map +1 -1
  97. package/dist/plugins/internal/codegen-helpers.mjs +0 -1
  98. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
  99. package/dist/plugins/package/codegen.d.mts +1 -12
  100. package/dist/plugins/package/codegen.mjs +43 -25
  101. package/dist/plugins/package/codegen.mjs.map +1 -1
  102. package/dist/plugins/package/dep-resolution.mjs +1 -1
  103. package/dist/plugins/package/dep-resolution.mjs.map +1 -1
  104. package/dist/plugins/package/index.d.mts +14 -11
  105. package/dist/plugins/package/index.mjs +6 -7
  106. package/dist/plugins/package/index.mjs.map +1 -1
  107. package/dist/plugins/seal/codegen.mjs +3 -3
  108. package/dist/plugins/seal/codegen.mjs.map +1 -1
  109. package/dist/plugins/seal/index.mjs.map +1 -1
  110. package/dist/plugins/sui/codegen.mjs +5 -4
  111. package/dist/plugins/sui/codegen.mjs.map +1 -1
  112. package/dist/plugins/sui/index.d.mts +10 -10
  113. package/dist/plugins/sui/index.mjs +1 -2
  114. package/dist/plugins/sui/index.mjs.map +1 -1
  115. package/dist/plugins/sui/move-summary-runner.mjs +29 -2
  116. package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
  117. package/dist/plugins/wallet/codegen.d.mts +8 -12
  118. package/dist/plugins/wallet/codegen.mjs +22 -15
  119. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  120. package/dist/plugins/wallet/index.d.mts +4 -3
  121. package/dist/plugins/wallet/index.mjs +1 -1
  122. package/dist/plugins/wallet/index.mjs.map +1 -1
  123. package/dist/plugins/wallet/service.d.mts +2 -2
  124. package/dist/plugins/wallet/service.mjs +2 -3
  125. package/dist/plugins/wallet/service.mjs.map +1 -1
  126. package/dist/plugins/walrus/codegen.mjs +4 -4
  127. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  128. package/dist/plugins/walrus/index.mjs +1 -1
  129. package/dist/plugins/walrus/index.mjs.map +1 -1
  130. package/dist/substrate/manifest.d.mts +17 -22
  131. package/dist/substrate/manifest.mjs +4 -6
  132. package/dist/substrate/manifest.mjs.map +1 -1
  133. package/dist/substrate/plugin-ctx.d.mts +6 -6
  134. package/dist/substrate/plugin-ctx.mjs.map +1 -1
  135. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  136. package/dist/substrate/runtime/index.mjs +1 -0
  137. package/dist/substrate/runtime/lifecycle/file-watcher.d.mts +1 -0
  138. package/dist/substrate/runtime/lifecycle/file-watcher.mjs +54 -0
  139. package/dist/substrate/runtime/lifecycle/file-watcher.mjs.map +1 -0
  140. package/dist/substrate/runtime/lifecycle/index.mjs +1 -0
  141. package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +76 -6
  142. package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
  143. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  144. package/dist/substrate/runtime/paths.mjs +1 -1
  145. package/dist/substrate/runtime/supervisor/start-supervisor.mjs +2 -6
  146. package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
  147. package/dist/surfaces/cli/command-tree.mjs +6 -6
  148. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  149. package/dist/surfaces/cli/index.mjs +6 -4
  150. package/dist/surfaces/cli/index.mjs.map +1 -1
  151. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  152. package/package.json +1 -1
  153. package/dist/cli/wirings/dump-ids.mjs +0 -86
  154. package/dist/cli/wirings/dump-ids.mjs.map +0 -1
  155. package/dist/orchestrators/codegen/id-config.d.mts +0 -1
  156. package/dist/orchestrators/codegen/id-config.mjs +0 -107
  157. package/dist/orchestrators/codegen/id-config.mjs.map +0 -1
  158. package/dist/orchestrators/codegen/output-location.mjs +0 -32
  159. package/dist/orchestrators/codegen/output-location.mjs.map +0 -1
@@ -0,0 +1,130 @@
1
+ import { CodegenRenderError } from "./errors.mjs";
2
+ //#region src/orchestrators/codegen/deployment-network-file.ts
3
+ /** Canonical directory (relative to the project root) committed per-network
4
+ * deployments live under — the convention the Vite plugin auto-discovers. */
5
+ const DEPLOYMENTS_DIRNAME = "deployments";
6
+ /** The header every emitted `deployments/<net>.ts` carries. Hand-editable —
7
+ * this is an authoring surface — so it is NOT marked auto-generated. */
8
+ const HEADER = [
9
+ "// Committed per-network deployment for a real-network deploy.",
10
+ "//",
11
+ "// Emitted by `devstack dump-deployment --network <net>` from a resolved",
12
+ "// stack, then committed. Hand-editable: the `satisfies AppNetworkDeployment`",
13
+ "// type-checks it against this app declared packages + MVR placeholders, so a",
14
+ "// missing or mistyped id fails `tsc`. No dev `accounts` (those ride the",
15
+ "// runtime envelope, never the committed authoring surface)."
16
+ ].join("\n");
17
+ const INDENT = " ";
18
+ const IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
19
+ /** A single-quoted TS string literal (prettier `singleQuote: true`). Falls
20
+ * back to a double-quoted literal only when the value itself contains a
21
+ * single quote but no double quote (prettier's own preference), else escapes
22
+ * within single quotes.
23
+ *
24
+ * Escaping is derived from `JSON.stringify`, which already produces a valid
25
+ * double-quoted JS string literal for ANY input — escaping backslash, the
26
+ * double quote, and all control characters (newline, CR, tab, etc.) — so a
27
+ * `values`-channel blob with literal newlines (PEM/cert text, multi-line
28
+ * descriptions) can never emit an unterminated literal. The result is then
29
+ * rephrased into prettier's quote preference. `U+2028`/`U+2029` are valid in
30
+ * JS string literals (and `JSON.stringify` leaves them unescaped), but are
31
+ * escaped here defensively so the emitted file is robust under tools that
32
+ * treat them as line terminators. */
33
+ const LINE_SEP = /* @__PURE__ */ new RegExp("\\u2028", "g");
34
+ const PARA_SEP = /* @__PURE__ */ new RegExp("\\u2029", "g");
35
+ const quote = (s) => {
36
+ const json = JSON.stringify(s).replace(LINE_SEP, "\\u2028").replace(PARA_SEP, "\\u2029");
37
+ if (s.includes("'") && !s.includes("\"")) return json;
38
+ return `'${json.slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
39
+ };
40
+ const key = (k) => IDENT_RE.test(k) ? k : quote(k);
41
+ /** Render a JSON value to a prettier-compatible, SINGLE-quoted TS literal at
42
+ * the given indent `depth`. The deployment value space is exactly JSON
43
+ * (strings/numbers/booleans/null/arrays/objects), so no function/bigint/
44
+ * symbol handling is needed. */
45
+ const renderValue = (value, depth) => {
46
+ if (value === null) return "null";
47
+ const t = typeof value;
48
+ if (t === "string") return quote(value);
49
+ if (t === "number" || t === "boolean") return String(value);
50
+ if (Array.isArray(value)) {
51
+ if (value.length === 0) return "[]";
52
+ return `[\n${value.map((v) => INDENT.repeat(depth) + renderValue(v, depth + 1)).join(",\n")},\n${INDENT.repeat(depth - 1)}]`;
53
+ }
54
+ if (t === "object") {
55
+ const obj = value;
56
+ const keys = Object.keys(obj).sort();
57
+ if (keys.length === 0) return "{}";
58
+ return `{\n${keys.map((k) => `${INDENT.repeat(depth)}${key(k)}: ${renderValue(obj[k], depth + 1)}`).join(",\n")},\n${INDENT.repeat(depth - 1)}}`;
59
+ }
60
+ throw new CodegenRenderError({
61
+ emitterName: "dump-deployment",
62
+ outputPath: `${DEPLOYMENTS_DIRNAME}/<net>.ts`,
63
+ detail: `value of type ${t} is not JSON-serialisable`
64
+ });
65
+ };
66
+ /** The ordered, JSON-ish object the file body renders. Built explicitly (NOT a
67
+ * spread of the decoded unit) so the field order is stable and the dev-only
68
+ * `local` marker is dropped. Optional connection diagnostics are omitted when
69
+ * absent. `accounts` is structurally absent from `NetworkDeployment`, so it
70
+ * can never leak in.
71
+ *
72
+ * Exported as the SHARED normalize seam: `dump-deployment --network`'s JSON
73
+ * `data` reflects this same shape (network re-derived from the arg, `local`
74
+ * dropped) so a `--json` consumer never sees a shape that diverges from the
75
+ * committed file actually written. */
76
+ const deploymentBody = (network, unit) => {
77
+ const body = {
78
+ network,
79
+ rpc: unit.rpc
80
+ };
81
+ if (unit.chainId !== void 0) body.chainId = unit.chainId;
82
+ if (unit.faucet !== void 0) body.faucet = unit.faucet;
83
+ if (unit.graphql !== void 0) body.graphql = unit.graphql;
84
+ body.packages = unit.packages;
85
+ body.mvrOverrides = unit.mvrOverrides;
86
+ if (unit.values !== void 0) body.values = unit.values;
87
+ return body;
88
+ };
89
+ /**
90
+ * Render a typed `deployments/<net>.ts` for `network` from its resolved
91
+ * `NetworkDeployment` unit.
92
+ *
93
+ * `importPath` is the module specifier the emitted `import type` points at —
94
+ * the app's generated `deployment.js` relative to the `deployments/` dir
95
+ * (default `../src/generated/deployment.js`). Output is prettier-compatible
96
+ * (tab indent, single quotes, trailing commas) so a prettier-on-write hook is
97
+ * a no-op.
98
+ */
99
+ const renderNetworkDeploymentFile = (network, unit, importPath = "../src/generated/deployment.js") => {
100
+ try {
101
+ const body = renderValue(deploymentBody(network, unit), 1);
102
+ return {
103
+ ok: true,
104
+ text: `${HEADER}
105
+
106
+ import type { AppNetworkDeployment } from ${quote(importPath)};
107
+
108
+ export const deployment = ${body} satisfies AppNetworkDeployment;
109
+ `
110
+ };
111
+ } catch (cause) {
112
+ if (cause instanceof CodegenRenderError) return {
113
+ ok: false,
114
+ error: cause
115
+ };
116
+ return {
117
+ ok: false,
118
+ error: new CodegenRenderError({
119
+ emitterName: "dump-deployment",
120
+ outputPath: `${DEPLOYMENTS_DIRNAME}/${network}.ts`,
121
+ detail: "failed to render network deployment file",
122
+ cause
123
+ })
124
+ };
125
+ }
126
+ };
127
+ //#endregion
128
+ export { DEPLOYMENTS_DIRNAME, deploymentBody, renderNetworkDeploymentFile };
129
+
130
+ //# sourceMappingURL=deployment-network-file.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-network-file.mjs","names":[],"sources":["../../../src/orchestrators/codegen/deployment-network-file.ts"],"sourcesContent":["// The typed per-network deployment file `dump-deployment --network <net>`\n// emits — a committed `deployments/<net>.ts` a prod build / dev serve loads.\n//\n// Unlike the boot-written `deployment.json` (the untyped multi-network\n// ENVELOPE), this is the SINGLE-network, hand-editable, type-checked authoring\n// surface: `export const deployment = {…} satisfies AppNetworkDeployment`. The\n// `satisfies` ties it to the app's strict generated `deployment.ts`, so a\n// missing/typo'd package id or MVR placeholder fails `tsc` against the app's\n// own `AppNetworkDeployment`.\n//\n// Sourced from one `networks.<net>` entry of the resolved envelope (the same\n// data `assembleDeployment` produces). The dev-only `accounts` are NOT part of\n// a `NetworkDeployment` (they live on the envelope), so they never appear here;\n// the `local` marker (a dev-stack flag) is also dropped — a committed\n// deployment is non-local by definition.\n//\n// This file is COMMITTED (not under `generated/`), so unlike the codegen\n// renderer (`format.ts`, double-quoted JSON literals in a prettier-IGNORED\n// tree) the output must be prettier-clean: SINGLE-quoted strings, tab indent,\n// trailing commas, sorted keys. A prettier-on-write hook is then a no-op.\n\nimport type { NetworkDeployment } from './deployment.ts';\nimport { CodegenRenderError } from './errors.ts';\n\n/** Canonical directory (relative to the project root) committed per-network\n * deployments live under — the convention the Vite plugin auto-discovers. */\nexport const DEPLOYMENTS_DIRNAME = 'deployments';\n\n/** The header every emitted `deployments/<net>.ts` carries. Hand-editable —\n * this is an authoring surface — so it is NOT marked auto-generated. */\nconst HEADER = [\n\t'// Committed per-network deployment for a real-network deploy.',\n\t'//',\n\t'// Emitted by `devstack dump-deployment --network <net>` from a resolved',\n\t'// stack, then committed. Hand-editable: the `satisfies AppNetworkDeployment`',\n\t'// type-checks it against this app declared packages + MVR placeholders, so a',\n\t'// missing or mistyped id fails `tsc`. No dev `accounts` (those ride the',\n\t'// runtime envelope, never the committed authoring surface).',\n].join('\\n');\n\nconst INDENT = '\\t';\nconst IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\n/** A single-quoted TS string literal (prettier `singleQuote: true`). Falls\n * back to a double-quoted literal only when the value itself contains a\n * single quote but no double quote (prettier's own preference), else escapes\n * within single quotes.\n *\n * Escaping is derived from `JSON.stringify`, which already produces a valid\n * double-quoted JS string literal for ANY input — escaping backslash, the\n * double quote, and all control characters (newline, CR, tab, etc.) — so a\n * `values`-channel blob with literal newlines (PEM/cert text, multi-line\n * descriptions) can never emit an unterminated literal. The result is then\n * rephrased into prettier's quote preference. `U+2028`/`U+2029` are valid in\n * JS string literals (and `JSON.stringify` leaves them unescaped), but are\n * escaped here defensively so the emitted file is robust under tools that\n * treat them as line terminators. */\n// JS line/paragraph separators: valid in string literals but treated as line\n// terminators by some tooling. Built from escape sequences so this SOURCE file\n// stays pure-ASCII (no raw separator bytes).\nconst LINE_SEP = new RegExp('\\\\u2028', 'g');\nconst PARA_SEP = new RegExp('\\\\u2029', 'g');\nconst quote = (s: string): string => {\n\t// `JSON.stringify` yields `\"…\"` with `\\\\`, `\\\"`, and all control chars\n\t// escaped; the body (sans surrounding quotes) is then a safe double-quoted\n\t// payload we can re-quote. Escape the JS line/paragraph separators too.\n\tconst json = JSON.stringify(s).replace(LINE_SEP, '\\\\u2028').replace(PARA_SEP, '\\\\u2029');\n\t// Prefer single quotes (prettier `singleQuote: true`). The JSON body escapes\n\t// `\"` as `\\\"`; to single-quote we unescape `\\\"` → `\"` and escape any literal\n\t// `'` instead. Keep the double-quoted form when the value has a single quote\n\t// but no double quote (prettier's own preference: fewer escapes).\n\tif (s.includes(\"'\") && !s.includes('\"')) return json;\n\tconst body = json.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/'/g, \"\\\\'\");\n\treturn `'${body}'`;\n};\n\nconst key = (k: string): string => (IDENT_RE.test(k) ? k : quote(k));\n\n/** Render a JSON value to a prettier-compatible, SINGLE-quoted TS literal at\n * the given indent `depth`. The deployment value space is exactly JSON\n * (strings/numbers/booleans/null/arrays/objects), so no function/bigint/\n * symbol handling is needed. */\nconst renderValue = (value: unknown, depth: number): string => {\n\tif (value === null) return 'null';\n\tconst t = typeof value;\n\tif (t === 'string') return quote(value as string);\n\tif (t === 'number' || t === 'boolean') return String(value);\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return '[]';\n\t\tconst inner = value.map((v) => INDENT.repeat(depth) + renderValue(v, depth + 1)).join(',\\n');\n\t\treturn `[\\n${inner},\\n${INDENT.repeat(depth - 1)}]`;\n\t}\n\tif (t === 'object') {\n\t\tconst obj = value as Record<string, unknown>;\n\t\tconst keys = Object.keys(obj).sort();\n\t\tif (keys.length === 0) return '{}';\n\t\tconst lines = keys\n\t\t\t.map((k) => `${INDENT.repeat(depth)}${key(k)}: ${renderValue(obj[k], depth + 1)}`)\n\t\t\t.join(',\\n');\n\t\treturn `{\\n${lines},\\n${INDENT.repeat(depth - 1)}}`;\n\t}\n\t// `undefined` / symbol / function — not JSON. The deployment schema admits\n\t// only JSON, so this is unreachable for a schema-decoded unit; throw rather\n\t// than emit a broken file.\n\tthrow new CodegenRenderError({\n\t\temitterName: 'dump-deployment',\n\t\toutputPath: `${DEPLOYMENTS_DIRNAME}/<net>.ts`,\n\t\tdetail: `value of type ${t} is not JSON-serialisable`,\n\t});\n};\n\n/** The ordered, JSON-ish object the file body renders. Built explicitly (NOT a\n * spread of the decoded unit) so the field order is stable and the dev-only\n * `local` marker is dropped. Optional connection diagnostics are omitted when\n * absent. `accounts` is structurally absent from `NetworkDeployment`, so it\n * can never leak in.\n *\n * Exported as the SHARED normalize seam: `dump-deployment --network`'s JSON\n * `data` reflects this same shape (network re-derived from the arg, `local`\n * dropped) so a `--json` consumer never sees a shape that diverges from the\n * committed file actually written. */\nexport const deploymentBody = (\n\tnetwork: string,\n\tunit: NetworkDeployment,\n): Record<string, unknown> => {\n\tconst body: Record<string, unknown> = { network, rpc: unit.rpc };\n\tif (unit.chainId !== undefined) body.chainId = unit.chainId;\n\tif (unit.faucet !== undefined) body.faucet = unit.faucet;\n\tif (unit.graphql !== undefined) body.graphql = unit.graphql;\n\tbody.packages = unit.packages;\n\tbody.mvrOverrides = unit.mvrOverrides;\n\tif (unit.values !== undefined) body.values = unit.values;\n\treturn body;\n};\n\n/** Result of rendering — discriminated so the caller dispatches on `ok`\n * without `instanceof` (STYLE_GUIDE §2). */\nexport type NetworkFileRenderResult =\n\t| { readonly ok: true; readonly text: string }\n\t| { readonly ok: false; readonly error: CodegenRenderError };\n\n/**\n * Render a typed `deployments/<net>.ts` for `network` from its resolved\n * `NetworkDeployment` unit.\n *\n * `importPath` is the module specifier the emitted `import type` points at —\n * the app's generated `deployment.js` relative to the `deployments/` dir\n * (default `../src/generated/deployment.js`). Output is prettier-compatible\n * (tab indent, single quotes, trailing commas) so a prettier-on-write hook is\n * a no-op.\n */\nexport const renderNetworkDeploymentFile = (\n\tnetwork: string,\n\tunit: NetworkDeployment,\n\timportPath = '../src/generated/deployment.js',\n): NetworkFileRenderResult => {\n\ttry {\n\t\tconst body = renderValue(deploymentBody(network, unit), 1);\n\t\tconst text = `${HEADER}\n\nimport type { AppNetworkDeployment } from ${quote(importPath)};\n\nexport const deployment = ${body} satisfies AppNetworkDeployment;\n`;\n\t\treturn { ok: true, text };\n\t} catch (cause) {\n\t\tif (cause instanceof CodegenRenderError) return { ok: false, error: cause };\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: new CodegenRenderError({\n\t\t\t\temitterName: 'dump-deployment',\n\t\t\t\toutputPath: `${DEPLOYMENTS_DIRNAME}/${network}.ts`,\n\t\t\t\tdetail: 'failed to render network deployment file',\n\t\t\t\tcause,\n\t\t\t}),\n\t\t};\n\t}\n};\n"],"mappings":";;;;AA0BA,MAAa,sBAAsB;;;AAInC,MAAM,SAAS;CACd;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC,CAAC,KAAK,IAAI;AAEX,MAAM,SAAS;AACf,MAAM,WAAW;;;;;;;;;;;;;;;AAmBjB,MAAM,2BAAW,IAAI,OAAO,WAAW,GAAG;AAC1C,MAAM,2BAAW,IAAI,OAAO,WAAW,GAAG;AAC1C,MAAM,SAAS,MAAsB;CAIpC,MAAM,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,UAAU,SAAS,CAAC,CAAC,QAAQ,UAAU,SAAS;CAKvF,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC,EAAE,SAAS,IAAG,GAAG,OAAO;CAEhD,OAAO,IADM,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,QAAQ,QAAQ,IAAG,CAAC,CAAC,QAAQ,MAAM,KACpD,EAAE;AACjB;AAEA,MAAM,OAAO,MAAuB,SAAS,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC;;;;;AAMlE,MAAM,eAAe,OAAgB,UAA0B;CAC9D,IAAI,UAAU,MAAM,OAAO;CAC3B,MAAM,IAAI,OAAO;CACjB,IAAI,MAAM,UAAU,OAAO,MAAM,KAAe;CAChD,IAAI,MAAM,YAAY,MAAM,WAAW,OAAO,OAAO,KAAK;CAC1D,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzB,IAAI,MAAM,WAAW,GAAG,OAAO;EAE/B,OAAO,MADO,MAAM,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,KACrE,EAAE,KAAK,OAAO,OAAO,QAAQ,CAAC,EAAE;CAClD;CACA,IAAI,MAAM,UAAU;EACnB,MAAM,MAAM;EACZ,MAAM,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK;EACnC,IAAI,KAAK,WAAW,GAAG,OAAO;EAI9B,OAAO,MAHO,KACZ,KAAK,MAAM,GAAG,OAAO,OAAO,KAAK,IAAI,IAAI,CAAC,EAAE,IAAI,YAAY,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,CACjF,KAAK,KACU,EAAE,KAAK,OAAO,OAAO,QAAQ,CAAC,EAAE;CAClD;CAIA,MAAM,IAAI,mBAAmB;EAC5B,aAAa;EACb,YAAY,GAAG,oBAAoB;EACnC,QAAQ,iBAAiB,EAAE;CAC5B,CAAC;AACF;;;;;;;;;;;AAYA,MAAa,kBACZ,SACA,SAC6B;CAC7B,MAAM,OAAgC;EAAE;EAAS,KAAK,KAAK;CAAI;CAC/D,IAAI,KAAK,YAAY,KAAA,GAAW,KAAK,UAAU,KAAK;CACpD,IAAI,KAAK,WAAW,KAAA,GAAW,KAAK,SAAS,KAAK;CAClD,IAAI,KAAK,YAAY,KAAA,GAAW,KAAK,UAAU,KAAK;CACpD,KAAK,WAAW,KAAK;CACrB,KAAK,eAAe,KAAK;CACzB,IAAI,KAAK,WAAW,KAAA,GAAW,KAAK,SAAS,KAAK;CAClD,OAAO;AACR;;;;;;;;;;;AAkBA,MAAa,+BACZ,SACA,MACA,aAAa,qCACgB;CAC7B,IAAI;EACH,MAAM,OAAO,YAAY,eAAe,SAAS,IAAI,GAAG,CAAC;EAOzD,OAAO;GAAE,IAAI;GAAM,MAAA,GANH,OAAO;;4CAEmB,MAAM,UAAU,EAAE;;4BAElC,KAAK;;EAEP;CACzB,SAAS,OAAO;EACf,IAAI,iBAAiB,oBAAoB,OAAO;GAAE,IAAI;GAAO,OAAO;EAAM;EAC1E,OAAO;GACN,IAAI;GACJ,OAAO,IAAI,mBAAmB;IAC7B,aAAa;IACb,YAAY,GAAG,oBAAoB,GAAG,QAAQ;IAC9C,QAAQ;IACR;GACD,CAAC;EACF;CACD;AACD"}
@@ -0,0 +1,77 @@
1
+ //#region src/orchestrators/codegen/deployment-strict.ts
2
+ /** Output path (relative to the generated tree) of the emitted strict type. */
3
+ const DEPLOYMENT_STRICT_OUTPUT_PATH = "deployment.ts";
4
+ /** Render the app-specific strict deployment type from data. Pure +
5
+ * deterministic (stable key ordering), types-only output. */
6
+ const renderDeploymentStrict = (input) => {
7
+ const { localNetworkName, packageNames, mvrPlaceholders, mvrTypeTags } = input;
8
+ const providedNetworks = [...new Set(input.providedNetworks)].filter((n) => n !== localNetworkName);
9
+ const packagesBody = packageNames.length > 0 ? packageNames.map((name) => `\treadonly ${JSON.stringify(name)}: { readonly id: string; readonly objects?: Record<string, string> };`).join("\n") : " readonly [packageName: string]: never;";
10
+ const mvrPackagesBody = mvrPlaceholders.length > 0 ? mvrPlaceholders.map((mvr) => `\t\t\t${JSON.stringify(mvr)}: string;`).join("\n") : " // (this app declares no MVR placeholders)";
11
+ const hasMvrTypes = mvrTypeTags.length > 0;
12
+ const mvrTypesBody = hasMvrTypes ? mvrTypeTags.map((tag) => `\t\t\t${JSON.stringify(tag)}: string;`).join("\n") : "";
13
+ const mvrTypesField = hasMvrTypes ? `\t\treadonly types: {\n${mvrTypesBody}\n\t\t} & { readonly [namedType: string]: string };` : `\t\treadonly types?: { readonly [namedType: string]: string };`;
14
+ const valueNamespaces = Object.keys(input.serviceValues).sort();
15
+ const hasServiceValues = valueNamespaces.length > 0;
16
+ const valuesBody = hasServiceValues ? valueNamespaces.map((ns) => {
17
+ const fields = Object.keys(input.serviceValues[ns]).sort().map((k) => `\t\t\t${JSON.stringify(k)}: ${input.serviceValues[ns][k]};`).join("\n");
18
+ return `\t\t${JSON.stringify(ns)}: {\n${fields}\n\t\t};`;
19
+ }).join("\n") : "";
20
+ return `// THIS FILE IS AUTO-GENERATED BY @mysten/devstack.
21
+ // Do not edit by hand — your changes will be overwritten by the next
22
+ // \`devstack codegen\`. Apps consume codegen output; codegen output never
23
+ // imports from devstack.
24
+ //
25
+ // The APP-SPECIFIC strict deployment type. A prod author writes a
26
+ // \`deployments/<net>.ts\` that \`satisfies AppNetworkDeployment\` — the type
27
+ // is exhaustive over this app's declared packages + MVR placeholders, so a
28
+ // missing/typo'd id fails \`tsc\`. The live network set
29
+ // (\`ProvidedNetwork\` / \`NETWORK_NAMES\`) is derived from the
30
+ // \`deployments/*.ts\` filenames. Types-only — zero runtime — except the
31
+ // \`NETWORK_NAMES\` literal tuple (for dapp-kit's typed \`switchNetwork\`).
32
+
33
+ import type { NetworkDeployment } from './config-runtime.js';
34
+
35
+ /** Exhaustive over THIS app's declared package names. */
36
+ export interface AppPackages {
37
+ ${packagesBody}
38
+ }
39
+
40
+ /** The per-network shape a prod author hand-writes in
41
+ * \`deployments/<net>.ts\`: a \`NetworkDeployment\` narrowed so \`packages\` is
42
+ * exhaustive over this app's packages, \`mvrOverrides\` is the @mysten MVR
43
+ * override surface (\`{ packages, types }\`) requiring every declared
44
+ * \`@local/<slug>\` placeholder + named-type tag, and \`values\` requires every
45
+ * service value namespace/key (when the app declares any). NO \`accounts\` —
46
+ * dev accounts ride the runtime envelope, never the per-network authoring
47
+ * surface. */
48
+ export interface AppNetworkDeployment
49
+ extends Omit<NetworkDeployment, 'packages' | 'mvrOverrides' | 'values'> {
50
+ readonly packages: AppPackages;
51
+ readonly mvrOverrides: {
52
+ readonly packages: {
53
+ ${mvrPackagesBody}
54
+ } & { readonly [mvrPlaceholder: string]: string };
55
+ ${mvrTypesField}
56
+ };
57
+ ${hasServiceValues ? `\treadonly values: {\n${valuesBody}\n\t} & {\n\t\treadonly [namespace: string]: { readonly [key: string]: unknown };\n\t};` : `\treadonly values?: NetworkDeployment['values'];`}
58
+ }
59
+
60
+ /** The LIVE network names this app ships — the \`deployments/*.ts\` filenames
61
+ * (local excluded). \`never\` when the app ships no committed deployments. */
62
+ export type ProvidedNetwork = ${providedNetworks.length > 0 ? providedNetworks.map((n) => JSON.stringify(n)).join(" | ") : "never"};
63
+
64
+ /** The committed per-network deployments map a prod build / dev serve loads.
65
+ * Partial — an app need not ship every live network at once. */
66
+ export type ProvidedDeployments = Partial<Record<ProvidedNetwork, AppNetworkDeployment>>;
67
+
68
+ /** The full network-name set, local-first: \`[<local>, ...<provided>]\`.
69
+ * dapp-kit's \`networks\` / \`switchNetwork\` type-check against this tuple
70
+ * (D2). */
71
+ export const NETWORK_NAMES = [${[localNetworkName, ...providedNetworks].map((n) => JSON.stringify(n)).join(", ")}] as const;
72
+ `;
73
+ };
74
+ //#endregion
75
+ export { DEPLOYMENT_STRICT_OUTPUT_PATH, renderDeploymentStrict };
76
+
77
+ //# sourceMappingURL=deployment-strict.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-strict.mjs","names":[],"sources":["../../../src/orchestrators/codegen/deployment-strict.ts"],"sourcesContent":["// The APP-SPECIFIC strict deployment type — emitted as\n// `src/generated/deployment.ts`.\n//\n// Unlike `config-runtime.ts` (a verbatim constant string), THIS file is\n// RENDERED FROM DATA: it narrows the generic `NetworkDeployment` (from\n// `config-runtime.ts`) to exactly the package names + MVR placeholders the\n// app declares, and enumerates the live networks the app ships from the\n// `deployments/` directory filenames.\n//\n// Four exported types/values:\n// - `AppPackages` — exhaustive over THIS app's declared package\n// names.\n// - `AppNetworkDeployment` — the per-network shape a prod author hand-\n// writes in `deployments/<net>.ts`: a\n// `NetworkDeployment` with `packages: AppPackages`\n// and `mvrOverrides` requiring the declared\n// `@local/*` placeholder keys. NO `accounts`\n// (those ride the runtime envelope, dev-only).\n// - `ProvidedNetwork` — a union of the LIVE network names (the\n// `deployments/*.ts` filenames, local excluded);\n// `never` when none.\n// - `ProvidedDeployments` — `Partial<Record<ProvidedNetwork,\n// AppNetworkDeployment>>`.\n// - `NETWORK_NAMES` — a literal `as const` tuple\n// `[<localNetworkName>, ...<deployments files>]`\n// for dapp-kit's typed `switchNetwork` (D2).\n//\n// Types-only + zero runtime: on a clean clone (no `deployments/` dir) this is\n// the local network alone — `ProvidedNetwork = never`, `ProvidedDeployments`\n// empty — so `tsc` stays green.\n\n/** Input the renderer derives the strict types from. All values are\n * CONFIG-known (no chain / no live resolution): the declared package names\n * + MVR placeholders come from the `config.ts` aggregate bucket, the local\n * network name from the sui binding, the live network names from the\n * `deployments/*.ts` filenames. */\nexport interface DeploymentStrictInput {\n\t/** The local (dev-stack) network name — the sui binding's `network`\n\t * field. Always the head of `NETWORK_NAMES`. */\n\treadonly localNetworkName: string;\n\t/** This app's declared package names (the `config.packages.<name>`\n\t * keys), in stable order. */\n\treadonly packageNames: ReadonlyArray<string>;\n\t/** This app's declared MVR placeholders (the `@local/<slug>` keys an app\n\t * feeds dapp-kit's `mvr.overrides.packages`), in stable order. */\n\treadonly mvrPlaceholders: ReadonlyArray<string>;\n\t/** This app's declared MVR `types` keys — fully-qualified\n\t * `@local/<slug>::<module>::<Name>` named struct tags (the @mysten MVR\n\t * `types` override surface), in stable order. Empty when the app declares\n\t * no Move datatypes. Drives `AppNetworkDeployment.mvrOverrides.types`. */\n\treadonly mvrTypeTags: ReadonlyArray<string>;\n\t/** The LIVE network names — `deployments/*.ts` filenames (sans `.ts`),\n\t * with the local network name excluded. Empty on a clean clone. */\n\treadonly providedNetworks: ReadonlyArray<string>;\n\t/** The structured SERVICE-VALUE channel: `values[namespace][key] = <tsType>`\n\t * — every generic (non-sugar) config-binding the app's service plugins\n\t * declare (deepbook ids/pools, walrus/seal endpoints, coin decimals +\n\t * full coin type, package object captures). Drives a REQUIRED `values`\n\t * shape on `AppNetworkDeployment` so a hand-written `deployments/<net>.ts`\n\t * is compile-checked for every service value. Empty for a service-less\n\t * (counter-style) app — then `values` stays optional/loose. */\n\treadonly serviceValues: Readonly<Record<string, Readonly<Record<string, string>>>>;\n}\n\n/** Output path (relative to the generated tree) of the emitted strict type. */\nexport const DEPLOYMENT_STRICT_OUTPUT_PATH = 'deployment.ts';\n\n/** Render the app-specific strict deployment type from data. Pure +\n * deterministic (stable key ordering), types-only output. */\nexport const renderDeploymentStrict = (input: DeploymentStrictInput): string => {\n\tconst { localNetworkName, packageNames, mvrPlaceholders, mvrTypeTags } = input;\n\n\t// Defensive: the local network is the head of `NETWORK_NAMES` and is never a\n\t// committed/provided network, so drop it (and any duplicate) from\n\t// `providedNetworks` even if a caller passes it in. The source discovery\n\t// (`discoverProvidedNetworks`) already filters it, but a hand-supplied set\n\t// (tests, future callers) must not yield a duplicate `localnet` tuple element\n\t// or pollute the `ProvidedNetwork` union.\n\tconst providedNetworks = [...new Set(input.providedNetworks)].filter(\n\t\t(n) => n !== localNetworkName,\n\t);\n\n\t// `AppPackages` — exhaustive over the declared package names. Each entry\n\t// carries `{ id; objects? }`. An app with no packages still declares the\n\t// interface (empty), so `AppNetworkDeployment.packages` stays a concrete\n\t// type.\n\tconst packagesBody =\n\t\tpackageNames.length > 0\n\t\t\t? packageNames\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(name) =>\n\t\t\t\t\t\t\t`\\treadonly ${JSON.stringify(name)}: { readonly id: string; readonly objects?: Record<string, string> };`,\n\t\t\t\t\t)\n\t\t\t\t\t.join('\\n')\n\t\t\t: '\\treadonly [packageName: string]: never;';\n\n\t// `mvrOverrides.packages` requires every declared `@local/<slug>` placeholder\n\t// key (resolved package id). The @mysten MVR override shape exactly:\n\t// `{ packages: Record<mvr, id>; types: Record<namedType, resolvedType> }`.\n\tconst mvrPackagesBody =\n\t\tmvrPlaceholders.length > 0\n\t\t\t? mvrPlaceholders.map((mvr) => `\\t\\t\\t${JSON.stringify(mvr)}: string;`).join('\\n')\n\t\t\t: '\\t\\t\\t// (this app declares no MVR placeholders)';\n\t// `mvrOverrides.types` is OPT-IN. When the app DECLARES named types, the\n\t// field is REQUIRED and exhaustively narrowed over the declared tags (a\n\t// hand-written `deployments/<net>.ts` must provide exactly those, valued by\n\t// the resolved `<packageId>::<module>::<Name>`), plus the permissive trailing\n\t// index. When NONE are declared, the field is OPTIONAL + loose so an app that\n\t// exposes no Move datatypes need not write a `types` block at all.\n\tconst hasMvrTypes = mvrTypeTags.length > 0;\n\tconst mvrTypesBody = hasMvrTypes\n\t\t? mvrTypeTags.map((tag) => `\\t\\t\\t${JSON.stringify(tag)}: string;`).join('\\n')\n\t\t: '';\n\tconst mvrTypesField = hasMvrTypes\n\t\t? `\\t\\treadonly types: {\\n${mvrTypesBody}\\n\\t\\t} & { readonly [namedType: string]: string };`\n\t\t: `\\t\\treadonly types?: { readonly [namedType: string]: string };`;\n\n\t// The structured `values` channel — required per service namespace/key with\n\t// its concrete TS type, so a hand-written deployment is compile-checked for\n\t// every service value (deepbook/coin/seal/walrus/package-objects). A\n\t// service-less app contributes nothing → `values` stays optional/loose.\n\tconst valueNamespaces = Object.keys(input.serviceValues).sort();\n\tconst hasServiceValues = valueNamespaces.length > 0;\n\tconst valuesBody = hasServiceValues\n\t\t? valueNamespaces\n\t\t\t\t.map((ns) => {\n\t\t\t\t\tconst keys = Object.keys(input.serviceValues[ns]!).sort();\n\t\t\t\t\tconst fields = keys\n\t\t\t\t\t\t.map((k) => `\\t\\t\\t${JSON.stringify(k)}: ${input.serviceValues[ns]![k]!};`)\n\t\t\t\t\t\t.join('\\n');\n\t\t\t\t\treturn `\\t\\t${JSON.stringify(ns)}: {\\n${fields}\\n\\t\\t};`;\n\t\t\t\t})\n\t\t\t\t.join('\\n')\n\t\t: '';\n\n\t// The emitted `values` field. With service values it is REQUIRED and\n\t// narrowed per namespace/key (a missing service value fails `tsc`), plus a\n\t// permissive trailing index so an app can carry extra namespaces. With NO\n\t// service values (a counter-style app) it stays OPTIONAL + loose so a\n\t// service-less clean clone stays `tsc`-green.\n\tconst valuesField = hasServiceValues\n\t\t? `\\treadonly values: {\\n${valuesBody}\\n\\t} & {\\n\\t\\treadonly [namespace: string]: { readonly [key: string]: unknown };\\n\\t};`\n\t\t: `\\treadonly values?: NetworkDeployment['values'];`;\n\n\t// `ProvidedNetwork` — the live (committed) network union; `never` when\n\t// the app ships none (a clean clone with no `deployments/` dir).\n\tconst providedUnion =\n\t\tprovidedNetworks.length > 0\n\t\t\t? providedNetworks.map((n) => JSON.stringify(n)).join(' | ')\n\t\t\t: 'never';\n\n\t// `NETWORK_NAMES` — `[<local>, ...<provided>]` as a literal tuple.\n\tconst networkNamesTuple = [localNetworkName, ...providedNetworks]\n\t\t.map((n) => JSON.stringify(n))\n\t\t.join(', ');\n\n\treturn `// THIS FILE IS AUTO-GENERATED BY @mysten/devstack.\n// Do not edit by hand — your changes will be overwritten by the next\n// \\`devstack codegen\\`. Apps consume codegen output; codegen output never\n// imports from devstack.\n//\n// The APP-SPECIFIC strict deployment type. A prod author writes a\n// \\`deployments/<net>.ts\\` that \\`satisfies AppNetworkDeployment\\` — the type\n// is exhaustive over this app's declared packages + MVR placeholders, so a\n// missing/typo'd id fails \\`tsc\\`. The live network set\n// (\\`ProvidedNetwork\\` / \\`NETWORK_NAMES\\`) is derived from the\n// \\`deployments/*.ts\\` filenames. Types-only — zero runtime — except the\n// \\`NETWORK_NAMES\\` literal tuple (for dapp-kit's typed \\`switchNetwork\\`).\n\nimport type { NetworkDeployment } from './config-runtime.js';\n\n/** Exhaustive over THIS app's declared package names. */\nexport interface AppPackages {\n${packagesBody}\n}\n\n/** The per-network shape a prod author hand-writes in\n * \\`deployments/<net>.ts\\`: a \\`NetworkDeployment\\` narrowed so \\`packages\\` is\n * exhaustive over this app's packages, \\`mvrOverrides\\` is the @mysten MVR\n * override surface (\\`{ packages, types }\\`) requiring every declared\n * \\`@local/<slug>\\` placeholder + named-type tag, and \\`values\\` requires every\n * service value namespace/key (when the app declares any). NO \\`accounts\\` —\n * dev accounts ride the runtime envelope, never the per-network authoring\n * surface. */\nexport interface AppNetworkDeployment\n\textends Omit<NetworkDeployment, 'packages' | 'mvrOverrides' | 'values'> {\n\treadonly packages: AppPackages;\n\treadonly mvrOverrides: {\n\t\treadonly packages: {\n${mvrPackagesBody}\n\t\t} & { readonly [mvrPlaceholder: string]: string };\n${mvrTypesField}\n\t};\n${valuesField}\n}\n\n/** The LIVE network names this app ships — the \\`deployments/*.ts\\` filenames\n * (local excluded). \\`never\\` when the app ships no committed deployments. */\nexport type ProvidedNetwork = ${providedUnion};\n\n/** The committed per-network deployments map a prod build / dev serve loads.\n * Partial — an app need not ship every live network at once. */\nexport type ProvidedDeployments = Partial<Record<ProvidedNetwork, AppNetworkDeployment>>;\n\n/** The full network-name set, local-first: \\`[<local>, ...<provided>]\\`.\n * dapp-kit's \\`networks\\` / \\`switchNetwork\\` type-check against this tuple\n * (D2). */\nexport const NETWORK_NAMES = [${networkNamesTuple}] as const;\n`;\n};\n"],"mappings":";;AAiEA,MAAa,gCAAgC;;;AAI7C,MAAa,0BAA0B,UAAyC;CAC/E,MAAM,EAAE,kBAAkB,cAAc,iBAAiB,gBAAgB;CAQzE,MAAM,mBAAmB,CAAC,GAAG,IAAI,IAAI,MAAM,gBAAgB,CAAC,CAAC,CAAC,QAC5D,MAAM,MAAM,gBACd;CAMA,MAAM,eACL,aAAa,SAAS,IACnB,aACC,KACC,SACA,cAAc,KAAK,UAAU,IAAI,EAAE,sEACrC,CAAC,CACA,KAAK,IAAI,IACV;CAKJ,MAAM,kBACL,gBAAgB,SAAS,IACtB,gBAAgB,KAAK,QAAQ,SAAS,KAAK,UAAU,GAAG,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI,IAC/E;CAOJ,MAAM,cAAc,YAAY,SAAS;CACzC,MAAM,eAAe,cAClB,YAAY,KAAK,QAAQ,SAAS,KAAK,UAAU,GAAG,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI,IAC3E;CACH,MAAM,gBAAgB,cACnB,0BAA0B,aAAa,uDACvC;CAMH,MAAM,kBAAkB,OAAO,KAAK,MAAM,aAAa,CAAC,CAAC,KAAK;CAC9D,MAAM,mBAAmB,gBAAgB,SAAS;CAClD,MAAM,aAAa,mBAChB,gBACC,KAAK,OAAO;EAEZ,MAAM,SADO,OAAO,KAAK,MAAM,cAAc,GAAI,CAAC,CAAC,KACjC,CAAC,CACjB,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,EAAE,IAAI,MAAM,cAAc,GAAG,CAAE,GAAI,EAAE,CAAC,CAC1E,KAAK,IAAI;EACX,OAAO,OAAO,KAAK,UAAU,EAAE,EAAE,OAAO,OAAO;CAChD,CAAC,CAAC,CACD,KAAK,IAAI,IACV;CAuBH,OAAO;;;;;;;;;;;;;;;;;EAiBN,aAAa;;;;;;;;;;;;;;;;EAgBb,gBAAgB;;EAEhB,cAAc;;EAnDK,mBACjB,yBAAyB,WAAW,2FACpC,mDAmDU;;;;;gCA9CZ,iBAAiB,SAAS,IACvB,iBAAiB,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,IACzD,QAiDyC;;;;;;;;;gCA9CnB,CAAC,kBAAkB,GAAG,gBAAgB,CAAC,CAC/D,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAC7B,KAAK,IAqDwC,EAAE;;AAElD"}
@@ -0,0 +1,63 @@
1
+ import { Effect, FileSystem, Schema } from "effect";
2
+
3
+ //#region src/orchestrators/codegen/deployment.d.ts
4
+ /** Any JSON-serialisable value. The deployment round-trips through
5
+ * `JSON.stringify` into the injected `__DEVSTACK_DEPLOYMENT__` global, so a
6
+ * plugin live value carried in the generic `values` channel must be JSON. */
7
+ type JsonValue = null | string | number | boolean | ReadonlyArray<JsonValue> | {
8
+ readonly [key: string]: JsonValue;
9
+ };
10
+ /** One network's full resolved deployment — the per-network UNIT of the
11
+ * multi-network envelope. Carries the connection coordinates (`rpc` is the
12
+ * load-bearing field the app reads synchronously at module load, plus
13
+ * optional `chainId`/`faucet`/`graphql`) FLATTENED inline alongside the
14
+ * on-chain ids/values for that network. The whole document is data — no
15
+ * functions, no devstack imports — so it round-trips through JSON and a
16
+ * `JSON.stringify` into a vite `define` global. */
17
+ declare const NetworkDeploymentSchema: Schema.Struct<{
18
+ /** This network's name (the `networks.<name>` key it sits under).
19
+ * Optional on input — the envelope key is authoritative, so the Vite
20
+ * merge and the boot writer set it from the key; a hand-written
21
+ * committed `deployments/<net>.ts` need not restate it. */
22
+ readonly network: Schema.optional<Schema.String>; /** Load-bearing — the RPC endpoint the app reads synchronously. */
23
+ readonly rpc: Schema.String;
24
+ readonly chainId: Schema.optional<Schema.String>;
25
+ readonly faucet: Schema.optional<Schema.NullOr<Schema.String>>;
26
+ readonly graphql: Schema.optional<Schema.NullOr<Schema.String>>;
27
+ /** Marks a LIVE LOCAL network (a `devstack up` stack). The deploy
28
+ * filter (`command === 'build'`) drops these — a production bundle
29
+ * ships only committed, non-local networks. Optional so a hand-written
30
+ * committed `deployments/<net>.ts` omits it (treated as non-local). */
31
+ readonly local: Schema.optional<Schema.Boolean>;
32
+ /** Resolved package ids (+ object captures). Optional, default `{}`: a
33
+ * network may have zero packages (a network-only stack, or a
34
+ * hand-authored deploy file), and the boot writer always emits the key
35
+ * anyway — defaulting keeps the injected blob well-formed so the app's
36
+ * resolvers throw `DevstackConfigMissingError` rather than a raw
37
+ * TypeError on a missing section. */
38
+ readonly packages: Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.Struct<{
39
+ readonly id: Schema.String;
40
+ readonly objects: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
41
+ }>>>;
42
+ /** The @mysten MVR override surface an app feeds straight into dapp-kit's
43
+ * `mvr.overrides`, for this network:
44
+ * - `packages`: `@local/<slug>` → resolved package id.
45
+ * - `types`: `@local/<slug>::<module>::<Name>` → resolved
46
+ * `<packageId>::<module>::<Name>` (each KEY passes
47
+ * `isValidNamedType`, each VALUE a concrete struct tag).
48
+ * Both maps optional-default `{}` (a network may declare no packages, and
49
+ * an older injected unit / hand-written committed deployment may omit
50
+ * `types`). */
51
+ readonly mvrOverrides: Schema.withDecodingDefaultKey<Schema.Struct<{
52
+ readonly packages: Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.String>>;
53
+ readonly types: Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.String>>;
54
+ }>>;
55
+ /** Generic resolver channel — `values[namespace][key]` carries
56
+ * arbitrary live plugin JSON the typed fields above can't. Optional
57
+ * so older deployment files (no `values`) still decode. */
58
+ readonly values: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Codec<JsonValue, JsonValue, never, never>>>>;
59
+ }>;
60
+ type NetworkDeployment = typeof NetworkDeploymentSchema.Type;
61
+ //#endregion
62
+ export { NetworkDeployment };
63
+ //# sourceMappingURL=deployment.d.mts.map
@@ -0,0 +1,153 @@
1
+ import { decodeJsonTextSync, decodeUnknownSync } from "../../substrate/runtime/runtime-decode.mjs";
2
+ import { atomicWriteFile } from "../../substrate/runtime/atomic-write.mjs";
3
+ import { Effect, Schema } from "effect";
4
+ //#region src/orchestrators/codegen/deployment.ts
5
+ /** The all-zero Sui object id used as the placeholder for an unresolved
6
+ * (stack-free) id. A committed `config.ts` resolver treats this value —
7
+ * and a missing id — identically: it THROWS `DevstackConfigMissingError`
8
+ * at access time (see `config-runtime.ts`). Apps never transact with it. */
9
+ const UNRESOLVED_ID = "0x0000000000000000000000000000000000000000000000000000000000000000";
10
+ /** One `packages.<name>` entry — the resolved package id plus any
11
+ * resolved object captures for that network. */
12
+ const DeploymentPackageSchema = Schema.Struct({
13
+ id: Schema.String,
14
+ objects: Schema.optional(Schema.Record(Schema.String, Schema.String))
15
+ });
16
+ /** A JSON-serialisable value carried in the generic `values` channel.
17
+ * The whole deployment round-trips through `JSON.stringify` into the
18
+ * vite `define` global, so the value space is exactly JSON. */
19
+ const DeploymentJsonSchema = Schema.suspend(() => Schema.Union([
20
+ Schema.Null,
21
+ Schema.String,
22
+ Schema.Number,
23
+ Schema.Boolean,
24
+ Schema.Array(DeploymentJsonSchema),
25
+ Schema.Record(Schema.String, DeploymentJsonSchema)
26
+ ]));
27
+ /** The generic resolver channel: a two-level namespaced map of arbitrary
28
+ * JSON values a plugin contributes at boot and the committed `config.ts`
29
+ * reads back via `resolveValue(namespace, key)`. This is the open-ended
30
+ * sibling to the typed `network`/`networks`/`packages`/`mvrOverrides`
31
+ * fields — it carries the plugin live values the fixed
32
+ * channel can't (deepbook pool ids, coin types, walrus/seal endpoints). */
33
+ const DeploymentValuesSchema = Schema.Record(Schema.String, Schema.Record(Schema.String, DeploymentJsonSchema));
34
+ /** One network's full resolved deployment — the per-network UNIT of the
35
+ * multi-network envelope. Carries the connection coordinates (`rpc` is the
36
+ * load-bearing field the app reads synchronously at module load, plus
37
+ * optional `chainId`/`faucet`/`graphql`) FLATTENED inline alongside the
38
+ * on-chain ids/values for that network. The whole document is data — no
39
+ * functions, no devstack imports — so it round-trips through JSON and a
40
+ * `JSON.stringify` into a vite `define` global. */
41
+ const NetworkDeploymentSchema = Schema.Struct({
42
+ /** This network's name (the `networks.<name>` key it sits under).
43
+ * Optional on input — the envelope key is authoritative, so the Vite
44
+ * merge and the boot writer set it from the key; a hand-written
45
+ * committed `deployments/<net>.ts` need not restate it. */
46
+ network: Schema.optional(Schema.String),
47
+ /** Load-bearing — the RPC endpoint the app reads synchronously. */
48
+ rpc: Schema.String,
49
+ chainId: Schema.optional(Schema.String),
50
+ faucet: Schema.optional(Schema.NullOr(Schema.String)),
51
+ graphql: Schema.optional(Schema.NullOr(Schema.String)),
52
+ /** Marks a LIVE LOCAL network (a `devstack up` stack). The deploy
53
+ * filter (`command === 'build'`) drops these — a production bundle
54
+ * ships only committed, non-local networks. Optional so a hand-written
55
+ * committed `deployments/<net>.ts` omits it (treated as non-local). */
56
+ local: Schema.optional(Schema.Boolean),
57
+ /** Resolved package ids (+ object captures). Optional, default `{}`: a
58
+ * network may have zero packages (a network-only stack, or a
59
+ * hand-authored deploy file), and the boot writer always emits the key
60
+ * anyway — defaulting keeps the injected blob well-formed so the app's
61
+ * resolvers throw `DevstackConfigMissingError` rather than a raw
62
+ * TypeError on a missing section. */
63
+ packages: Schema.Record(Schema.String, DeploymentPackageSchema).pipe(Schema.withDecodingDefaultKey(Effect.succeed({}))),
64
+ /** The @mysten MVR override surface an app feeds straight into dapp-kit's
65
+ * `mvr.overrides`, for this network:
66
+ * - `packages`: `@local/<slug>` → resolved package id.
67
+ * - `types`: `@local/<slug>::<module>::<Name>` → resolved
68
+ * `<packageId>::<module>::<Name>` (each KEY passes
69
+ * `isValidNamedType`, each VALUE a concrete struct tag).
70
+ * Both maps optional-default `{}` (a network may declare no packages, and
71
+ * an older injected unit / hand-written committed deployment may omit
72
+ * `types`). */
73
+ mvrOverrides: Schema.Struct({
74
+ packages: Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed({}))),
75
+ types: Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed({})))
76
+ }).pipe(Schema.withDecodingDefaultKey(Effect.succeed({
77
+ packages: {},
78
+ types: {}
79
+ }))),
80
+ /** Generic resolver channel — `values[namespace][key]` carries
81
+ * arbitrary live plugin JSON the typed fields above can't. Optional
82
+ * so older deployment files (no `values`) still decode. */
83
+ values: Schema.optional(DeploymentValuesSchema)
84
+ });
85
+ /** The injected multi-network ENVELOPE — every network this deployment
86
+ * supports, keyed by name, plus the default the app opens on. The single
87
+ * on-disk / injected shape: boot writes one (single-network) envelope, the
88
+ * Vite plugin merges live + committed envelopes, and the generated resolver
89
+ * reads it off `__DEVSTACK_DEPLOYMENT__`. */
90
+ const DevstackDeploymentSchema = Schema.Struct({
91
+ /** The network the app opens on (a `networks.<name>` key). */
92
+ defaultNetwork: Schema.String,
93
+ networks: Schema.Record(Schema.String, NetworkDeploymentSchema),
94
+ /** DEV-only account name → address map. Accounts are a network-AGNOSTIC
95
+ * dev concept (keypair gen needs no network), so they live at the
96
+ * envelope level — NOT per-`NetworkDeployment`. They exist only when
97
+ * running THROUGH devstack (dev serve); a real prod deployment carries
98
+ * none. Optional, default `{}` (a hand-written committed envelope, or a
99
+ * pure prod build, omits it). */
100
+ accounts: Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed({})))
101
+ });
102
+ /** Failure reading or decoding a deployment file. */
103
+ var DeploymentDecodeError = class extends Schema.TaggedErrorClass()("DeploymentDecodeError", {
104
+ source: Schema.String,
105
+ message: Schema.String,
106
+ cause: Schema.optional(Schema.Defect)
107
+ }) {};
108
+ /** Canonical filename of the per-stack deployment under
109
+ * `.devstack/stacks/<name>/`. */
110
+ const DEPLOYMENT_FILENAME = "deployment.json";
111
+ /** Write the deployment as pretty JSON. Idempotent at the byte level for
112
+ * identical input (sorted by the caller's assembly order). */
113
+ const writeDeployment = (path, config) => Effect.gen(function* () {
114
+ const text = `${JSON.stringify(config, null, 2)}\n`;
115
+ yield* atomicWriteFile(path, new TextEncoder().encode(text), { mode: 420 }).pipe(Effect.mapError((cause) => new DeploymentDecodeError({
116
+ source: path,
117
+ message: "failed to write deployment",
118
+ cause
119
+ })));
120
+ });
121
+ /** Project a runtime-decode issue into the typed `DeploymentDecodeError`. */
122
+ const mkDeploymentError = (issue) => new DeploymentDecodeError({
123
+ source: issue.source,
124
+ message: issue.message,
125
+ ...issue.cause === void 0 ? {} : { cause: issue.cause }
126
+ });
127
+ /** Decode + validate a deployment from already-read JSON text. The single
128
+ * schema-decode seam every reader shares (the Vite plugin, the `dump-deployment`
129
+ * verb, the codegen verb) so the parse-and-validate decision lives in ONE
130
+ * place rather than each caller hand-rolling `JSON.parse`. Throws
131
+ * `DeploymentDecodeError` on malformed JSON or a shape that violates
132
+ * `DeploymentSchema`. */
133
+ const decodeDeployment = (text) => decodeJsonTextSync(DevstackDeploymentSchema, text, {
134
+ source: DEPLOYMENT_FILENAME,
135
+ mkError: mkDeploymentError
136
+ });
137
+ /** Decode + validate a single per-network `NetworkDeployment` unit from an
138
+ * already-parsed object (a committed `deployments/<net>.ts` thunk's
139
+ * `deployment`). The Vite plugin's merge layer calls this on each committed
140
+ * thunk so a malformed committed deployment surfaces loudly at config-load
141
+ * (rather than silently injecting a broken network). Throws
142
+ * `DeploymentDecodeError` on a shape that violates `NetworkDeploymentSchema`.
143
+ * The caller overwrites `network`/`local` from the envelope key afterwards,
144
+ * so the unit's own `network` field is optional here. */
145
+ const decodeNetworkDeployment = (value, source) => decodeUnknownSync(NetworkDeploymentSchema, value, {
146
+ source,
147
+ mkError: mkDeploymentError,
148
+ message: "committed deployment is not a valid NetworkDeployment"
149
+ });
150
+ //#endregion
151
+ export { DEPLOYMENT_FILENAME, UNRESOLVED_ID, decodeDeployment, decodeNetworkDeployment, writeDeployment };
152
+
153
+ //# sourceMappingURL=deployment.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment.mjs","names":[],"sources":["../../../src/orchestrators/codegen/deployment.ts"],"sourcesContent":["// The deployment interchange file — the single source of on-chain ids.\n//\n// Stop treating on-chain ids as codegen OUTPUT. Treat them as loaded\n// CONFIG DATA. Codegen is a deterministic, stack-free function\n// `(Move source, deployment?) → generated`. Booting a stack's only new\n// job is to PRODUCE this file; the codegen verb READS it (or runs with\n// none); the vite plugin INJECTS it into the app build/dev server.\n//\n// Four authors/consumers, one shared schema:\n// - WRITER: `orchestrators/boot.ts` post-acquire assembles this from\n// acquired plugin state and writes it to the gitignored\n// `.devstack/stacks/<name>/deployment.json`.\n// - READER: the stack-free `devstack codegen` verb reads it via the\n// optional `--config <file>` flag (absent ⇒ ids unresolved).\n// - CONSUMER: the emitted `config-runtime.ts` resolver reads the same\n// shape off the injected `__DEVSTACK_DEPLOYMENT__` global.\n// - INJECTOR: the vite plugin reads the live file (dev) or committed\n// per-network deployment files (prod, via the `deployments`\n// option / `DEVSTACK_DEPLOYMENT_FILE`), MERGES them, and\n// `define`s the global.\n//\n// The shape is a MULTI-NETWORK ENVELOPE: `{ defaultNetwork, networks }`.\n// Each `networks.<name>` entry is a `NetworkDeployment` — the id-half of\n// today's `config.ts` for that one network: rpc (+ chainId/faucet/graphql),\n// per-package ids (+ captured object ids), the MVR placeholder → id override\n// map an app feeds dapp-kit, and a generic `values` channel. Dev `accounts`\n// (name → address) live at the ENVELOPE level — they are network-agnostic\n// dev identities, not part of any per-network unit. A plain single-network dev stack produces an envelope\n// with exactly one entry (the live local network, `local: true`); a real\n// multi-network deployment keys several. The envelope is the uniform unit\n// the Vite plugin merges live (dev) + committed (prod) sources into.\n\nimport { Effect, FileSystem, Schema } from 'effect';\n\nimport { atomicWriteFile } from '../../substrate/runtime/atomic-write.ts';\nimport {\n\tdecodeJsonTextSync,\n\tdecodeUnknownSync,\n\ttype RuntimeDecodeIssue,\n} from '../../substrate/runtime/runtime-decode.ts';\n\n// -----------------------------------------------------------------------------\n// Sentinel — the all-zero id that marks an UNRESOLVED on-chain id.\n// -----------------------------------------------------------------------------\n\n/** The all-zero Sui object id used as the placeholder for an unresolved\n * (stack-free) id. A committed `config.ts` resolver treats this value —\n * and a missing id — identically: it THROWS `DevstackConfigMissingError`\n * at access time (see `config-runtime.ts`). Apps never transact with it. */\nexport const UNRESOLVED_ID = '0x0000000000000000000000000000000000000000000000000000000000000000';\n\n/** True when `id` is absent or the all-zero sentinel — i.e. not a real\n * resolved on-chain id. */\nexport const isUnresolvedId = (id: string | undefined | null): boolean =>\n\tid === undefined || id === null || id === UNRESOLVED_ID;\n\n// -----------------------------------------------------------------------------\n// JSON value space — the generic `values` channel carries exactly JSON.\n// -----------------------------------------------------------------------------\n\n/** Any JSON-serialisable value. The deployment round-trips through\n * `JSON.stringify` into the injected `__DEVSTACK_DEPLOYMENT__` global, so a\n * plugin live value carried in the generic `values` channel must be JSON. */\nexport type JsonValue =\n\t| null\n\t| string\n\t| number\n\t| boolean\n\t| ReadonlyArray<JsonValue>\n\t| { readonly [key: string]: JsonValue };\n\n// -----------------------------------------------------------------------------\n// Schema\n// -----------------------------------------------------------------------------\n\n/** One `packages.<name>` entry — the resolved package id plus any\n * resolved object captures for that network. */\nexport const DeploymentPackageSchema = Schema.Struct({\n\tid: Schema.String,\n\tobjects: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n});\n\n/** A JSON-serialisable value carried in the generic `values` channel.\n * The whole deployment round-trips through `JSON.stringify` into the\n * vite `define` global, so the value space is exactly JSON. */\n// Typed as `Schema.Codec<JsonValue>` (NOT `Schema.Schema<JsonValue>`): the\n// type-only `Schema<T>` widens `DecodingServices` to `unknown`, which would\n// poison every decoder of `DeploymentSchema`; `Codec<T>` defaults the decode/\n// encode services to `never`, matching the real (service-free) recursion.\nexport const DeploymentJsonSchema: Schema.Codec<JsonValue> = Schema.suspend(() =>\n\tSchema.Union([\n\t\tSchema.Null,\n\t\tSchema.String,\n\t\tSchema.Number,\n\t\tSchema.Boolean,\n\t\tSchema.Array(DeploymentJsonSchema),\n\t\tSchema.Record(Schema.String, DeploymentJsonSchema),\n\t]),\n) as Schema.Codec<JsonValue>;\n\n/** The generic resolver channel: a two-level namespaced map of arbitrary\n * JSON values a plugin contributes at boot and the committed `config.ts`\n * reads back via `resolveValue(namespace, key)`. This is the open-ended\n * sibling to the typed `network`/`networks`/`packages`/`mvrOverrides`\n * fields — it carries the plugin live values the fixed\n * channel can't (deepbook pool ids, coin types, walrus/seal endpoints). */\nexport const DeploymentValuesSchema = Schema.Record(\n\tSchema.String,\n\tSchema.Record(Schema.String, DeploymentJsonSchema),\n);\n\n/** One network's full resolved deployment — the per-network UNIT of the\n * multi-network envelope. Carries the connection coordinates (`rpc` is the\n * load-bearing field the app reads synchronously at module load, plus\n * optional `chainId`/`faucet`/`graphql`) FLATTENED inline alongside the\n * on-chain ids/values for that network. The whole document is data — no\n * functions, no devstack imports — so it round-trips through JSON and a\n * `JSON.stringify` into a vite `define` global. */\nexport const NetworkDeploymentSchema = Schema.Struct({\n\t/** This network's name (the `networks.<name>` key it sits under).\n\t * Optional on input — the envelope key is authoritative, so the Vite\n\t * merge and the boot writer set it from the key; a hand-written\n\t * committed `deployments/<net>.ts` need not restate it. */\n\tnetwork: Schema.optional(Schema.String),\n\t/** Load-bearing — the RPC endpoint the app reads synchronously. */\n\trpc: Schema.String,\n\tchainId: Schema.optional(Schema.String),\n\tfaucet: Schema.optional(Schema.NullOr(Schema.String)),\n\tgraphql: Schema.optional(Schema.NullOr(Schema.String)),\n\t/** Marks a LIVE LOCAL network (a `devstack up` stack). The deploy\n\t * filter (`command === 'build'`) drops these — a production bundle\n\t * ships only committed, non-local networks. Optional so a hand-written\n\t * committed `deployments/<net>.ts` omits it (treated as non-local). */\n\tlocal: Schema.optional(Schema.Boolean),\n\t/** Resolved package ids (+ object captures). Optional, default `{}`: a\n\t * network may have zero packages (a network-only stack, or a\n\t * hand-authored deploy file), and the boot writer always emits the key\n\t * anyway — defaulting keeps the injected blob well-formed so the app's\n\t * resolvers throw `DevstackConfigMissingError` rather than a raw\n\t * TypeError on a missing section. */\n\tpackages: Schema.Record(Schema.String, DeploymentPackageSchema).pipe(\n\t\tSchema.withDecodingDefaultKey(Effect.succeed({})),\n\t),\n\t/** The @mysten MVR override surface an app feeds straight into dapp-kit's\n\t * `mvr.overrides`, for this network:\n\t * - `packages`: `@local/<slug>` → resolved package id.\n\t * - `types`: `@local/<slug>::<module>::<Name>` → resolved\n\t * `<packageId>::<module>::<Name>` (each KEY passes\n\t * `isValidNamedType`, each VALUE a concrete struct tag).\n\t * Both maps optional-default `{}` (a network may declare no packages, and\n\t * an older injected unit / hand-written committed deployment may omit\n\t * `types`). */\n\tmvrOverrides: Schema.Struct({\n\t\tpackages: Schema.Record(Schema.String, Schema.String).pipe(\n\t\t\tSchema.withDecodingDefaultKey(Effect.succeed({})),\n\t\t),\n\t\ttypes: Schema.Record(Schema.String, Schema.String).pipe(\n\t\t\tSchema.withDecodingDefaultKey(Effect.succeed({})),\n\t\t),\n\t}).pipe(Schema.withDecodingDefaultKey(Effect.succeed({ packages: {}, types: {} }))),\n\t/** Generic resolver channel — `values[namespace][key]` carries\n\t * arbitrary live plugin JSON the typed fields above can't. Optional\n\t * so older deployment files (no `values`) still decode. */\n\tvalues: Schema.optional(DeploymentValuesSchema),\n});\n\n/** The injected multi-network ENVELOPE — every network this deployment\n * supports, keyed by name, plus the default the app opens on. The single\n * on-disk / injected shape: boot writes one (single-network) envelope, the\n * Vite plugin merges live + committed envelopes, and the generated resolver\n * reads it off `__DEVSTACK_DEPLOYMENT__`. */\nexport const DevstackDeploymentSchema = Schema.Struct({\n\t/** The network the app opens on (a `networks.<name>` key). */\n\tdefaultNetwork: Schema.String,\n\tnetworks: Schema.Record(Schema.String, NetworkDeploymentSchema),\n\t/** DEV-only account name → address map. Accounts are a network-AGNOSTIC\n\t * dev concept (keypair gen needs no network), so they live at the\n\t * envelope level — NOT per-`NetworkDeployment`. They exist only when\n\t * running THROUGH devstack (dev serve); a real prod deployment carries\n\t * none. Optional, default `{}` (a hand-written committed envelope, or a\n\t * pure prod build, omits it). */\n\taccounts: Schema.Record(Schema.String, Schema.String).pipe(\n\t\tSchema.withDecodingDefaultKey(Effect.succeed({})),\n\t),\n});\n\nexport type DevstackDeployment = typeof DevstackDeploymentSchema.Type;\nexport type NetworkDeployment = typeof NetworkDeploymentSchema.Type;\nexport type DeploymentPackage = typeof DeploymentPackageSchema.Type;\nexport type DeploymentValues = typeof DeploymentValuesSchema.Type;\n\n// -----------------------------------------------------------------------------\n// Error\n// -----------------------------------------------------------------------------\n\n/** Failure reading or decoding a deployment file. */\nexport class DeploymentDecodeError extends Schema.TaggedErrorClass<DeploymentDecodeError>()(\n\t'DeploymentDecodeError',\n\t{\n\t\tsource: Schema.String,\n\t\tmessage: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n// -----------------------------------------------------------------------------\n// Read / write helpers\n// -----------------------------------------------------------------------------\n\n/** Canonical filename of the per-stack deployment under\n * `.devstack/stacks/<name>/`. */\nexport const DEPLOYMENT_FILENAME = 'deployment.json';\n\n/** Write the deployment as pretty JSON. Idempotent at the byte level for\n * identical input (sorted by the caller's assembly order). */\nexport const writeDeployment = (\n\tpath: string,\n\tconfig: DevstackDeployment,\n): Effect.Effect<void, DeploymentDecodeError, FileSystem.FileSystem> =>\n\tEffect.gen(function* () {\n\t\tconst text = `${JSON.stringify(config, null, 2)}\\n`;\n\t\tconst bytes = new TextEncoder().encode(text);\n\t\t// Atomic temp+rename — the Vite plugin reads this file with a plain\n\t\t// `readFileSync` + `JSON.parse`, so a torn / partial write would surface\n\t\t// as a parse error. `atomicWriteFile` ensures the parent dir (the\n\t\t// deployment write may run before the manifest write) and fsyncs before\n\t\t// the rename, so readers only ever see a complete file.\n\t\tyield* atomicWriteFile(path, bytes, { mode: 0o644 }).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause) =>\n\t\t\t\t\tnew DeploymentDecodeError({ source: path, message: 'failed to write deployment', cause }),\n\t\t\t),\n\t\t);\n\t});\n\n/** Project a runtime-decode issue into the typed `DeploymentDecodeError`. */\nconst mkDeploymentError = (issue: RuntimeDecodeIssue): DeploymentDecodeError =>\n\tnew DeploymentDecodeError({\n\t\tsource: issue.source,\n\t\tmessage: issue.message,\n\t\t...(issue.cause === undefined ? {} : { cause: issue.cause }),\n\t});\n\n/** Decode + validate a deployment from already-read JSON text. The single\n * schema-decode seam every reader shares (the Vite plugin, the `dump-deployment`\n * verb, the codegen verb) so the parse-and-validate decision lives in ONE\n * place rather than each caller hand-rolling `JSON.parse`. Throws\n * `DeploymentDecodeError` on malformed JSON or a shape that violates\n * `DeploymentSchema`. */\nexport const decodeDeployment = (text: string): DevstackDeployment =>\n\tdecodeJsonTextSync(DevstackDeploymentSchema, text, {\n\t\tsource: DEPLOYMENT_FILENAME,\n\t\tmkError: mkDeploymentError,\n\t});\n\n/** Decode + validate a single per-network `NetworkDeployment` unit from an\n * already-parsed object (a committed `deployments/<net>.ts` thunk's\n * `deployment`). The Vite plugin's merge layer calls this on each committed\n * thunk so a malformed committed deployment surfaces loudly at config-load\n * (rather than silently injecting a broken network). Throws\n * `DeploymentDecodeError` on a shape that violates `NetworkDeploymentSchema`.\n * The caller overwrites `network`/`local` from the envelope key afterwards,\n * so the unit's own `network` field is optional here. */\nexport const decodeNetworkDeployment = (value: unknown, source: string): NetworkDeployment =>\n\tdecodeUnknownSync(NetworkDeploymentSchema, value, {\n\t\tsource,\n\t\tmkError: mkDeploymentError,\n\t\tmessage: 'committed deployment is not a valid NetworkDeployment',\n\t});\n"],"mappings":";;;;;;;;AAiDA,MAAa,gBAAgB;;;AA4B7B,MAAa,0BAA0B,OAAO,OAAO;CACpD,IAAI,OAAO;CACX,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC;AACrE,CAAC;;;;AASD,MAAa,uBAAgD,OAAO,cACnE,OAAO,MAAM;CACZ,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO,MAAM,oBAAoB;CACjC,OAAO,OAAO,OAAO,QAAQ,oBAAoB;AAClD,CAAC,CACF;;;;;;;AAQA,MAAa,yBAAyB,OAAO,OAC5C,OAAO,QACP,OAAO,OAAO,OAAO,QAAQ,oBAAoB,CAClD;;;;;;;;AASA,MAAa,0BAA0B,OAAO,OAAO;;;;;CAKpD,SAAS,OAAO,SAAS,OAAO,MAAM;;CAEtC,KAAK,OAAO;CACZ,SAAS,OAAO,SAAS,OAAO,MAAM;CACtC,QAAQ,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,CAAC;CACpD,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,CAAC;;;;;CAKrD,OAAO,OAAO,SAAS,OAAO,OAAO;;;;;;;CAOrC,UAAU,OAAO,OAAO,OAAO,QAAQ,uBAAuB,CAAC,CAAC,KAC/D,OAAO,uBAAuB,OAAO,QAAQ,CAAC,CAAC,CAAC,CACjD;;;;;;;;;;CAUA,cAAc,OAAO,OAAO;EAC3B,UAAU,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,KACrD,OAAO,uBAAuB,OAAO,QAAQ,CAAC,CAAC,CAAC,CACjD;EACA,OAAO,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,KAClD,OAAO,uBAAuB,OAAO,QAAQ,CAAC,CAAC,CAAC,CACjD;CACD,CAAC,CAAC,CAAC,KAAK,OAAO,uBAAuB,OAAO,QAAQ;EAAE,UAAU,CAAC;EAAG,OAAO,CAAC;CAAE,CAAC,CAAC,CAAC;;;;CAIlF,QAAQ,OAAO,SAAS,sBAAsB;AAC/C,CAAC;;;;;;AAOD,MAAa,2BAA2B,OAAO,OAAO;;CAErD,gBAAgB,OAAO;CACvB,UAAU,OAAO,OAAO,OAAO,QAAQ,uBAAuB;;;;;;;CAO9D,UAAU,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,KACrD,OAAO,uBAAuB,OAAO,QAAQ,CAAC,CAAC,CAAC,CACjD;AACD,CAAC;;AAYD,IAAa,wBAAb,cAA2C,OAAO,iBAAwC,CAAC,CAC1F,yBACA;CACC,QAAQ,OAAO;CACf,SAAS,OAAO;CAChB,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;AAQH,MAAa,sBAAsB;;;AAInC,MAAa,mBACZ,MACA,WAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE;CAOhD,OAAO,gBAAgB,MANT,IAAI,YAAY,CAAC,CAAC,OAAO,IAMN,GAAG,EAAE,MAAM,IAAM,CAAC,CAAC,CAAC,KACpD,OAAO,UACL,UACA,IAAI,sBAAsB;EAAE,QAAQ;EAAM,SAAS;EAA8B;CAAM,CAAC,CAC1F,CACD;AACD,CAAC;;AAGF,MAAM,qBAAqB,UAC1B,IAAI,sBAAsB;CACzB,QAAQ,MAAM;CACd,SAAS,MAAM;CACf,GAAI,MAAM,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,MAAM,MAAM;AAC3D,CAAC;;;;;;;AAQF,MAAa,oBAAoB,SAChC,mBAAmB,0BAA0B,MAAM;CAClD,QAAQ;CACR,SAAS;AACV,CAAC;;;;;;;;;AAUF,MAAa,2BAA2B,OAAgB,WACvD,kBAAkB,yBAAyB,OAAO;CACjD;CACA,SAAS;CACT,SAAS;AACV,CAAC"}
@@ -21,17 +21,15 @@ var CodegenEmitterCollision = class extends Schema.TaggedErrorClass()("CodegenEm
21
21
  outputPaths: Schema.Array(Schema.String)
22
22
  }) {};
23
23
  /** Two `Codegenable` contributions target the SAME aggregate
24
- * `bucket` but disagree on its routing/sensitivity metadata
25
- * (`outputLocation` or `sensitive`). The `AggregateContribution`
26
- * contract requires all contributors to a bucket to agree; the
27
- * orchestrator routes the synthesized aggregate from the FIRST
28
- * contributor it sees, so a silent disagreement could misroute a
29
- * sensitive aggregate into the committed `generated` tree. Detected
30
- * while folding contributions so the cycle fails fast rather than
31
- * emitting a secret with non-sensitive handling. */
24
+ * `bucket` but disagree on its `sensitive` metadata. The
25
+ * `AggregateContribution` contract requires all contributors to a
26
+ * bucket to agree; the orchestrator takes the FIRST contributor's
27
+ * sensitivity, so a silent disagreement could emit a secret with
28
+ * non-sensitive handling. Detected while folding contributions so the
29
+ * cycle fails fast. */
32
30
  var CodegenAggregateConflict = class extends Schema.TaggedErrorClass()("CodegenAggregateConflict", {
33
31
  bucket: Schema.String,
34
- field: Schema.Literals(["outputLocation", "sensitive"]),
32
+ field: Schema.Literals(["sensitive"]),
35
33
  /** The value the first contributor established for the bucket. */
36
34
  established: Schema.String,
37
35
  /** The conflicting value a later contributor declared. */
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/orchestrators/codegen/errors.ts"],"sourcesContent":["// Typed errors for the Codegen orchestrator.\n//\n// A phase-tagged failure-mode taxonomy: \"emitter-collision at acquire\",\n// \"binary shell-out failure\", and \"pure render failure\" each get a\n// separate tag so callers can `catchTag` on each.\n//\n// Phase tags inside each error name the lifecycle step that failed\n// (resolve → emit → render → write → bindings → finalize) so error\n// attribution stays accurate.\n\nimport { Schema } from 'effect';\n\n/** Path-layer rejection from the codegen orchestrator.\n * - `kind: 'duplicate'` — two `Codegenable` contributions claim the\n * same `outputPath`. Hard failure detected BEFORE write so the\n * user-visible output dir never sees an ambiguous overwrite.\n * - `kind: 'non-relative'` — a plugin-authored `outputPath` escapes\n * the codegen root (contains `..` or is absolute). Defense-in-depth\n * for the file-layout invariants. */\nexport class CodegenPathConflict extends Schema.TaggedErrorClass<CodegenPathConflict>()(\n\t'CodegenPathConflict',\n\t{\n\t\tkind: Schema.Literals(['duplicate', 'non-relative']),\n\t\toutputPath: Schema.String,\n\t\temitters: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** Two `Codegenable` contributions share the SAME `emitterName`\n * literal but resolve to different `outputPath`s — programming\n * bug in plugin code (emitter name should be unique). Distinct\n * from `CodegenPathConflict` so attribution stays clean. */\nexport class CodegenEmitterCollision extends Schema.TaggedErrorClass<CodegenEmitterCollision>()(\n\t'CodegenEmitterCollision',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPaths: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** Two `Codegenable` contributions target the SAME aggregate\n * `bucket` but disagree on its routing/sensitivity metadata\n * (`outputLocation` or `sensitive`). The `AggregateContribution`\n * contract requires all contributors to a bucket to agree; the\n * orchestrator routes the synthesized aggregate from the FIRST\n * contributor it sees, so a silent disagreement could misroute a\n * sensitive aggregate into the committed `generated` tree. Detected\n * while folding contributions so the cycle fails fast rather than\n * emitting a secret with non-sensitive handling. */\nexport class CodegenAggregateConflict extends Schema.TaggedErrorClass<CodegenAggregateConflict>()(\n\t'CodegenAggregateConflict',\n\t{\n\t\tbucket: Schema.String,\n\t\tfield: Schema.Literals(['outputLocation', 'sensitive']),\n\t\t/** The value the first contributor established for the bucket. */\n\t\testablished: Schema.String,\n\t\t/** The conflicting value a later contributor declared. */\n\t\tconflicting: Schema.String,\n\t\t/** Emitter names: the contributor that established the value and\n\t\t * the one that disagreed. */\n\t\temitters: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** A `Codegenable.emit()` wrote a value that the renderer cannot\n * serialise (a function, a symbol, a circular reference, etc.). */\nexport class CodegenRenderError extends Schema.TaggedErrorClass<CodegenRenderError>()(\n\t'CodegenRenderError',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPath: Schema.String,\n\t\tdetail: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** `Codegenable.emit()` raised. Wraps the inner Effect failure\n * rather than propagating it raw so the orchestrator's error\n * channel stays closed. */\nexport class CodegenEmitFailed extends Schema.TaggedErrorClass<CodegenEmitFailed>()(\n\t'CodegenEmitFailed',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPath: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** Disk write (atomic-write or permission-tighten) failed. */\nexport class CodegenWriteFailed extends Schema.TaggedErrorClass<CodegenWriteFailed>()(\n\t'CodegenWriteFailed',\n\t{\n\t\toutputPath: Schema.String,\n\t\tstage: Schema.Literals(['mkdir-parent', 'write', 'rename', 'chmod', 'gitignore']),\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** `@mysten/codegen` shell-out (Move-to-TS bindings) failed or\n * silently no-op'd. Distilled-doc § \"Silent no-op from a\n * downstream tool is a failure\" — we surface a hint about the\n * common `Move.toml` cause. */\nexport class CodegenBindingsFailed extends Schema.TaggedErrorClass<CodegenBindingsFailed>()(\n\t'CodegenBindingsFailed',\n\t{\n\t\tpackage: Schema.String,\n\t\tsourcePath: Schema.String,\n\t\treason: Schema.Literals(['summary-failed', 'no-output', 'render-failed', 'write-failed']),\n\t\thint: Schema.optional(Schema.String),\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** The reader of the manifest envelope detected drift between\n * what plugins contributed and what's on disk — e.g. a stale\n * envelope from a previous stack lifecycle. */\nexport class CodegenManifestDrift extends Schema.TaggedErrorClass<CodegenManifestDrift>()(\n\t'CodegenManifestDrift',\n\t{\n\t\tdetail: Schema.String,\n\t},\n) {}\n\nexport type CodegenError =\n\t| CodegenPathConflict\n\t| CodegenEmitterCollision\n\t| CodegenAggregateConflict\n\t| CodegenRenderError\n\t| CodegenEmitFailed\n\t| CodegenWriteFailed\n\t| CodegenBindingsFailed\n\t| CodegenManifestDrift;\n"],"mappings":";;;;;;;;;AAmBA,IAAa,sBAAb,cAAyC,OAAO,iBAAsC,CAAC,CACtF,uBACA;CACC,MAAM,OAAO,SAAS,CAAC,aAAa,cAAc,CAAC;CACnD,YAAY,OAAO;CACnB,UAAU,OAAO,MAAM,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,0BAAb,cAA6C,OAAO,iBAA0C,CAAC,CAC9F,2BACA;CACC,aAAa,OAAO;CACpB,aAAa,OAAO,MAAM,OAAO,MAAM;AACxC,CACD,CAAC,CAAC,CAAC;;;;;;;;;;AAWH,IAAa,2BAAb,cAA8C,OAAO,iBAA2C,CAAC,CAChG,4BACA;CACC,QAAQ,OAAO;CACf,OAAO,OAAO,SAAS,CAAC,kBAAkB,WAAW,CAAC;;CAEtD,aAAa,OAAO;;CAEpB,aAAa,OAAO;;;CAGpB,UAAU,OAAO,MAAM,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;AAIH,IAAa,qBAAb,cAAwC,OAAO,iBAAqC,CAAC,CACpF,sBACA;CACC,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,QAAQ,OAAO;CACf,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;AAKH,IAAa,oBAAb,cAAuC,OAAO,iBAAoC,CAAC,CAClF,qBACA;CACC,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;AAGH,IAAa,qBAAb,cAAwC,OAAO,iBAAqC,CAAC,CACpF,sBACA;CACC,YAAY,OAAO;CACnB,OAAO,OAAO,SAAS;EAAC;EAAgB;EAAS;EAAU;EAAS;CAAW,CAAC;CAChF,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,wBAAb,cAA2C,OAAO,iBAAwC,CAAC,CAC1F,yBACA;CACC,SAAS,OAAO;CAChB,YAAY,OAAO;CACnB,QAAQ,OAAO,SAAS;EAAC;EAAkB;EAAa;EAAiB;CAAc,CAAC;CACxF,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;AAKuC,OAAO,iBAAuC,CAAC,CACxF,wBACA,EACC,QAAQ,OAAO,OAChB,CACD"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/orchestrators/codegen/errors.ts"],"sourcesContent":["// Typed errors for the Codegen orchestrator.\n//\n// A phase-tagged failure-mode taxonomy: \"emitter-collision at acquire\",\n// \"binary shell-out failure\", and \"pure render failure\" each get a\n// separate tag so callers can `catchTag` on each.\n//\n// Phase tags inside each error name the lifecycle step that failed\n// (resolve → emit → render → write → bindings → finalize) so error\n// attribution stays accurate.\n\nimport { Schema } from 'effect';\n\n/** Path-layer rejection from the codegen orchestrator.\n * - `kind: 'duplicate'` — two `Codegenable` contributions claim the\n * same `outputPath`. Hard failure detected BEFORE write so the\n * user-visible output dir never sees an ambiguous overwrite.\n * - `kind: 'non-relative'` — a plugin-authored `outputPath` escapes\n * the codegen root (contains `..` or is absolute). Defense-in-depth\n * for the file-layout invariants. */\nexport class CodegenPathConflict extends Schema.TaggedErrorClass<CodegenPathConflict>()(\n\t'CodegenPathConflict',\n\t{\n\t\tkind: Schema.Literals(['duplicate', 'non-relative']),\n\t\toutputPath: Schema.String,\n\t\temitters: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** Two `Codegenable` contributions share the SAME `emitterName`\n * literal but resolve to different `outputPath`s — programming\n * bug in plugin code (emitter name should be unique). Distinct\n * from `CodegenPathConflict` so attribution stays clean. */\nexport class CodegenEmitterCollision extends Schema.TaggedErrorClass<CodegenEmitterCollision>()(\n\t'CodegenEmitterCollision',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPaths: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** Two `Codegenable` contributions target the SAME aggregate\n * `bucket` but disagree on its `sensitive` metadata. The\n * `AggregateContribution` contract requires all contributors to a\n * bucket to agree; the orchestrator takes the FIRST contributor's\n * sensitivity, so a silent disagreement could emit a secret with\n * non-sensitive handling. Detected while folding contributions so the\n * cycle fails fast. */\nexport class CodegenAggregateConflict extends Schema.TaggedErrorClass<CodegenAggregateConflict>()(\n\t'CodegenAggregateConflict',\n\t{\n\t\tbucket: Schema.String,\n\t\tfield: Schema.Literals(['sensitive']),\n\t\t/** The value the first contributor established for the bucket. */\n\t\testablished: Schema.String,\n\t\t/** The conflicting value a later contributor declared. */\n\t\tconflicting: Schema.String,\n\t\t/** Emitter names: the contributor that established the value and\n\t\t * the one that disagreed. */\n\t\temitters: Schema.Array(Schema.String),\n\t},\n) {}\n\n/** A `Codegenable.emit()` wrote a value that the renderer cannot\n * serialise (a function, a symbol, a circular reference, etc.). */\nexport class CodegenRenderError extends Schema.TaggedErrorClass<CodegenRenderError>()(\n\t'CodegenRenderError',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPath: Schema.String,\n\t\tdetail: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** `Codegenable.emit()` raised. Wraps the inner Effect failure\n * rather than propagating it raw so the orchestrator's error\n * channel stays closed. */\nexport class CodegenEmitFailed extends Schema.TaggedErrorClass<CodegenEmitFailed>()(\n\t'CodegenEmitFailed',\n\t{\n\t\temitterName: Schema.String,\n\t\toutputPath: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** Disk write (atomic-write or permission-tighten) failed. */\nexport class CodegenWriteFailed extends Schema.TaggedErrorClass<CodegenWriteFailed>()(\n\t'CodegenWriteFailed',\n\t{\n\t\toutputPath: Schema.String,\n\t\tstage: Schema.Literals(['mkdir-parent', 'write', 'rename', 'chmod', 'gitignore']),\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** `@mysten/codegen` shell-out (Move-to-TS bindings) failed or\n * silently no-op'd. Distilled-doc § \"Silent no-op from a\n * downstream tool is a failure\" — we surface a hint about the\n * common `Move.toml` cause. */\nexport class CodegenBindingsFailed extends Schema.TaggedErrorClass<CodegenBindingsFailed>()(\n\t'CodegenBindingsFailed',\n\t{\n\t\tpackage: Schema.String,\n\t\tsourcePath: Schema.String,\n\t\treason: Schema.Literals(['summary-failed', 'no-output', 'render-failed', 'write-failed']),\n\t\thint: Schema.optional(Schema.String),\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n/** The reader of the manifest envelope detected drift between\n * what plugins contributed and what's on disk — e.g. a stale\n * envelope from a previous stack lifecycle. */\nexport class CodegenManifestDrift extends Schema.TaggedErrorClass<CodegenManifestDrift>()(\n\t'CodegenManifestDrift',\n\t{\n\t\tdetail: Schema.String,\n\t},\n) {}\n\nexport type CodegenError =\n\t| CodegenPathConflict\n\t| CodegenEmitterCollision\n\t| CodegenAggregateConflict\n\t| CodegenRenderError\n\t| CodegenEmitFailed\n\t| CodegenWriteFailed\n\t| CodegenBindingsFailed\n\t| CodegenManifestDrift;\n"],"mappings":";;;;;;;;;AAmBA,IAAa,sBAAb,cAAyC,OAAO,iBAAsC,CAAC,CACtF,uBACA;CACC,MAAM,OAAO,SAAS,CAAC,aAAa,cAAc,CAAC;CACnD,YAAY,OAAO;CACnB,UAAU,OAAO,MAAM,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,0BAAb,cAA6C,OAAO,iBAA0C,CAAC,CAC9F,2BACA;CACC,aAAa,OAAO;CACpB,aAAa,OAAO,MAAM,OAAO,MAAM;AACxC,CACD,CAAC,CAAC,CAAC;;;;;;;;AASH,IAAa,2BAAb,cAA8C,OAAO,iBAA2C,CAAC,CAChG,4BACA;CACC,QAAQ,OAAO;CACf,OAAO,OAAO,SAAS,CAAC,WAAW,CAAC;;CAEpC,aAAa,OAAO;;CAEpB,aAAa,OAAO;;;CAGpB,UAAU,OAAO,MAAM,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;AAIH,IAAa,qBAAb,cAAwC,OAAO,iBAAqC,CAAC,CACpF,sBACA;CACC,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,QAAQ,OAAO;CACf,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;AAKH,IAAa,oBAAb,cAAuC,OAAO,iBAAoC,CAAC,CAClF,qBACA;CACC,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;AAGH,IAAa,qBAAb,cAAwC,OAAO,iBAAqC,CAAC,CACpF,sBACA;CACC,YAAY,OAAO;CACnB,OAAO,OAAO,SAAS;EAAC;EAAgB;EAAS;EAAU;EAAS;CAAW,CAAC;CAChF,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,wBAAb,cAA2C,OAAO,iBAAwC,CAAC,CAC1F,yBACA;CACC,SAAS,OAAO;CAChB,YAAY,OAAO;CACnB,QAAQ,OAAO,SAAS;EAAC;EAAkB;EAAa;EAAiB;CAAc,CAAC;CACxF,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,OAAO,OAAO,SAAS,OAAO,MAAM;AACrC,CACD,CAAC,CAAC,CAAC;AAKuC,OAAO,iBAAuC,CAAC,CACxF,wBACA,EACC,QAAQ,OAAO,OAChB,CACD"}
@@ -1,5 +1,5 @@
1
1
  import { CodegenRenderError } from "./errors.mjs";
2
- import { isRawExpr } from "../../contracts/codegenable.mjs";
2
+ import { isForNetworkBucket, isRawExpr } from "../../contracts/codegenable.mjs";
3
3
  //#region src/orchestrators/codegen/format.ts
4
4
  const GENERATED_HEADER = [
5
5
  "// THIS FILE IS AUTO-GENERATED BY @mysten/devstack.",
@@ -39,6 +39,10 @@ const renderFile = (input) => {
39
39
  }
40
40
  lines.push("");
41
41
  }
42
+ if (input.preamble && input.preamble.length > 0) {
43
+ for (const stmt of input.preamble) lines.push(stmt);
44
+ lines.push("");
45
+ }
42
46
  const keys = Object.keys(input.exports).sort();
43
47
  for (const key of keys) {
44
48
  const value = input.exports[key];
@@ -67,6 +71,21 @@ const tryRender = (value, seen, depth = 1) => {
67
71
  if (value === null) return tryOk("null");
68
72
  if (value === void 0) return tryErr("undefined is not serialisable — emit null instead");
69
73
  if (isRawExpr(value)) return tryOk(value.expr);
74
+ if (isForNetworkBucket(value)) {
75
+ const inner = tryRender(value.inner, seen, depth + 2);
76
+ if (!inner.ok) return inner;
77
+ const method = INDENT.repeat(depth);
78
+ const body = INDENT.repeat(depth + 1);
79
+ const close = INDENT.repeat(depth - 1);
80
+ const param = value.needsDep ? "network" : "_network";
81
+ const lines = ["{"];
82
+ lines.push(`${method}forNetwork(${param}: string) {`);
83
+ if (value.needsDep) lines.push(`${body}const dep = loadDeployment().forNetwork(network);`);
84
+ lines.push(`${body}return ${inner.text} as const;`);
85
+ lines.push(`${method}},`);
86
+ lines.push(`${close}}`);
87
+ return tryOk(lines.join("\n"));
88
+ }
70
89
  const t = typeof value;
71
90
  if (t === "string") return tryOk(JSON.stringify(value));
72
91
  if (t === "number") {