@mysten-incubation/devstack 0.3.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 (132) hide show
  1. package/README.md +1 -1
  2. package/dashboard-ui/assets/{grpc-Clz0oOtc.js → grpc-CpkDu4SA.js} +1 -1
  3. package/dashboard-ui/assets/{index-Cmqv9kiU.js → index-jLPRmjst.js} +2 -2
  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 +1 -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/errors.d.mts +1 -1
  14. package/dist/build-integrations/playwright/errors.mjs.map +1 -1
  15. package/dist/build-integrations/playwright/index.d.mts +2 -2
  16. package/dist/build-integrations/playwright/index.mjs +2 -2
  17. package/dist/build-integrations/playwright/wallet-context.d.mts +2 -1
  18. package/dist/build-integrations/playwright/wallet-context.mjs +141 -41
  19. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  20. package/dist/build-integrations/runtime/dapp-kit-slot.mjs +1 -1
  21. package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
  22. package/dist/build-integrations/vite/index.d.mts +54 -42
  23. package/dist/build-integrations/vite/index.mjs +239 -106
  24. package/dist/build-integrations/vite/index.mjs.map +1 -1
  25. package/dist/build-integrations/vitest/global-setup.mjs +8 -8
  26. package/dist/build-integrations/vitest/global-setup.mjs.map +1 -1
  27. package/dist/cli/main.mjs +3 -2
  28. package/dist/cli/main.mjs.map +1 -1
  29. package/dist/cli/wirings/apply.mjs +0 -1
  30. package/dist/cli/wirings/apply.mjs.map +1 -1
  31. package/dist/cli/wirings/codegen.mjs +2 -3
  32. package/dist/cli/wirings/codegen.mjs.map +1 -1
  33. package/dist/cli/wirings/dump-deployment.mjs +141 -0
  34. package/dist/cli/wirings/dump-deployment.mjs.map +1 -0
  35. package/dist/cli/wirings/snapshot.mjs +0 -1
  36. package/dist/cli/wirings/snapshot.mjs.map +1 -1
  37. package/dist/contracts/codegenable.d.mts +22 -25
  38. package/dist/contracts/codegenable.mjs +35 -4
  39. package/dist/contracts/codegenable.mjs.map +1 -1
  40. package/dist/contracts/config-bindings.mjs +43 -18
  41. package/dist/contracts/config-bindings.mjs.map +1 -1
  42. package/dist/index.mjs +1 -1
  43. package/dist/orchestrators/boot.d.mts +0 -10
  44. package/dist/orchestrators/boot.mjs +19 -59
  45. package/dist/orchestrators/boot.mjs.map +1 -1
  46. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  47. package/dist/orchestrators/codegen/config-runtime.mjs +137 -112
  48. package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -1
  49. package/dist/orchestrators/codegen/deployment-network-file.mjs +130 -0
  50. package/dist/orchestrators/codegen/deployment-network-file.mjs.map +1 -0
  51. package/dist/orchestrators/codegen/deployment-strict.mjs +77 -0
  52. package/dist/orchestrators/codegen/deployment-strict.mjs.map +1 -0
  53. package/dist/orchestrators/codegen/deployment.d.mts +63 -0
  54. package/dist/orchestrators/codegen/deployment.mjs +153 -0
  55. package/dist/orchestrators/codegen/deployment.mjs.map +1 -0
  56. package/dist/orchestrators/codegen/errors.mjs +7 -9
  57. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  58. package/dist/orchestrators/codegen/format.mjs +20 -1
  59. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  60. package/dist/orchestrators/codegen/paths.mjs +1 -8
  61. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  62. package/dist/orchestrators/codegen/service.mjs +354 -141
  63. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  64. package/dist/orchestrators/layers.mjs +0 -1
  65. package/dist/orchestrators/layers.mjs.map +1 -1
  66. package/dist/orchestrators/network-options.d.mts +37 -35
  67. package/dist/orchestrators/network-options.mjs +13 -10
  68. package/dist/orchestrators/network-options.mjs.map +1 -1
  69. package/dist/plugins/account/codegen.d.mts +3 -4
  70. package/dist/plugins/account/codegen.mjs +5 -7
  71. package/dist/plugins/account/codegen.mjs.map +1 -1
  72. package/dist/plugins/account/index.mjs +1 -3
  73. package/dist/plugins/account/index.mjs.map +1 -1
  74. package/dist/plugins/coin/codegen.mjs +5 -5
  75. package/dist/plugins/coin/codegen.mjs.map +1 -1
  76. package/dist/plugins/coin/index.mjs.map +1 -1
  77. package/dist/plugins/dashboard/schema/root.mjs +3 -1
  78. package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
  79. package/dist/plugins/deepbook/codegen.mjs +4 -4
  80. package/dist/plugins/deepbook/codegen.mjs.map +1 -1
  81. package/dist/plugins/deepbook/index.mjs.map +1 -1
  82. package/dist/plugins/internal/codegen-helpers.mjs +0 -1
  83. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
  84. package/dist/plugins/package/codegen.d.mts +1 -12
  85. package/dist/plugins/package/codegen.mjs +43 -25
  86. package/dist/plugins/package/codegen.mjs.map +1 -1
  87. package/dist/plugins/package/dep-resolution.mjs +1 -1
  88. package/dist/plugins/package/dep-resolution.mjs.map +1 -1
  89. package/dist/plugins/package/index.d.mts +14 -11
  90. package/dist/plugins/package/index.mjs +6 -7
  91. package/dist/plugins/package/index.mjs.map +1 -1
  92. package/dist/plugins/seal/codegen.mjs +3 -3
  93. package/dist/plugins/seal/codegen.mjs.map +1 -1
  94. package/dist/plugins/seal/index.mjs.map +1 -1
  95. package/dist/plugins/sui/codegen.mjs +5 -4
  96. package/dist/plugins/sui/codegen.mjs.map +1 -1
  97. package/dist/plugins/sui/index.mjs +1 -2
  98. package/dist/plugins/sui/index.mjs.map +1 -1
  99. package/dist/plugins/wallet/codegen.d.mts +8 -12
  100. package/dist/plugins/wallet/codegen.mjs +22 -15
  101. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  102. package/dist/plugins/wallet/index.d.mts +4 -3
  103. package/dist/plugins/wallet/index.mjs +1 -1
  104. package/dist/plugins/wallet/index.mjs.map +1 -1
  105. package/dist/plugins/wallet/service.d.mts +2 -2
  106. package/dist/plugins/wallet/service.mjs +2 -3
  107. package/dist/plugins/wallet/service.mjs.map +1 -1
  108. package/dist/plugins/walrus/codegen.mjs +4 -4
  109. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  110. package/dist/plugins/walrus/index.mjs +1 -1
  111. package/dist/plugins/walrus/index.mjs.map +1 -1
  112. package/dist/substrate/manifest.d.mts +17 -22
  113. package/dist/substrate/manifest.mjs +4 -6
  114. package/dist/substrate/manifest.mjs.map +1 -1
  115. package/dist/substrate/plugin-ctx.d.mts +6 -6
  116. package/dist/substrate/plugin-ctx.mjs.map +1 -1
  117. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  118. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  119. package/dist/substrate/runtime/paths.mjs +1 -1
  120. package/dist/surfaces/cli/command-tree.mjs +6 -6
  121. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  122. package/dist/surfaces/cli/index.mjs +6 -4
  123. package/dist/surfaces/cli/index.mjs.map +1 -1
  124. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  125. package/package.json +1 -1
  126. package/dist/cli/wirings/dump-ids.mjs +0 -86
  127. package/dist/cli/wirings/dump-ids.mjs.map +0 -1
  128. package/dist/orchestrators/codegen/id-config.d.mts +0 -1
  129. package/dist/orchestrators/codegen/id-config.mjs +0 -107
  130. package/dist/orchestrators/codegen/id-config.mjs.map +0 -1
  131. package/dist/orchestrators/codegen/output-location.mjs +0 -32
  132. package/dist/orchestrators/codegen/output-location.mjs.map +0 -1
@@ -6,37 +6,38 @@ import { emitOne } from "./emit.mjs";
6
6
  import { dirModeFor, modeFor } from "./permissions.mjs";
7
7
  import { MoveCodegenService, MoveSummaryRunnerService, emitBindings, isPackageBindings } from "./bindings.mjs";
8
8
  import { CodegenPathsService } from "./paths.mjs";
9
- import { isRawExpr } from "../../contracts/codegenable.mjs";
9
+ import { ForNetworkBucket, isForNetworkBucket, isRawExpr, rawExpr } from "../../contracts/codegenable.mjs";
10
10
  import { CONFIG_RUNTIME_OUTPUT_PATH, CONFIG_RUNTIME_SOURCE } from "./config-runtime.mjs";
11
+ import { DEPLOYMENT_STRICT_OUTPUT_PATH, renderDeploymentStrict } from "./deployment-strict.mjs";
12
+ import { LOCAL_NETWORK_NAME } from "../../api/inference-network.mjs";
11
13
  import { renderFile } from "./format.mjs";
12
14
  import { writeGitignore } from "./gitignore.mjs";
13
- import { UNRESOLVED_ID } from "./id-config.mjs";
15
+ import { UNRESOLVED_ID } from "./deployment.mjs";
14
16
  import { Context, Effect, Layer, Order, Ref } from "effect";
15
- import { dirname } from "node:path";
17
+ import { existsSync, readdirSync } from "node:fs";
18
+ import { dirname, join } from "node:path";
16
19
  //#region src/orchestrators/codegen/service.ts
17
- /** Resolve a decl/aggregate's absolute output path against the tree
18
- * selected by its `outputLocation`. `'generated-extras'` routes
19
- * through `paths.resolveExtras` (the gitignored dev tree); everything
20
- * else through `paths.resolve` (the staging-and-swapped runtime tree). */
21
- const resolveAt = (paths, location, outputPath) => location === "generated-extras" ? paths.resolveExtras(outputPath) : paths.resolve(outputPath);
22
- const declLocation = (decl) => decl.outputLocation ?? "generated";
23
- /** A decl belongs to the `emitExtras` flush IFF it writes ONLY into the
24
- * dev-only `generated-extras` tree. INVARIANT: `emitExtras` must NEVER
25
- * touch the committed `src/generated` tree (it runs without stage-and-swap),
26
- * so a decl that would emit any file into `generated` is excluded.
27
- *
28
- * - `aggregateOnly` decls write only their aggregate file: include iff the
29
- * aggregate's location is `generated-extras` (e.g. each account folding
30
- * into the gitignored `accounts.ts`).
31
- * - standalone decls write a per-decl file (and possibly an aggregate):
32
- * include iff that standalone file lands in `generated-extras` (e.g. the
33
- * wallet's `dev-wallet.ts`). A standalone-in-`generated` decl is excluded
34
- * even if its aggregate targets `generated-extras`. */
35
- const isExtrasDecl = (decl) => decl.aggregateOnly === true ? (decl.aggregate?.outputLocation ?? "generated") === "generated-extras" : declLocation(decl) === "generated-extras";
20
+ /** Discover the app's LIVE network names by globbing `<projectRoot>/deployments/*.ts`
21
+ * (D7 the network set is the `deployments/` directory, by FILENAME; the
22
+ * file CONTENTS are never read — ids load at app build via Vite). The
23
+ * project root is the grandparent of the canonical (non-staging) codegen
24
+ * `outputDir` (`<projectRoot>/src/generated`). Returns the filenames sans
25
+ * `.ts`, sorted; empty when there is no `deployments/` dir (a clean clone /
26
+ * template `ProvidedNetwork = never`, `NETWORK_NAMES = [<local>]`). Never
27
+ * throws a read failure degrades to empty (no live networks). */
28
+ const discoverProvidedNetworks = (canonicalOutputDir) => {
29
+ try {
30
+ const deploymentsDir = join(dirname(dirname(canonicalOutputDir)), "deployments");
31
+ if (!existsSync(deploymentsDir)) return [];
32
+ return readdirSync(deploymentsDir).filter((f) => f.endsWith(".ts") && !f.endsWith(".d.ts")).map((f) => f.slice(0, -3)).filter((n) => n.length > 0).filter((n) => n !== LOCAL_NETWORK_NAME).sort();
33
+ } catch {
34
+ return [];
35
+ }
36
+ };
36
37
  const buildParentModeResolver = (paths, entries) => Effect.gen(function* () {
37
38
  const byParent = /* @__PURE__ */ new Map();
38
39
  for (const entry of entries) {
39
- const parent = dirname(yield* resolveAt(paths, entry.location, entry.outputPath));
40
+ const parent = dirname(yield* paths.resolve(entry.outputPath));
40
41
  const current = byParent.get(parent);
41
42
  if (current === void 0) byParent.set(parent, [{ sensitive: entry.sensitive }]);
42
43
  else current.push({ sensitive: entry.sensitive });
@@ -66,6 +67,11 @@ const runEmitCycleLocked = (input) => Effect.gen(function* () {
66
67
  const paths = yield* CodegenPathsService;
67
68
  const moveRunner = yield* MoveSummaryRunnerService;
68
69
  const moveCodegen = yield* MoveCodegenService;
70
+ const providedNetworks = input.providedNetworks ?? discoverProvidedNetworks(paths.outputDir);
71
+ const innerInput = {
72
+ ...input,
73
+ providedNetworks
74
+ };
69
75
  yield* validateUniqueness(input.contributions);
70
76
  yield* validateAggregatePathAvailability(input.contributions);
71
77
  const cycleId = mintRandomSuffix(16);
@@ -75,7 +81,7 @@ const runEmitCycleLocked = (input) => Effect.gen(function* () {
75
81
  idSuffix: cycleId,
76
82
  preserveOnPreseed: true,
77
83
  build: Effect.gen(function* () {
78
- return rewriteResultPaths(yield* runEmitCycleInner(input, stagingPaths).pipe(Effect.provideService(MoveSummaryRunnerService, moveRunner), Effect.provideService(MoveCodegenService, moveCodegen)), stagingPaths.outputDir, paths.outputDir);
84
+ return rewriteResultPaths(yield* runEmitCycleInner(innerInput, stagingPaths).pipe(Effect.provideService(MoveSummaryRunnerService, moveRunner), Effect.provideService(MoveCodegenService, moveCodegen)), stagingPaths.outputDir, paths.outputDir);
79
85
  })
80
86
  }).pipe(Effect.mapError((e) => {
81
87
  if (e instanceof StageAndSwapError) return new CodegenWriteFailed({
@@ -124,7 +130,6 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
124
130
  const sortedDecls = [...fileEmitters].sort(Order.mapInput(Order.String, (d) => d.outputPath));
125
131
  const parentModeFor = yield* buildParentModeResolver(paths, fileEmitters.filter((d) => d.aggregateOnly !== true).map((d) => ({
126
132
  outputPath: d.outputPath,
127
- location: declLocation(d),
128
133
  sensitive: d.sensitive === true
129
134
  })));
130
135
  for (const decl of sortedDecls) {
@@ -136,30 +141,19 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
136
141
  const bucket = aggregates.get(decl.aggregate.bucket) ?? {};
137
142
  deepMerge(bucket, projected);
138
143
  aggregates.set(decl.aggregate.bucket, bucket);
139
- const declLoc = decl.aggregate.outputLocation ?? "generated";
140
144
  const declSensitive = decl.aggregate.sensitive === true;
141
145
  const established = aggregateMeta.get(decl.aggregate.bucket);
142
146
  if (established === void 0) aggregateMeta.set(decl.aggregate.bucket, {
143
- location: declLoc,
144
147
  sensitive: declSensitive,
145
148
  establishedBy: decl.emitterName
146
149
  });
147
- else {
148
- if (established.location !== declLoc) return yield* Effect.fail(new CodegenAggregateConflict({
149
- bucket: decl.aggregate.bucket,
150
- field: "outputLocation",
151
- established: established.location,
152
- conflicting: declLoc,
153
- emitters: [established.establishedBy, decl.emitterName]
154
- }));
155
- if (established.sensitive !== declSensitive) return yield* Effect.fail(new CodegenAggregateConflict({
156
- bucket: decl.aggregate.bucket,
157
- field: "sensitive",
158
- established: String(established.sensitive),
159
- conflicting: String(declSensitive),
160
- emitters: [established.establishedBy, decl.emitterName]
161
- }));
162
- }
150
+ else if (established.sensitive !== declSensitive) return yield* Effect.fail(new CodegenAggregateConflict({
151
+ bucket: decl.aggregate.bucket,
152
+ field: "sensitive",
153
+ established: String(established.sensitive),
154
+ conflicting: String(declSensitive),
155
+ emitters: [established.establishedBy, decl.emitterName]
156
+ }));
163
157
  }
164
158
  }
165
159
  for (const value of Object.values(exported)) if (isPackageBindings(value)) packageContribs.push(value);
@@ -172,7 +166,7 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
172
166
  imports: emission.imports
173
167
  });
174
168
  if (!rendered.ok) return yield* Effect.fail(rendered.error);
175
- const abs = yield* resolveAt(paths, declLocation(decl), decl.outputPath);
169
+ const abs = yield* paths.resolve(decl.outputPath);
176
170
  switch ((yield* emitOne({
177
171
  path: abs,
178
172
  content: rendered.text,
@@ -190,20 +184,27 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
190
184
  break;
191
185
  }
192
186
  }
193
- const aggregateFiles = buildAggregateFiles(aggregates, aggregateMeta);
187
+ const aggregateFiles = buildAggregateFiles(aggregates, aggregateMeta).map(withConfigEnvelopeAccessors).map(withForNetworkAccessor);
194
188
  let needsConfigRuntime = false;
195
189
  for (const aggregate of aggregateFiles) {
196
- const resolvers = resolversUsedBy(aggregate.exports);
197
- if (resolvers.length > 0) needsConfigRuntime = true;
190
+ const usage = deploymentUsageOf(aggregate.exports);
191
+ if (!deploymentUsageEmpty(usage)) needsConfigRuntime = true;
192
+ const imports = deploymentImportsFor(usage);
193
+ const preamble = isServiceBucket(aggregate.outputPath) ? [] : deploymentPreambleFor(usage);
194
+ const usesNetworkNames = referencesNetworkNames(aggregate.exports);
195
+ const importLines = [];
196
+ if (imports.length > 0) importLines.push(`import { ${imports.join(", ")} } from './config-runtime.js';`);
197
+ if (usesNetworkNames) importLines.push(`import { NETWORK_NAMES } from './deployment.js';`);
198
198
  const rendered = renderFile({
199
199
  emitterName: aggregate.emitterName,
200
200
  outputPath: aggregate.outputPath,
201
201
  sensitive: aggregate.sensitive,
202
202
  exports: aggregate.exports,
203
- ...resolvers.length > 0 ? { imports: [`import { ${resolvers.join(", ")} } from './config-runtime.js';`] } : {}
203
+ ...importLines.length > 0 ? { imports: importLines } : {},
204
+ ...preamble.length > 0 ? { preamble } : {}
204
205
  });
205
206
  if (!rendered.ok) return yield* Effect.fail(rendered.error);
206
- const abs = yield* resolveAt(paths, aggregate.location, aggregate.outputPath);
207
+ const abs = yield* paths.resolve(aggregate.outputPath);
207
208
  switch ((yield* emitOne({
208
209
  path: abs,
209
210
  content: rendered.text,
@@ -239,6 +240,32 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
239
240
  filesChmod.push(abs);
240
241
  break;
241
242
  }
243
+ const strictInput = strictTypeInputFrom(aggregateFiles);
244
+ const deploymentStrict = renderDeploymentStrict({
245
+ localNetworkName: LOCAL_NETWORK_NAME,
246
+ packageNames: strictInput.packageNames,
247
+ mvrPlaceholders: strictInput.mvrPlaceholders,
248
+ mvrTypeTags: strictInput.mvrTypeTags,
249
+ providedNetworks: input.providedNetworks ?? [],
250
+ serviceValues: serviceValuesFrom(input.contributions)
251
+ });
252
+ const strictAbs = yield* paths.resolve(DEPLOYMENT_STRICT_OUTPUT_PATH);
253
+ switch ((yield* emitOne({
254
+ path: strictAbs,
255
+ content: deploymentStrict,
256
+ mode: 420,
257
+ parentMode: parentModeFor(strictAbs)
258
+ })).outcome) {
259
+ case "wrote":
260
+ filesWritten.push(strictAbs);
261
+ break;
262
+ case "unchanged":
263
+ filesUnchanged.push(strictAbs);
264
+ break;
265
+ case "chmod-only":
266
+ filesChmod.push(strictAbs);
267
+ break;
268
+ }
242
269
  }
243
270
  let bindings = null;
244
271
  if (packageContribs.length > 0) bindings = yield* emitBindings({
@@ -247,8 +274,8 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
247
274
  importExtension: input.bindingsImportExtension
248
275
  });
249
276
  else yield* Effect.logInfo("codegen: no package contributions; skipping Move-to-TS bindings step.");
250
- if (fileEmitters.some((d) => d.aggregateOnly !== true && declLocation(d) === "generated") || aggregateFiles.some((a) => a.location === "generated")) {
251
- const sensitivePaths = [...fileEmitters.filter((d) => d.sensitive === true && d.aggregateOnly !== true && declLocation(d) === "generated").map((d) => d.outputPath), ...aggregateFiles.filter((a) => a.sensitive && a.location === "generated").map((a) => a.outputPath)];
277
+ if (fileEmitters.some((d) => d.aggregateOnly !== true) || aggregateFiles.length > 0) {
278
+ const sensitivePaths = [...fileEmitters.filter((d) => d.sensitive === true && d.aggregateOnly !== true).map((d) => d.outputPath), ...aggregateFiles.filter((a) => a.sensitive).map((a) => a.outputPath)];
252
279
  yield* writeGitignore({
253
280
  path: paths.gitignoreFile,
254
281
  sensitivePaths,
@@ -299,19 +326,18 @@ const validateUniqueness = (decls) => Effect.gen(function* () {
299
326
  const byName = /* @__PURE__ */ new Map();
300
327
  for (const d of decls) {
301
328
  if (d.aggregateOnly !== true) {
302
- const pathKey = `${declLocation(d)} ${d.outputPath}`;
303
- const ps = byPath.get(pathKey) ?? [];
329
+ const ps = byPath.get(d.outputPath) ?? [];
304
330
  ps.push(d.emitterName);
305
- byPath.set(pathKey, ps);
331
+ byPath.set(d.outputPath, ps);
306
332
  }
307
333
  if (d.allowEmitterNameRepetition === true) continue;
308
334
  const ns = byName.get(d.emitterName) ?? [];
309
335
  ns.push(d.outputPath);
310
336
  byName.set(d.emitterName, ns);
311
337
  }
312
- for (const [pathKey, emitters] of byPath) if (emitters.length > 1) return yield* Effect.fail(new CodegenPathConflict({
338
+ for (const [outputPath, emitters] of byPath) if (emitters.length > 1) return yield* Effect.fail(new CodegenPathConflict({
313
339
  kind: "duplicate",
314
- outputPath: pathKey.slice(pathKey.indexOf(" ") + 1),
340
+ outputPath,
315
341
  emitters
316
342
  }));
317
343
  for (const [name, outputPaths] of byName) if (outputPaths.length > 1) return yield* Effect.fail(new CodegenEmitterCollision({
@@ -326,14 +352,10 @@ const validateUniqueness = (decls) => Effect.gen(function* () {
326
352
  * it does not enumerate or recognize plugin identities here.
327
353
  */
328
354
  const validateAggregatePathAvailability = (decls) => Effect.gen(function* () {
329
- const aggregatePaths = /* @__PURE__ */ new Map();
330
- for (const decl of decls) if (decl.aggregate !== void 0) {
331
- const location = decl.aggregate.outputLocation ?? "generated";
332
- aggregatePaths.set(`${location} ${decl.aggregate.bucket}`, decl.aggregate.bucket);
333
- }
334
- for (const [key, bucket] of aggregatePaths) {
335
- const location = key.slice(0, key.indexOf(" "));
336
- const colliding = decls.filter((decl) => decl.aggregateOnly !== true && declLocation(decl) === location && decl.outputPath === bucket);
355
+ const aggregateBuckets = /* @__PURE__ */ new Set();
356
+ for (const decl of decls) if (decl.aggregate !== void 0) aggregateBuckets.add(decl.aggregate.bucket);
357
+ for (const bucket of aggregateBuckets) {
358
+ const colliding = decls.filter((decl) => decl.aggregateOnly !== true && decl.outputPath === bucket);
337
359
  if (colliding.length > 0) return yield* Effect.fail(new CodegenPathConflict({
338
360
  kind: "duplicate",
339
361
  outputPath: bucket,
@@ -369,8 +391,7 @@ const deepMerge = (target, source) => {
369
391
  * orchestrator picks the export key from the bucket filename; the
370
392
  * stem itself is not a plugin identifier — it is the filename
371
393
  * without the `.ts` extension, derived mechanically. The bucket's
372
- * `location`/`sensitive` (from the first contributing decl) drive
373
- * which tree the file lands in and its mode.
394
+ * `sensitive` flag (from the first contributing decl) drives its mode.
374
395
  */
375
396
  const buildAggregateFiles = (buckets, meta) => {
376
397
  const files = [];
@@ -379,7 +400,6 @@ const buildAggregateFiles = (buckets, meta) => {
379
400
  if (Object.keys(contents).length === 0) continue;
380
401
  const stem = bucketStem(bucket);
381
402
  const bucketMeta = meta.get(bucket) ?? {
382
- location: "generated",
383
403
  sensitive: false,
384
404
  establishedBy: `aggregate/${stem}`
385
405
  };
@@ -387,62 +407,264 @@ const buildAggregateFiles = (buckets, meta) => {
387
407
  emitterName: `aggregate/${stem}`,
388
408
  outputPath: bucket,
389
409
  exports: { [stem]: contents },
390
- location: bucketMeta.location,
391
410
  sensitive: bucketMeta.sensitive
392
411
  });
393
412
  }
394
413
  return files;
395
414
  };
396
415
  const bucketStem = (bucket) => bucket.replace(/\.ts$/, "").replace(/^.*\//, "");
397
- /** The config-runtime resolver names a committed `config.ts` aggregate may
398
- * reference as raw expressions. Each is imported from `./config-runtime.js`
399
- * only when the aggregate actually calls it (oxlint flags unused imports). */
400
- const CONFIG_RUNTIME_RESOLVERS = [
401
- "resolveId",
402
- "resolveNetwork",
403
- "resolveNetworks",
404
- "resolveValue"
405
- ];
406
- /** Recursively collect which `config-runtime.ts` resolvers an exports map
407
- * references via raw expressions — i.e. the committed `config.ts` needs each
408
- * imported + the fixed `config-runtime.ts` emitted alongside it. */
409
- const collectResolversInValue = (value, found) => {
416
+ /** The committed `config.ts` bucket. The orchestrator already encodes
417
+ * `config.ts` semantics by name elsewhere (the live `assembleDeployment`
418
+ * slices it by this exact bucket); the static envelope-accessor injection
419
+ * below is the matching static-render-only branch. */
420
+ const CONFIG_BUCKET = "config.ts";
421
+ /** The network-agnostic `accounts.ts` bucket. Like `config.ts`, this is a
422
+ * bucket the orchestrator special-cases STRUCTURALLY (not by plugin identity):
423
+ * the live `assembleDeployment` folds it into the deployment envelope's
424
+ * network-AGNOSTIC `accounts` map (name → address) rather than any per-network
425
+ * unit, so it must NOT receive the per-network `forNetwork(network)` wrapper. */
426
+ const ACCOUNTS_BUCKET = "accounts.ts";
427
+ /** The buckets that are NOT per-network service buckets the ones the
428
+ * orchestrator special-cases structurally:
429
+ * - `config.ts`: carries the TYPED deployment channel and its own
430
+ * per-network `forNetwork` field (injected by {@link withConfigEnvelopeAccessors});
431
+ * `assembleDeployment` slices it into `network`/`networks`/`packages`/`mvrOverrides`.
432
+ * - `accounts.ts`: network-agnostic (name → address), folded into the
433
+ * envelope's `accounts` map by `assembleDeployment`.
434
+ * - `packages.ts`: network-agnostic MVR pointers (see {@link PACKAGES_BUCKET}).
435
+ * config/accounts mirror the two bucket arms `assembleDeployment` branches on;
436
+ * `packages.ts` is the additional structurally-network-agnostic aggregate whose
437
+ * per-network story is owned by `config.forNetwork`. Keeping this set to the
438
+ * genuinely network-agnostic buckets is what lets the STATIC `forNetwork` gate
439
+ * auto-wrap any NEW per-network service bucket by default. */
440
+ const NON_SERVICE_BUCKETS = new Set([
441
+ CONFIG_BUCKET,
442
+ ACCOUNTS_BUCKET,
443
+ "packages.ts"
444
+ ]);
445
+ /** True when a bucket is a per-network SERVICE bucket (coins / deepbook / seal /
446
+ * walrus today; a NEW plugin's `pyth.ts` automatically) — i.e. any aggregate
447
+ * bucket that is NOT one of the orchestrator's structurally-special buckets.
448
+ *
449
+ * Derived from a DECLARED structural fact (the bucket is not config / not
450
+ * accounts) rather than a hard-coded service-name allowlist: a per-network
451
+ * service plugin emitting a new bucket is wrapped in its `forNetwork(network)`
452
+ * accessor by default, so its ids resolve for the dapp-kit-selected network
453
+ * instead of silently baking the DEFAULT network's ids at module load. */
454
+ const isServiceBucket = (bucket) => !NON_SERVICE_BUCKETS.has(bucket);
455
+ /**
456
+ * Inject the DEPLOYMENT envelope-accessor fields into the committed
457
+ * `config.ts` aggregate's `config` object literal as raw expressions:
458
+ * - `defaultNetwork: __deployment.defaultNetwork`
459
+ * - `networkNames: __deployment.networkNames`
460
+ * - `forNetwork: __deployment.forNetwork`
461
+ *
462
+ * There is deliberately NO `activeNetwork` field: the genuinely active network
463
+ * is whatever dapp-kit currently has selected (it can `switchNetwork` at
464
+ * runtime), so a statically-resolved "active" entry would lie the moment the
465
+ * user switches. Apps resolve per-network data through
466
+ * `config.forNetwork(<dapp-kit-selected network>)` — e.g.
467
+ * `createClient(network) => config.forNetwork(network)` — so nothing drifts out
468
+ * of sync with the selected network.
469
+ *
470
+ * STATIC-render-only: these are wired into the emitted committed tree so apps
471
+ * can enumerate / look up networks off `config`, but they are NOT part of the
472
+ * live deployment path (`assembleDeployment` / `deploymentFromBucket` slice the raw
473
+ * `network`/`networks`/`packages`/`mvrOverrides` fields, never these). The
474
+ * aggregate file's `exports` is `{ config: {...} }`; mutate the inner object.
475
+ */
476
+ const withConfigEnvelopeAccessors = (file) => {
477
+ if (file.outputPath !== CONFIG_BUCKET) return file;
478
+ const stem = bucketStem(file.outputPath);
479
+ const inner = file.exports[stem];
480
+ if (!isPlainObject(inner)) return file;
481
+ const augmented = {
482
+ ...inner,
483
+ defaultNetwork: rawExpr("__deployment.defaultNetwork as (typeof NETWORK_NAMES)[number]"),
484
+ networkNames: rawExpr("NETWORK_NAMES"),
485
+ forNetwork: rawExpr("__deployment.forNetwork")
486
+ };
487
+ return {
488
+ ...file,
489
+ exports: {
490
+ ...file.exports,
491
+ [stem]: augmented
492
+ }
493
+ };
494
+ };
495
+ /**
496
+ * Wrap a SERVICE bucket's inner object in a `forNetwork(network)` accessor.
497
+ *
498
+ * A per-network service bucket (coin → `coins.ts`, deepbook → `deepbook.ts`,
499
+ * seal → `seal.ts`, walrus → `walrus.ts`, and any NEW plugin's bucket) gets its
500
+ * ids wrapped so they resolve for the dapp-kit-selected network rather than the
501
+ * default network baked at module load. Which buckets qualify is derived from
502
+ * {@link isServiceBucket} (every bucket that is not the structurally-special
503
+ * `config.ts` / `accounts.ts`) — see its note for why a declared denylist beats
504
+ * a hard-coded service-name allowlist.
505
+ *
506
+ * The aggregate file's `exports` is `{ <stem>: <merged bucket object> }`. We
507
+ * replace the merged object with a {@link ForNetworkBucket} marker the renderer
508
+ * emits as `{ forNetwork(network) { const dep = …; return <object> as const; } }`.
509
+ * `needsDep` is true when the merged object actually references `dep` (a
510
+ * pure-literal bucket — known/live seal, builtin-only coin — does not, so the
511
+ * accessor omits the `const dep` line and ignores its `network` param).
512
+ *
513
+ * Non-service buckets pass through unchanged.
514
+ */
515
+ const withForNetworkAccessor = (file) => {
516
+ if (!isServiceBucket(file.outputPath)) return file;
517
+ const stem = bucketStem(file.outputPath);
518
+ const inner = file.exports[stem];
519
+ if (!isPlainObject(inner)) return file;
520
+ const usage = { ...EMPTY_DEPLOYMENT_USAGE };
521
+ scanDeploymentUsage(inner, usage);
522
+ const marker = new ForNetworkBucket(inner, usage.usesDep);
523
+ return {
524
+ ...file,
525
+ exports: {
526
+ ...file.exports,
527
+ [stem]: marker
528
+ }
529
+ };
530
+ };
531
+ /** Pull the app's declared package names + MVR placeholders out of the
532
+ * committed `config.ts` aggregate's inner `config` object — the SAME data
533
+ * the strict `deployment.ts` type narrows over. `config.packages.<name>`
534
+ * gives the package names; `config.mvrOverrides.<mvr>` gives the placeholder
535
+ * keys. Both come from the deep-merged bucket (no chain / no live data), so
536
+ * this stays a pure projection over already-collected exports. Returns empty
537
+ * arrays when there is no `config.ts` aggregate. */
538
+ const strictTypeInputFrom = (aggregateFiles) => {
539
+ const empty = {
540
+ packageNames: [],
541
+ mvrPlaceholders: [],
542
+ mvrTypeTags: []
543
+ };
544
+ const configFile = aggregateFiles.find((f) => f.outputPath === CONFIG_BUCKET);
545
+ if (configFile === void 0) return empty;
546
+ const inner = configFile.exports[bucketStem(CONFIG_BUCKET)];
547
+ if (!isPlainObject(inner)) return empty;
548
+ const packagesNode = inner["packages"];
549
+ const mvrNode = isPlainObject(inner["mvrOverrides"]) ? inner["mvrOverrides"] : {};
550
+ const mvrPackagesNode = mvrNode["packages"];
551
+ const mvrTypesNode = mvrNode["types"];
552
+ return {
553
+ packageNames: isPlainObject(packagesNode) ? Object.keys(packagesNode).sort() : [],
554
+ mvrPlaceholders: isPlainObject(mvrPackagesNode) ? Object.keys(mvrPackagesNode).sort() : [],
555
+ mvrTypeTags: isPlainObject(mvrTypesNode) ? Object.keys(mvrTypesNode).sort() : []
556
+ };
557
+ };
558
+ /**
559
+ * Derive the structured SERVICE-VALUE channel `values[namespace][key] = <tsType>`
560
+ * for the strict `deployment.ts` — every generic (non-sugar) RESOLVED
561
+ * config-binding the contributions declare. Computed from the SAME contribution
562
+ * decls the cycle emits: a binding lands here exactly when it would land in the
563
+ * live deployment's generic `values` channel (a `resolved` binding with NO
564
+ * `sugar`), so the required `AppNetworkDeployment.values` shape matches what a
565
+ * resolved deployment actually carries. The tsType is read off each contribution's
566
+ * `aggregate.valueTypes` (added in config-bindings); a binding with no declared
567
+ * tsType contributes `'unknown'`. Empty for a service-less app.
568
+ */
569
+ const serviceValuesFrom = (contributions) => {
570
+ const out = {};
571
+ for (const decl of contributions) {
572
+ const valueTypes = decl.aggregate?.valueTypes;
573
+ if (valueTypes === void 0) continue;
574
+ for (const [ns, keys] of Object.entries(valueTypes)) {
575
+ const nsOut = out[ns] ??= {};
576
+ for (const [key, tsType] of Object.entries(keys)) nsOut[key] = tsType;
577
+ }
578
+ }
579
+ return out;
580
+ };
581
+ const EMPTY_DEPLOYMENT_USAGE = {
582
+ usesDep: false,
583
+ usesDeployment: false,
584
+ requireId: false,
585
+ requireValue: false,
586
+ optionalValue: false
587
+ };
588
+ const deploymentUsageEmpty = (u) => !u.usesDep && !u.usesDeployment && !u.requireId && !u.requireValue && !u.optionalValue;
589
+ /** Recursively scan an exports value's raw expressions, OR-ing in the
590
+ * deployment symbols each references. */
591
+ const scanDeploymentUsage = (value, acc) => {
410
592
  if (isRawExpr(value)) {
411
- for (const name of CONFIG_RUNTIME_RESOLVERS) if (value.expr.includes(`${name}(`)) found.add(name);
593
+ const e = value.expr;
594
+ if (/\bdep\b/.test(e)) acc.usesDep = true;
595
+ if (e.includes("__deployment")) acc.usesDeployment = true;
596
+ if (e.includes("requireId(")) acc.requireId = true;
597
+ if (e.includes("requireValue")) acc.requireValue = true;
598
+ if (e.includes("optionalValue(")) acc.optionalValue = true;
599
+ return;
600
+ }
601
+ if (isForNetworkBucket(value)) {
602
+ scanDeploymentUsage(value.inner, acc);
412
603
  return;
413
604
  }
414
605
  if (Array.isArray(value)) {
415
- for (const v of value) collectResolversInValue(v, found);
606
+ for (const v of value) scanDeploymentUsage(v, acc);
416
607
  return;
417
608
  }
418
- if (isPlainObject(value)) for (const v of Object.values(value)) collectResolversInValue(v, found);
609
+ if (isPlainObject(value)) for (const v of Object.values(value)) scanDeploymentUsage(v, acc);
610
+ };
611
+ /** True when any raw expression in the exports references the `NETWORK_NAMES`
612
+ * identifier (the strict `deployment.ts` tuple `config.ts` types against).
613
+ * Drives the `./deployment.js` import injection. */
614
+ const referencesNetworkNames = (value) => {
615
+ if (isRawExpr(value)) return /\bNETWORK_NAMES\b/.test(value.expr);
616
+ if (Array.isArray(value)) return value.some(referencesNetworkNames);
617
+ if (isPlainObject(value)) return Object.values(value).some(referencesNetworkNames);
618
+ return false;
619
+ };
620
+ /** The deployment symbols an aggregate's exports use (all-false when the
621
+ * aggregate carries no deployment expressions — pure literals). */
622
+ const deploymentUsageOf = (exports) => {
623
+ const acc = { ...EMPTY_DEPLOYMENT_USAGE };
624
+ for (const v of Object.values(exports)) scanDeploymentUsage(v, acc);
625
+ return acc;
419
626
  };
420
- /** The ordered set of config-runtime resolvers an aggregate's exports use
421
- * (empty when none the aggregate needs no resolver import). */
422
- const resolversUsedBy = (exports) => {
423
- const found = /* @__PURE__ */ new Set();
424
- for (const v of Object.values(exports)) collectResolversInValue(v, found);
425
- return CONFIG_RUNTIME_RESOLVERS.filter((name) => found.has(name));
627
+ /** The `./config-runtime.js` named imports the usage requires, in a stable
628
+ * order. Only symbols actually used are imported (oxlint flags unused). */
629
+ const deploymentImportsFor = (u) => {
630
+ const names = [];
631
+ if (u.usesDep || u.usesDeployment) names.push("loadDeployment");
632
+ if (u.requireId) names.push("requireId");
633
+ if (u.requireValue) names.push("requireValue");
634
+ if (u.optionalValue) names.push("optionalValue");
635
+ return names;
636
+ };
637
+ /** The module-level preamble lines the usage requires (`loadDeployment()`
638
+ * once, then the active-network `dep`). */
639
+ const deploymentPreambleFor = (u) => {
640
+ const lines = [];
641
+ if (u.usesDep || u.usesDeployment) lines.push("const __deployment = loadDeployment();");
642
+ if (u.usesDep) lines.push("const dep = __deployment.forNetwork(__deployment.defaultNetwork);");
643
+ return lines;
426
644
  };
427
645
  var CodegenOrchestratorService = class extends Context.Service()("@devstack/orchestrators/Codegen") {};
428
646
  /**
429
- * Slice the deep-merged `config.ts` aggregate bucket into the loadable
430
- * `IdConfig` interchange shape. The bucket is the live codegen
431
- * accumulation (sui `networks`, per-package `packages`/`objects`/
432
- * `mvrOverrides`, account `accounts`); this picks the id-bearing fields
433
- * the Vite plugin injects. Reads are defensive any missing slice
434
- * collapses to an empty record so a partial stack still writes a valid
435
- * (if sparse) id-config.
647
+ * Slice the deep-merged `config.ts` aggregate bucket into a single
648
+ * loadable `NetworkDeployment` (the LIVE LOCAL network unit). The bucket is
649
+ * the live codegen accumulation (sui `networks`, per-package `packages`/
650
+ * `objects`/`mvrOverrides`); this picks the id-bearing
651
+ * fields the Vite plugin injects and FLATTENS the chosen network's
652
+ * connection coordinates (rpc/chainId/faucet/graphql) inline. Reads are
653
+ * defensive any missing slice collapses to an empty record so a partial
654
+ * stack still writes a valid (if sparse) network deployment. Single-network
655
+ * only here: `assembleDeployment` keys the envelope under this unit's network.
656
+ * Per-network package ids for live networks come from the committed
657
+ * `deployments/<net>.ts` files merged into the envelope at app build/dev time.
436
658
  */
437
- const idConfigFromBucket = (bucket, network, values) => {
659
+ const deploymentFromBucket = (bucket, network, values) => {
438
660
  const asRecord = (v) => isPlainObject(v) ? v : {};
439
661
  const asString = (v) => typeof v === "string" ? v : void 0;
440
- const networks = {};
662
+ const conns = {};
441
663
  for (const [name, raw] of Object.entries(asRecord(bucket["networks"]))) {
442
664
  const entry = asRecord(raw);
443
665
  const rpc = asString(entry["rpc"]);
444
666
  if (rpc === void 0) continue;
445
- networks[name] = {
667
+ conns[name] = {
446
668
  rpc,
447
669
  ...asString(entry["chainId"]) !== void 0 ? { chainId: asString(entry["chainId"]) } : {},
448
670
  ...entry["faucet"] !== void 0 ? { faucet: asString(entry["faucet"]) ?? null } : {},
@@ -465,23 +687,28 @@ const idConfigFromBucket = (bucket, network, values) => {
465
687
  ...Object.keys(objects).length > 0 ? { objects } : {}
466
688
  };
467
689
  }
468
- const accounts = {};
469
- for (const [name, v] of Object.entries(asRecord(bucket["accounts"]))) {
470
- const address = asString(v) ?? asString(asRecord(v)["address"]);
471
- if (address !== void 0) accounts[name] = address;
472
- }
473
- const mvrOverrides = {};
474
- for (const [mvr, v] of Object.entries(asRecord(bucket["mvrOverrides"]))) {
690
+ const mvrPackages = {};
691
+ const mvrNode = asRecord(bucket["mvrOverrides"]);
692
+ for (const [mvr, v] of Object.entries(asRecord(mvrNode["packages"]))) {
475
693
  const s = asString(v);
476
- if (s !== void 0) mvrOverrides[mvr] = s;
694
+ if (s !== void 0) mvrPackages[mvr] = s;
477
695
  }
478
- const networkKeys = Object.keys(networks);
696
+ const mvrOverrides = {
697
+ packages: mvrPackages,
698
+ types: {}
699
+ };
700
+ const connKeys = Object.keys(conns);
479
701
  const bucketNetwork = asString(bucket["network"]);
702
+ const activeNetwork = bucketNetwork !== void 0 && connKeys.includes(bucketNetwork) ? bucketNetwork : connKeys.length === 1 ? connKeys[0] : bucketNetwork ?? network;
703
+ const conn = conns[activeNetwork] ?? { rpc: "" };
480
704
  return {
481
- network: bucketNetwork !== void 0 && networkKeys.includes(bucketNetwork) ? bucketNetwork : networkKeys.includes(network) ? network : networkKeys.length === 1 ? networkKeys[0] : bucketNetwork ?? network,
482
- networks,
705
+ network: activeNetwork,
706
+ rpc: conn.rpc,
707
+ ...conn.chainId !== void 0 ? { chainId: conn.chainId } : {},
708
+ ...conn.faucet !== void 0 ? { faucet: conn.faucet } : {},
709
+ ...conn.graphql !== void 0 ? { graphql: conn.graphql } : {},
710
+ local: true,
483
711
  packages,
484
- accounts,
485
712
  mvrOverrides,
486
713
  ...Object.keys(values).length > 0 ? { values } : {}
487
714
  };
@@ -502,7 +729,7 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
502
729
  yield* Ref.update(contributionsRef, (xs) => [...xs, entry]);
503
730
  yield* Effect.addFinalizer(() => Ref.update(contributionsRef, (xs) => xs.filter((e) => e.seq !== seq)));
504
731
  });
505
- const assembleIdConfig = (network) => Effect.gen(function* () {
732
+ const assembleDeployment = (network) => Effect.gen(function* () {
506
733
  const registered = (yield* Ref.get(contributionsRef)).map((e) => e.decl);
507
734
  const bucket = {};
508
735
  const accounts = {};
@@ -510,41 +737,28 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
510
737
  for (const decl of registered) {
511
738
  if (decl.aggregate === void 0) continue;
512
739
  if (decl.aggregate.idConfigValues !== void 0) deepMerge(values, decl.aggregate.idConfigValues);
513
- if (decl.aggregate.bucket === "config.ts") {
740
+ if (decl.aggregate.bucket === CONFIG_BUCKET) {
514
741
  const emission = yield* runEmitter(decl);
515
742
  const projected = decl.aggregate.project(emission.exports);
516
743
  if (projected !== null) deepMerge(bucket, projected);
517
- } else if (decl.aggregate.bucket === "accounts.ts") {
744
+ } else if (decl.aggregate.bucket === ACCOUNTS_BUCKET) {
518
745
  const emission = yield* runEmitter(decl);
519
746
  const projected = decl.aggregate.project(emission.exports);
520
747
  if (projected !== null) deepMerge(accounts, projected);
521
748
  }
522
749
  }
523
- bucket["accounts"] = accounts;
524
- return idConfigFromBucket(bucket, network, values);
525
- });
526
- const emitExtras = () => Effect.gen(function* () {
527
- const extras = (yield* Ref.get(contributionsRef)).map((e) => e.decl).filter(isExtrasDecl);
528
- if (extras.length === 0) return {
529
- filesWritten: [],
530
- filesUnchanged: [],
531
- filesChmod: [],
532
- bindings: null
750
+ const envelopeAccounts = {};
751
+ for (const [name, v] of Object.entries(accounts)) {
752
+ const address = typeof v === "string" ? v : isPlainObject(v) && typeof v["address"] === "string" ? v["address"] : void 0;
753
+ if (address !== void 0) envelopeAccounts[name] = address;
754
+ }
755
+ const unit = deploymentFromBucket(bucket, network, values);
756
+ const unitNetwork = unit.network ?? network;
757
+ return {
758
+ defaultNetwork: unitNetwork,
759
+ networks: { [unitNetwork]: unit },
760
+ accounts: envelopeAccounts
533
761
  };
534
- yield* validateUniqueness(extras);
535
- yield* validateAggregatePathAvailability(extras);
536
- const paths = yield* CodegenPathsService;
537
- return yield* Effect.scoped(Effect.gen(function* () {
538
- yield* acquireStackLock(paths.codegenLockFile, CODEGEN_CYCLE_LOCK_TIMEOUT_MS).pipe(Effect.mapError((cause) => new CodegenWriteFailed({
539
- outputPath: paths.codegenLockFile,
540
- stage: "write",
541
- cause
542
- })));
543
- return yield* runEmitCycleInner({
544
- contributions: extras,
545
- trackTree: false
546
- }, paths);
547
- }));
548
762
  });
549
763
  const emitBindings = (contributions) => Effect.gen(function* () {
550
764
  if (contributions.length === 0) return {
@@ -560,8 +774,7 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
560
774
  });
561
775
  return CodegenOrchestratorService.of({
562
776
  registerContribution,
563
- assembleIdConfig,
564
- emitExtras,
777
+ assembleDeployment,
565
778
  emitBindings
566
779
  });
567
780
  }));