@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
@@ -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,13 +274,15 @@ 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
- 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)];
251
- yield* writeGitignore({
252
- path: paths.gitignoreFile,
253
- sensitivePaths,
254
- parentMode: parentModeFor(paths.gitignoreFile),
255
- trackTree: input.trackTree === true
256
- });
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)];
279
+ yield* writeGitignore({
280
+ path: paths.gitignoreFile,
281
+ sensitivePaths,
282
+ parentMode: parentModeFor(paths.gitignoreFile),
283
+ trackTree: input.trackTree === true
284
+ });
285
+ }
257
286
  return {
258
287
  filesWritten,
259
288
  filesUnchanged,
@@ -297,19 +326,18 @@ const validateUniqueness = (decls) => Effect.gen(function* () {
297
326
  const byName = /* @__PURE__ */ new Map();
298
327
  for (const d of decls) {
299
328
  if (d.aggregateOnly !== true) {
300
- const pathKey = `${declLocation(d)} ${d.outputPath}`;
301
- const ps = byPath.get(pathKey) ?? [];
329
+ const ps = byPath.get(d.outputPath) ?? [];
302
330
  ps.push(d.emitterName);
303
- byPath.set(pathKey, ps);
331
+ byPath.set(d.outputPath, ps);
304
332
  }
305
333
  if (d.allowEmitterNameRepetition === true) continue;
306
334
  const ns = byName.get(d.emitterName) ?? [];
307
335
  ns.push(d.outputPath);
308
336
  byName.set(d.emitterName, ns);
309
337
  }
310
- 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({
311
339
  kind: "duplicate",
312
- outputPath: pathKey.slice(pathKey.indexOf(" ") + 1),
340
+ outputPath,
313
341
  emitters
314
342
  }));
315
343
  for (const [name, outputPaths] of byName) if (outputPaths.length > 1) return yield* Effect.fail(new CodegenEmitterCollision({
@@ -324,14 +352,10 @@ const validateUniqueness = (decls) => Effect.gen(function* () {
324
352
  * it does not enumerate or recognize plugin identities here.
325
353
  */
326
354
  const validateAggregatePathAvailability = (decls) => Effect.gen(function* () {
327
- const aggregatePaths = /* @__PURE__ */ new Map();
328
- for (const decl of decls) if (decl.aggregate !== void 0) {
329
- const location = decl.aggregate.outputLocation ?? "generated";
330
- aggregatePaths.set(`${location} ${decl.aggregate.bucket}`, decl.aggregate.bucket);
331
- }
332
- for (const [key, bucket] of aggregatePaths) {
333
- const location = key.slice(0, key.indexOf(" "));
334
- 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);
335
359
  if (colliding.length > 0) return yield* Effect.fail(new CodegenPathConflict({
336
360
  kind: "duplicate",
337
361
  outputPath: bucket,
@@ -367,8 +391,7 @@ const deepMerge = (target, source) => {
367
391
  * orchestrator picks the export key from the bucket filename; the
368
392
  * stem itself is not a plugin identifier — it is the filename
369
393
  * without the `.ts` extension, derived mechanically. The bucket's
370
- * `location`/`sensitive` (from the first contributing decl) drive
371
- * which tree the file lands in and its mode.
394
+ * `sensitive` flag (from the first contributing decl) drives its mode.
372
395
  */
373
396
  const buildAggregateFiles = (buckets, meta) => {
374
397
  const files = [];
@@ -377,7 +400,6 @@ const buildAggregateFiles = (buckets, meta) => {
377
400
  if (Object.keys(contents).length === 0) continue;
378
401
  const stem = bucketStem(bucket);
379
402
  const bucketMeta = meta.get(bucket) ?? {
380
- location: "generated",
381
403
  sensitive: false,
382
404
  establishedBy: `aggregate/${stem}`
383
405
  };
@@ -385,62 +407,264 @@ const buildAggregateFiles = (buckets, meta) => {
385
407
  emitterName: `aggregate/${stem}`,
386
408
  outputPath: bucket,
387
409
  exports: { [stem]: contents },
388
- location: bucketMeta.location,
389
410
  sensitive: bucketMeta.sensitive
390
411
  });
391
412
  }
392
413
  return files;
393
414
  };
394
415
  const bucketStem = (bucket) => bucket.replace(/\.ts$/, "").replace(/^.*\//, "");
395
- /** The config-runtime resolver names a committed `config.ts` aggregate may
396
- * reference as raw expressions. Each is imported from `./config-runtime.js`
397
- * only when the aggregate actually calls it (oxlint flags unused imports). */
398
- const CONFIG_RUNTIME_RESOLVERS = [
399
- "resolveId",
400
- "resolveNetwork",
401
- "resolveNetworks",
402
- "resolveValue"
403
- ];
404
- /** Recursively collect which `config-runtime.ts` resolvers an exports map
405
- * references via raw expressions — i.e. the committed `config.ts` needs each
406
- * imported + the fixed `config-runtime.ts` emitted alongside it. */
407
- 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) => {
408
592
  if (isRawExpr(value)) {
409
- 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);
410
603
  return;
411
604
  }
412
605
  if (Array.isArray(value)) {
413
- for (const v of value) collectResolversInValue(v, found);
606
+ for (const v of value) scanDeploymentUsage(v, acc);
414
607
  return;
415
608
  }
416
- 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;
417
626
  };
418
- /** The ordered set of config-runtime resolvers an aggregate's exports use
419
- * (empty when none the aggregate needs no resolver import). */
420
- const resolversUsedBy = (exports) => {
421
- const found = /* @__PURE__ */ new Set();
422
- for (const v of Object.values(exports)) collectResolversInValue(v, found);
423
- 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;
424
644
  };
425
645
  var CodegenOrchestratorService = class extends Context.Service()("@devstack/orchestrators/Codegen") {};
426
646
  /**
427
- * Slice the deep-merged `config.ts` aggregate bucket into the loadable
428
- * `IdConfig` interchange shape. The bucket is the live codegen
429
- * accumulation (sui `networks`, per-package `packages`/`objects`/
430
- * `mvrOverrides`, account `accounts`); this picks the id-bearing fields
431
- * the Vite plugin injects. Reads are defensive any missing slice
432
- * collapses to an empty record so a partial stack still writes a valid
433
- * (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.
434
658
  */
435
- const idConfigFromBucket = (bucket, network, values) => {
659
+ const deploymentFromBucket = (bucket, network, values) => {
436
660
  const asRecord = (v) => isPlainObject(v) ? v : {};
437
661
  const asString = (v) => typeof v === "string" ? v : void 0;
438
- const networks = {};
662
+ const conns = {};
439
663
  for (const [name, raw] of Object.entries(asRecord(bucket["networks"]))) {
440
664
  const entry = asRecord(raw);
441
665
  const rpc = asString(entry["rpc"]);
442
666
  if (rpc === void 0) continue;
443
- networks[name] = {
667
+ conns[name] = {
444
668
  rpc,
445
669
  ...asString(entry["chainId"]) !== void 0 ? { chainId: asString(entry["chainId"]) } : {},
446
670
  ...entry["faucet"] !== void 0 ? { faucet: asString(entry["faucet"]) ?? null } : {},
@@ -463,23 +687,28 @@ const idConfigFromBucket = (bucket, network, values) => {
463
687
  ...Object.keys(objects).length > 0 ? { objects } : {}
464
688
  };
465
689
  }
466
- const accounts = {};
467
- for (const [name, v] of Object.entries(asRecord(bucket["accounts"]))) {
468
- const address = asString(v) ?? asString(asRecord(v)["address"]);
469
- if (address !== void 0) accounts[name] = address;
470
- }
471
- const mvrOverrides = {};
472
- 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"]))) {
473
693
  const s = asString(v);
474
- if (s !== void 0) mvrOverrides[mvr] = s;
694
+ if (s !== void 0) mvrPackages[mvr] = s;
475
695
  }
476
- const networkKeys = Object.keys(networks);
696
+ const mvrOverrides = {
697
+ packages: mvrPackages,
698
+ types: {}
699
+ };
700
+ const connKeys = Object.keys(conns);
477
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: "" };
478
704
  return {
479
- network: bucketNetwork !== void 0 && networkKeys.includes(bucketNetwork) ? bucketNetwork : networkKeys.includes(network) ? network : networkKeys.length === 1 ? networkKeys[0] : bucketNetwork ?? network,
480
- 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,
481
711
  packages,
482
- accounts,
483
712
  mvrOverrides,
484
713
  ...Object.keys(values).length > 0 ? { values } : {}
485
714
  };
@@ -500,7 +729,7 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
500
729
  yield* Ref.update(contributionsRef, (xs) => [...xs, entry]);
501
730
  yield* Effect.addFinalizer(() => Ref.update(contributionsRef, (xs) => xs.filter((e) => e.seq !== seq)));
502
731
  });
503
- const assembleIdConfig = (network) => Effect.gen(function* () {
732
+ const assembleDeployment = (network) => Effect.gen(function* () {
504
733
  const registered = (yield* Ref.get(contributionsRef)).map((e) => e.decl);
505
734
  const bucket = {};
506
735
  const accounts = {};
@@ -508,46 +737,45 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
508
737
  for (const decl of registered) {
509
738
  if (decl.aggregate === void 0) continue;
510
739
  if (decl.aggregate.idConfigValues !== void 0) deepMerge(values, decl.aggregate.idConfigValues);
511
- if (decl.aggregate.bucket === "config.ts") {
740
+ if (decl.aggregate.bucket === CONFIG_BUCKET) {
512
741
  const emission = yield* runEmitter(decl);
513
742
  const projected = decl.aggregate.project(emission.exports);
514
743
  if (projected !== null) deepMerge(bucket, projected);
515
- } else if (decl.aggregate.bucket === "accounts.ts") {
744
+ } else if (decl.aggregate.bucket === ACCOUNTS_BUCKET) {
516
745
  const emission = yield* runEmitter(decl);
517
746
  const projected = decl.aggregate.project(emission.exports);
518
747
  if (projected !== null) deepMerge(accounts, projected);
519
748
  }
520
749
  }
521
- bucket["accounts"] = accounts;
522
- return idConfigFromBucket(bucket, network, values);
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
761
+ };
523
762
  });
524
- const emitExtras = () => Effect.gen(function* () {
525
- const extras = (yield* Ref.get(contributionsRef)).map((e) => e.decl).filter(isExtrasDecl);
526
- if (extras.length === 0) return {
763
+ const emitBindings = (contributions) => Effect.gen(function* () {
764
+ if (contributions.length === 0) return {
527
765
  filesWritten: [],
528
766
  filesUnchanged: [],
529
767
  filesChmod: [],
530
768
  bindings: null
531
769
  };
532
- yield* validateUniqueness(extras);
533
- yield* validateAggregatePathAvailability(extras);
534
- const paths = yield* CodegenPathsService;
535
- return yield* Effect.scoped(Effect.gen(function* () {
536
- yield* acquireStackLock(paths.codegenLockFile, CODEGEN_CYCLE_LOCK_TIMEOUT_MS).pipe(Effect.mapError((cause) => new CodegenWriteFailed({
537
- outputPath: paths.codegenLockFile,
538
- stage: "write",
539
- cause
540
- })));
541
- return yield* runEmitCycleInner({
542
- contributions: extras,
543
- trackTree: false
544
- }, paths);
545
- }));
770
+ return yield* runEmitCycle({
771
+ contributions,
772
+ trackTree: true
773
+ });
546
774
  });
547
775
  return CodegenOrchestratorService.of({
548
776
  registerContribution,
549
- assembleIdConfig,
550
- emitExtras
777
+ assembleDeployment,
778
+ emitBindings
551
779
  });
552
780
  }));
553
781
  //#endregion