@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
@@ -1,22 +1,17 @@
1
- import { decodeIdConfig } from "../../orchestrators/codegen/id-config.mjs";
2
- import { resolveNetworkOptions } from "../../orchestrators/network-options.mjs";
1
+ import { decodeDeployment, decodeNetworkDeployment } from "../../orchestrators/codegen/deployment.mjs";
3
2
  import { resolveDiscoveryEnv } from "../runtime/resolve-discovery-env.mjs";
4
3
  import { discoverManifestPath } from "../runtime/discover.mjs";
5
4
  import "../runtime/index.mjs";
6
- import { existsSync, readFileSync } from "node:fs";
7
- import { isAbsolute, resolve } from "node:path";
5
+ import { resolveNetworkOptions } from "../../orchestrators/network-options.mjs";
6
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
7
+ import { dirname, resolve } from "node:path";
8
+ import { pathToFileURL } from "node:url";
8
9
  //#region src/build-integrations/vite/index.ts
9
10
  /** Default import-alias prefix. Customizable via `options.alias` (some
10
11
  * apps prefer `@gen`, `~generated`, …). The app MUST use the SAME
11
12
  * prefix in three derivable places: this plugin option, the
12
13
  * `tsconfig` `paths` entry, and its import specifiers. */
13
14
  const DEFAULT_GENERATED_ALIAS = "@generated";
14
- /** Default dev-extras import-alias prefix. Resolves the PRIMARY stack's
15
- * `.devstack/stacks/<stack>/generated-extras` tree (dev-only / secret
16
- * artifacts — `accounts.ts`, `dev-wallet.ts`). Mirror the `@generated`
17
- * three-place discipline: this option, the `tsconfig` `paths` entry,
18
- * and the import specifiers. */
19
- const DEFAULT_DEV_EXTRAS_ALIAS = "@devstack-dev";
20
15
  /** The committed generated-bindings subpath, relative to the Vite root.
21
16
  * The single source of bindings — written by `devstack codegen` — that
22
17
  * `@generated` always resolves to (absent the `options.generatedDir`
@@ -32,7 +27,7 @@ const RESOLVED_VIRTUAL_DEV_WALLET_ID = "\0virtual:devstack-dev-wallet";
32
27
  * misroutes to the SPA fallback). Used for the injected `<script src>`. */
33
28
  const VIRTUAL_DEV_WALLET_SCRIPT_SRC = `/@id/__x00__${VIRTUAL_DEV_WALLET_ID}`;
34
29
  /** Best-effort, SYNC read of a string-valued field at `dottedPath` (e.g.
35
- * `'codegen.idsFile'`, `'identity.network'`) from the active stack's
30
+ * `'codegen.deploymentFile'`, `'identity.network'`) from the active stack's
36
31
  * manifest. Walks each path segment as a nested object, returning the leaf
37
32
  * value, or `null` on ANY miss (absent / partially-written / version-
38
33
  * mismatched manifest, a non-object hop, a missing or non-string/empty
@@ -41,9 +36,9 @@ const VIRTUAL_DEV_WALLET_SCRIPT_SRC = `/@id/__x00__${VIRTUAL_DEV_WALLET_ID}`;
41
36
  * and throws on a version mismatch) so an out-of-date or partially-written
42
37
  * manifest degrades gracefully instead of crashing the dev server. Never
43
38
  * throws — the single discover→parse→guard→degrade-to-null reader every
44
- * manifest field above (`codegen.idsFile`, `codegen.extrasDir`,
45
- * `identity.network`) routes through. */
46
- const readManifestField = (env, cwd, dottedPath) => {
39
+ * manifest field above (`codegen.deploymentFile`, `identity.network`)
40
+ * routes through. */
41
+ const readManifestObject = (env, cwd) => {
47
42
  try {
48
43
  const { stack, stateDir } = resolveDiscoveryEnv(env, { cwd });
49
44
  const manifestPath = discoverManifestPath({
@@ -53,49 +48,138 @@ const readManifestField = (env, cwd, dottedPath) => {
53
48
  cwd
54
49
  });
55
50
  if (manifestPath === void 0 || !existsSync(manifestPath)) return null;
56
- let node = JSON.parse(readFileSync(manifestPath, "utf8"));
57
- for (const segment of dottedPath.split(".")) {
58
- if (typeof node !== "object" || node === null) return null;
59
- node = node[segment];
60
- }
61
- return typeof node === "string" && node.length > 0 ? node : null;
51
+ return JSON.parse(readFileSync(manifestPath, "utf8"));
62
52
  } catch {
63
53
  return null;
64
54
  }
65
55
  };
66
- /** The gitignored `devstack-ids.json` path the boot wrote for the active
67
- * stack (`codegen.idsFile`), or `null` on any miss. */
68
- const readIdsFileFromManifest = (env, cwd) => readManifestField(env, cwd, "codegen.idsFile");
69
- /** SYNC read + schema-decode of an id-config FILE. The MISSING-file case
70
- * (absent path, no file on disk) collapses to `null` so the Vite config
56
+ /** Walk `dottedPath` over an already-parsed manifest object, returning the
57
+ * non-empty string leaf or `null` on ANY miss (non-object hop, missing /
58
+ * non-string / empty leaf). Lets one parsed manifest serve several field
59
+ * reads without re-parsing. */
60
+ const pickManifestString = (manifest, dottedPath) => {
61
+ let node = manifest;
62
+ for (const segment of dottedPath.split(".")) {
63
+ if (typeof node !== "object" || node === null) return null;
64
+ node = node[segment];
65
+ }
66
+ return typeof node === "string" && node.length > 0 ? node : null;
67
+ };
68
+ const readManifestField = (env, cwd, dottedPath) => pickManifestString(readManifestObject(env, cwd), dottedPath);
69
+ /** The gitignored `deployment.json` path the boot wrote for the active
70
+ * stack (`codegen.deploymentFile`), or `null` on any miss. */
71
+ const readIdsFileFromManifest = (env, cwd) => readManifestField(env, cwd, "codegen.deploymentFile");
72
+ /** SYNC read + schema-decode of a deployment ENVELOPE file. The MISSING-file
73
+ * case (absent path, no file on disk) collapses to `null` so the Vite config
71
74
  * load degrades gracefully when no stack has booted / no committed file is
72
- * wired. A PRESENT-but-malformed file is NOT swallowed: it flows through
73
- * the shared {@link decodeIdConfig}, which THROWS on bad JSON or a shape
74
- * that violates `IdConfigSchema` — surfacing a genuinely broken committed
75
- * id-config at config-load instead of silently injecting `null`. */
76
- const readIdConfigFile = (idsFile) => {
77
- if (idsFile === null || !existsSync(idsFile)) return null;
78
- return decodeIdConfig(readFileSync(idsFile, "utf8"));
75
+ * wired. A PRESENT-but-malformed file is NOT swallowed: it flows through the
76
+ * shared {@link decodeDeployment}, which THROWS on bad JSON or a shape that
77
+ * violates `DevstackDeploymentSchema` — surfacing a genuinely broken
78
+ * deployment at config-load instead of silently injecting `null`. */
79
+ const readDeploymentFile = (file) => {
80
+ if (file === null || !existsSync(file)) return null;
81
+ return decodeDeployment(readFileSync(file, "utf8"));
82
+ };
83
+ /** The LIVE local-stack deployment envelope for the active stack — the
84
+ * `deployment.json` boot wrote (via the manifest `codegen.deploymentFile`),
85
+ * or `null` on any miss. Read fresh so a republish reaches the app. */
86
+ const readLiveEnvelope = (env, root) => readDeploymentFile(readIdsFileFromManifest(env, root));
87
+ /** Resolve + validate the committed per-network deployments — the
88
+ * `deployments` option's thunks, each `() => Promise<{ deployment }>`. Each
89
+ * `deployment` is validated against `NetworkDeploymentSchema` (loud-fail on a
90
+ * malformed committed file) and stamped `{ network: <key>, local: false }` so
91
+ * the envelope key is authoritative and the deploy filter treats it as a real
92
+ * (non-local) network. Empty when no `deployments` are supplied. */
93
+ const resolveCommittedNetworks = async (deployments) => {
94
+ const committed = {};
95
+ for (const [net, thunk] of Object.entries(deployments)) committed[net] = {
96
+ ...decodeNetworkDeployment((await thunk()).deployment, `deployments['${net}']`),
97
+ network: net,
98
+ local: false
99
+ };
100
+ return committed;
79
101
  };
80
- /** Resolve the on-chain ids to inject as the `__DEVSTACK_IDS__` global —
81
- * ALWAYS from an id-config FILE (same schema in dev and prod), never a
82
- * JSON env blob. Dev (`serve`): the live `devstack-ids.json` (via the
83
- * manifest `codegen.idsFile`). Prod (`build`): the committed known-
84
- * deployment file — the plugin `ids` option, else the `DEVSTACK_IDS_FILE`
85
- * env (a PATH pointer, not data). Neither ⇒ `null`, so the generated
86
- * resolver throws loudly at id-access time. */
87
- const resolveInjectedIds = (env, root, command, idsOption) => {
102
+ /** Auto-discover the committed per-network deployment thunks by globbing
103
+ * `<root>/deployments/*.ts` (D7 "just drop a file" UX). Each filename
104
+ * (sans `.ts`) becomes a live network name keyed to a thunk that
105
+ * dynamically `import()`s the absolute file path and reads its `deployment`
106
+ * export (the `dump-deployment`-emitted / hand-written
107
+ * `export const deployment = {…} satisfies AppNetworkDeployment`). Returns
108
+ * `{}` when there is no `deployments/` dir (a clean clone / template — a
109
+ * pure types-only `deployment.ts` with an empty `ProvidedDeployments`). The
110
+ * explicit `deployments` option overrides this entirely (custom dir/paths).
111
+ * File CONTENTS are not read here — only the import is wired; ids load when
112
+ * Vite transforms the thunk at build/serve. */
113
+ const autoDiscoverDeployments = (root) => {
114
+ const deploymentsDir = resolve(root, "deployments");
115
+ if (!existsSync(deploymentsDir)) return {};
116
+ const thunks = {};
117
+ let files;
118
+ try {
119
+ files = readdirSync(deploymentsDir);
120
+ } catch {
121
+ return {};
122
+ }
123
+ for (const file of files) {
124
+ if (!file.endsWith(".ts") || file.endsWith(".d.ts")) continue;
125
+ const net = file.slice(0, -3);
126
+ if (net.length === 0) continue;
127
+ const abs = resolve(deploymentsDir, file);
128
+ thunks[net] = () => import(
129
+ /* @vite-ignore */
130
+ pathToFileURL(abs).href
131
+ );
132
+ }
133
+ return thunks;
134
+ };
135
+ /** The committed per-network deployments to merge — the explicit
136
+ * `deployments` option when supplied, else auto-discovery of
137
+ * `<root>/deployments/*.ts` (D7). */
138
+ const resolveDeploymentThunks = (options, root) => options.deployments !== void 0 ? { ...options.deployments } : autoDiscoverDeployments(root);
139
+ /** The first key of a record, or `undefined` when empty. */
140
+ const firstKey = (record) => Object.keys(record)[0];
141
+ /** Merge the committed + live deployments into the envelope to inject as
142
+ * `__DEVSTACK_DEPLOYMENT__`.
143
+ * - `command === 'build'` (DEPLOY): the committed, NON-local networks only —
144
+ * the live local network is dropped. Empty ⇒ `null` (the generated
145
+ * resolver throws loudly at access time).
146
+ * - dev `serve` (and config-load default): the committed networks OVERLAID
147
+ * with the live local network(s), the live default winning. No live
148
+ * envelope ⇒ committed only (default = `defaultNetwork` option / first
149
+ * committed key).
150
+ * The live envelope's entries are forced `local: true` (they ARE the running
151
+ * local stack) so a later `build` would drop them. */
152
+ const mergeDeployment = (command, committed, live, defaultNetworkOption) => {
88
153
  if (command === "build") {
89
- const pointer = idsOption ?? env["DEVSTACK_IDS_FILE"];
90
- if (pointer === void 0 || pointer.length === 0) return null;
91
- return readIdConfigFile(isAbsolute(pointer) ? pointer : resolve(root, pointer));
154
+ if (Object.keys(committed).length === 0) return null;
155
+ const fallback = firstKey(committed);
156
+ return {
157
+ defaultNetwork: defaultNetworkOption !== void 0 && committed[defaultNetworkOption] !== void 0 ? defaultNetworkOption : fallback,
158
+ networks: committed,
159
+ accounts: {}
160
+ };
161
+ }
162
+ const networks = { ...committed };
163
+ if (live !== null) {
164
+ for (const [net, dep] of Object.entries(live.networks)) networks[net] = {
165
+ ...dep,
166
+ network: net,
167
+ local: true
168
+ };
169
+ return {
170
+ defaultNetwork: live.defaultNetwork,
171
+ networks,
172
+ accounts: live.accounts ?? {}
173
+ };
92
174
  }
93
- return readIdConfigFile(readIdsFileFromManifest(env, root));
175
+ const fallback = firstKey(networks);
176
+ if (fallback === void 0) return null;
177
+ return {
178
+ defaultNetwork: defaultNetworkOption !== void 0 && networks[defaultNetworkOption] !== void 0 ? defaultNetworkOption : fallback,
179
+ networks,
180
+ accounts: {}
181
+ };
94
182
  };
95
- /** The manifest-recorded dev-extras tree (`codegen.extrasDir`) the
96
- * `@devstack-dev` alias points at for the active stack, or `null` on any
97
- * miss. */
98
- const readExtrasDirFromManifest = (env, cwd) => readManifestField(env, cwd, "codegen.extrasDir");
99
183
  /**
100
184
  * Build the devstack Vite plugin that aliases `options.alias`
101
185
  * (default `@generated`) at the committed `<root>/src/generated` tree.
@@ -106,34 +190,53 @@ const readExtrasDirFromManifest = (env, cwd) => readManifestField(env, cwd, "cod
106
190
  * // or devstackVitePlugin({ alias: '@gen' })
107
191
  *
108
192
  * The plugin's `config` hook merges `resolve.alias[<prefix>] = <dir>`
109
- * into the user config (Vite deep-merges the returned partial). Sync;
110
- * reads `process.env` + the manifest (for `__DEVSTACK_IDS__` / the
111
- * `@devstack-dev` extras dir) once at config-load.
193
+ * into the user config (Vite deep-merges the returned partial). Async
194
+ * (it awaits the committed `deployments` thunks); reads `process.env` +
195
+ * the manifest (for `__DEVSTACK_DEPLOYMENT__`) once at config-load.
112
196
  */
113
- /** Derive the cold-start fallback dev-extras dir
114
- * (`<root>/.devstack/stacks/<stack>/generated-extras`) for the active
115
- * stack used when no manifest / `codegen.extrasDir` is on disk yet.
116
- * Mirrors `output-location.ts`'s `extrasDirFor`. Best-effort: a
117
- * discovery failure collapses to the `default` stack name. */
118
- const fallbackExtrasDir = (env, root) => {
119
- let stack = "default";
197
+ /** The on-disk dev-wallet pairing-token for the active stack, given the
198
+ * already-resolved `deploymentFile` path (the manifest's
199
+ * `codegen.deploymentFile`). The token lives in a `0o600` side-channel file
200
+ * (`<stackRoot>/wallet/token`, written by `pairing.ts`), NEVER in the
201
+ * world-readable `deployment.json`. The boot writes `deployment.json` into the
202
+ * SAME `<stackRoot>`, so the token sits at `<dirname(deploymentFile)>/wallet/
203
+ * token`. Read in Node by the `load` hook (which runs server-side) so the
204
+ * secret stays off the manifest/deployment surface. Returns `null` on any
205
+ * miss (including a `null` deployment file). */
206
+ const readDevWalletToken = (deploymentFile) => {
207
+ if (deploymentFile === null) return null;
208
+ const tokenFile = resolve(dirname(deploymentFile), "wallet", "token");
120
209
  try {
121
- stack = resolveDiscoveryEnv(env, { cwd: root }).stack;
122
- } catch {}
123
- return resolve(root, ".devstack", "stacks", stack, "generated-extras");
124
- };
125
- /** Resolve the dev-extras dir for the active stack (shared by the alias
126
- * config and the dev-wallet virtual module). Explicit option wins, else
127
- * manifest `codegen.extrasDir`, else the derived cold-start path. */
128
- const resolveExtrasDir = (options, root, env) => {
129
- const explicitExtras = options.extrasDir;
130
- return explicitExtras !== void 0 ? resolve(root, explicitExtras) : readExtrasDirFromManifest(env, root) ?? fallbackExtrasDir(env, root);
210
+ if (!existsSync(tokenFile)) return null;
211
+ const raw = readFileSync(tokenFile, "utf8").trim();
212
+ return /^[0-9a-f]{32}$/.test(raw) ? raw : null;
213
+ } catch {
214
+ return null;
215
+ }
131
216
  };
217
+ /** Escape a `JSON.stringify` result for safe embedding in an inline
218
+ * `<script>` element's text. Unlike an external file, inline-script text is
219
+ * parsed by the HTML tokenizer first, so a raw `<\/script>` (or `<!--`) inside
220
+ * any string value would terminate the tag early — and a lone `<` is enough to
221
+ * matter. We escape `<` / `>` / `&` to their `\uXXXX` JS-string forms (valid
222
+ * inside JSON-as-JS, and inert to the HTML tokenizer) and the U+2028/U+2029
223
+ * line separators (legal in JSON strings but illegal as raw JS line
224
+ * terminators in older engines). Used ONLY on the inline-script injection path
225
+ * — the `define` build path embeds into a JS module, not HTML, so it needs no
226
+ * such escaping. */
227
+ const escapeForInlineScript = (json) => json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/[\u2028\u2029]/g, (ch) => "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0"));
228
+ /** A boolean env flag is truthy when set to `'1'` or `'true'`
229
+ * (case-insensitive). Shared by the auto-approve + e2e env readers. */
230
+ const isTruthyEnvFlag = (raw) => raw === "1" || raw?.toLowerCase() === "true";
132
231
  /** Read the `DEVSTACK_AUTO_APPROVE` env (`'1'`/`'true'`, case-insensitive). */
133
- const autoApproveFromEnv = (env) => {
134
- const raw = env["DEVSTACK_AUTO_APPROVE"];
135
- return raw === "1" || raw?.toLowerCase() === "true";
136
- };
232
+ const autoApproveFromEnv = (env) => isTruthyEnvFlag(env["DEVSTACK_AUTO_APPROVE"]);
233
+ /** True under a Playwright e2e run (`DEVSTACK_E2E` set to `'1'`/`'true'`,
234
+ * case-insensitive). DEDICATED signal distinct from `DEVSTACK_AUTO_APPROVE`
235
+ * — driving the injected `__DEVSTACK_E2E__` global. Gates dApp Kit's
236
+ * `autoConnect` ON only under e2e, so a normal `pnpm dev` serve exercises the
237
+ * real connect UX. A prod `vite build` never sets the env ⇒ injects `false`
238
+ * (tree-shakeable). */
239
+ const e2eFromEnv = (env) => isTruthyEnvFlag(env["DEVSTACK_E2E"]);
137
240
  /** Lit packages deduped to a single instance. The injected dev-wallet UI and
138
241
  * the app's dapp-kit UI are both Lit-based; if Vite loads two Lit copies they
139
242
  * register custom elements in separate realms, and the second realm's element
@@ -146,6 +249,19 @@ const LIT_DEDUPE = [
146
249
  "lit-element",
147
250
  "@lit/reactive-element"
148
251
  ];
252
+ /** Filter {@link LIT_DEDUPE} to the packages actually installed at the app
253
+ * root (`<root>/node_modules/<pkg>`). `resolve.dedupe` forces Vite to
254
+ * resolve each listed package from the ROOT copy — but under pnpm's strict
255
+ * layout a package is only surfaced at the root when the app declares it as
256
+ * a direct dependency. Listing a package that is merely a phantom
257
+ * (transitive-only, reachable solely under `@mysten/dapp-kit-core`'s nested
258
+ * store dir) makes Vite's resolver look for a root copy that does not exist
259
+ * and FAIL the production build with `Rollup failed to resolve import
260
+ * "lit"`. So we dedupe only what the app truly hoists: the `app` template
261
+ * declares `lit` (all dapp-kit-core Lit usage routes through the `lit`
262
+ * meta-package, so one `lit` ⇒ one nested `@lit/reactive-element`); the
263
+ * sub-packages stay phantom and are correctly dropped here. */
264
+ const resolvableLitDedupe = (root) => LIT_DEDUPE.filter((pkg) => existsSync(resolve(root, "node_modules", ...pkg.split("/"))));
149
265
  /** The dev-wallet entry points the injected virtual module imports. They are
150
266
  * reached only through the `<script>` this plugin adds in `transformIndexHtml`,
151
267
  * so Vite's initial dep scan never sees them and re-optimizes mid-session the
@@ -164,33 +280,47 @@ const DEV_WALLET_OPTIMIZE_ENTRIES = ["@mysten-incubation/dev-wallet/inject", "@m
164
280
  const devWalletInstalled = (root) => existsSync(resolve(root, "node_modules", "@mysten-incubation", "dev-wallet", "package.json"));
165
281
  const devstackVitePlugin = (options = {}) => {
166
282
  const alias = options.alias ?? "@generated";
167
- const devExtrasAlias = options.devExtrasAlias ?? "@devstack-dev";
168
283
  const injectDevWallet = options.injectDevWallet ?? true;
169
284
  let resolvedRoot = process.cwd();
170
- let resolvedExtrasDir = null;
171
285
  let isServe = false;
286
+ let devWalletPresent = false;
287
+ let resolvedCommittedNetworks = {};
288
+ let liveEnvelopeFresh = false;
289
+ let liveEnvelopeCache = null;
290
+ const readLiveEnvelopeCached = (env) => {
291
+ if (liveEnvelopeFresh) return liveEnvelopeCache;
292
+ const live = readLiveEnvelope(env, resolvedRoot);
293
+ if (live !== null) {
294
+ liveEnvelopeCache = live;
295
+ liveEnvelopeFresh = true;
296
+ } else liveEnvelopeCache = null;
297
+ return live;
298
+ };
172
299
  return {
173
300
  name: "devstack:generated-alias",
174
- config: (config, configEnv) => {
301
+ config: async (config, configEnv) => {
175
302
  const root = config.root ?? process.cwd();
176
303
  resolvedRoot = root;
177
304
  const env = process.env;
178
305
  const command = configEnv?.command ?? config.command ?? "build";
179
306
  const explicit = options.generatedDir;
180
307
  const generatedDir = explicit !== void 0 ? resolve(root, explicit) : resolve(root, GENERATED_SUBPATH);
181
- const extrasDir = resolveExtrasDir(options, root, env);
182
- resolvedExtrasDir = extrasDir;
183
- const includeDevWallet = injectDevWallet && devWalletInstalled(root);
184
- const injectedIds = resolveInjectedIds(env, root, command, options.ids);
308
+ devWalletPresent = devWalletInstalled(root);
309
+ const includeDevWallet = injectDevWallet && devWalletPresent;
310
+ resolvedCommittedNetworks = await resolveCommittedNetworks(resolveDeploymentThunks(options, root));
311
+ const injectedLive = command === "build" ? null : readLiveEnvelope(env, root);
312
+ const injectedDeployment = mergeDeployment(command, resolvedCommittedNetworks, injectedLive, options.defaultNetwork);
313
+ const isVitest = env["VITEST"] !== void 0;
314
+ const deploymentDefine = command === "serve" && !isVitest ? "globalThis.__DEVSTACK_DEPLOYMENT_LIVE__" : JSON.stringify(injectedDeployment ?? null);
185
315
  return {
186
316
  resolve: {
187
- alias: {
188
- [alias]: generatedDir,
189
- [devExtrasAlias]: extrasDir
190
- },
191
- dedupe: [...LIT_DEDUPE]
317
+ alias: { [alias]: generatedDir },
318
+ dedupe: resolvableLitDedupe(root)
319
+ },
320
+ define: {
321
+ __DEVSTACK_DEPLOYMENT__: deploymentDefine,
322
+ __DEVSTACK_E2E__: JSON.stringify(e2eFromEnv(env))
192
323
  },
193
- define: { __DEVSTACK_IDS__: JSON.stringify(injectedIds ?? null) },
194
324
  ...includeDevWallet ? { optimizeDeps: { include: [...DEV_WALLET_OPTIMIZE_ENTRIES] } } : {}
195
325
  };
196
326
  },
@@ -202,47 +332,86 @@ const devstackVitePlugin = (options = {}) => {
202
332
  },
203
333
  load: (id) => {
204
334
  if (id !== RESOLVED_VIRTUAL_DEV_WALLET_ID) return void 0;
205
- const extrasDir = resolvedExtrasDir ?? resolveExtrasDir(options, resolvedRoot, process.env);
206
- const devWalletFile = resolve(extrasDir, "dev-wallet.ts");
207
- const accountsFile = resolve(extrasDir, "accounts.ts");
208
- if (!injectDevWallet || !isServe || !existsSync(devWalletFile) || !existsSync(accountsFile)) return "export {};";
209
335
  const env = process.env;
210
- const netOpts = resolveNetworkOptions(readManifestField(env, resolvedRoot, "identity.network") ?? "mainnet", options.networkOptions);
336
+ const manifest = readManifestObject(env, resolvedRoot);
337
+ const token = readDevWalletToken(pickManifestString(manifest, "codegen.deploymentFile"));
338
+ if (!injectDevWallet || !isServe || token === null) return "export {};";
339
+ const netOpts = resolveNetworkOptions(pickManifestString(manifest, "identity.network") ?? "mainnet", options.networkOptions);
211
340
  const autoApprove = options.autoApprove ?? (autoApproveFromEnv(env) || netOpts.autoApproveSigning);
212
341
  return [
213
342
  `import { registerDevstackDevWallet } from '@mysten-incubation/dev-wallet/inject';`,
214
- `import { parseDevstackToken } from '@mysten-incubation/dev-wallet/adapters';`,
215
- `import { devWallet } from '${devExtrasAlias}/dev-wallet.js';`,
216
- `import { accounts } from '${devExtrasAlias}/accounts.js';`,
217
343
  `import { config as __devstackConfig } from '${alias}/config.js';`,
218
- `registerDevstackDevWallet({`,
219
- ` serverOrigin: devWallet.walletUrl,`,
220
- ` token: parseDevstackToken(devWallet.pairUrl),`,
221
- ` accounts,`,
222
- ` rpcUrl: __devstackConfig.networks[__devstackConfig.network].rpc,`,
223
- ` network: devWallet.network,`,
224
- ` autoApprove: ${autoApprove ? "true" : "false"},`,
225
- ` mountUI: true,`,
226
- `}).catch((err) => console.error('[devstack] dev-wallet injection failed:', err));`
344
+ `import { resolveAccounts, optionalValue } from '${alias}/config-runtime.js';`,
345
+ `const __devstackToken = ${JSON.stringify(token)};`,
346
+ `const __devstackAccounts = Object.fromEntries(`,
347
+ ` Object.entries(resolveAccounts()).map(([__name, __address]) => [`,
348
+ ` __name,`,
349
+ ` { name: __name, address: __address },`,
350
+ ` ]),`,
351
+ `);`,
352
+ `const __devstackNetworks = Object.fromEntries(`,
353
+ ` Object.entries(__devstackConfig.networks).map(([__net, __dep]) => [`,
354
+ ` __net,`,
355
+ ` { rpc: __dep.rpc, faucet: __dep.faucet ?? null },`,
356
+ ` ]),`,
357
+ `);`,
358
+ `const __devstackDefaultDep = __devstackConfig.networks[__devstackConfig.defaultNetwork];`,
359
+ `const __devstackConnection = __devstackDefaultDep`,
360
+ ` ? optionalValue(__devstackDefaultDep, 'dev-wallet', 'connection')`,
361
+ ` : undefined;`,
362
+ `if (__devstackConnection) {`,
363
+ ` registerDevstackDevWallet({`,
364
+ ` serverOrigin: __devstackConnection.walletUrl,`,
365
+ ` token: __devstackToken,`,
366
+ ` accounts: __devstackAccounts,`,
367
+ ` networks: __devstackNetworks,`,
368
+ ` defaultNetwork: __devstackConfig.defaultNetwork,`,
369
+ ` autoApprove: ${autoApprove ? "true" : "false"},`,
370
+ ` mountUI: true,`,
371
+ ` }).catch((err) => console.error('[devstack] dev-wallet injection failed:', err));`,
372
+ `}`
227
373
  ].join("\n");
228
374
  },
375
+ configureServer: (server) => {
376
+ if (!isServe) return;
377
+ const env = process.env;
378
+ const idsFile = readIdsFileFromManifest(env, resolvedRoot);
379
+ if (idsFile === null) return;
380
+ server.watcher.add(idsFile);
381
+ const reloadOnIdsChange = (changed) => {
382
+ if (resolve(resolvedRoot, changed) !== resolve(idsFile)) return;
383
+ liveEnvelopeFresh = false;
384
+ (server.hot ?? server.ws)?.send({ type: "full-reload" });
385
+ };
386
+ server.watcher.on("change", reloadOnIdsChange);
387
+ server.watcher.on("add", reloadOnIdsChange);
388
+ },
229
389
  transformIndexHtml: (html) => {
230
- if (!injectDevWallet || !isServe) return void 0;
390
+ if (!isServe) return void 0;
391
+ const env = process.env;
392
+ const live = readLiveEnvelopeCached(env);
393
+ const liveDeployment = mergeDeployment("serve", resolvedCommittedNetworks, live, options.defaultNetwork);
394
+ const tags = [{
395
+ tag: "script",
396
+ children: `globalThis.__DEVSTACK_DEPLOYMENT_LIVE__ = ${escapeForInlineScript(JSON.stringify(liveDeployment ?? null))};`,
397
+ injectTo: "head-prepend"
398
+ }];
399
+ if (injectDevWallet && devWalletPresent) tags.push({
400
+ tag: "script",
401
+ attrs: {
402
+ type: "module",
403
+ src: VIRTUAL_DEV_WALLET_SCRIPT_SRC
404
+ },
405
+ injectTo: "head"
406
+ });
231
407
  return {
232
408
  html,
233
- tags: [{
234
- tag: "script",
235
- attrs: {
236
- type: "module",
237
- src: VIRTUAL_DEV_WALLET_SCRIPT_SRC
238
- },
239
- injectTo: "head"
240
- }]
409
+ tags
241
410
  };
242
411
  }
243
412
  };
244
413
  };
245
414
  //#endregion
246
- export { DEFAULT_DEV_EXTRAS_ALIAS, DEFAULT_GENERATED_ALIAS, devstackVitePlugin };
415
+ export { DEFAULT_GENERATED_ALIAS, devstackVitePlugin };
247
416
 
248
417
  //# sourceMappingURL=index.mjs.map