@dreamboard-games/cli 0.1.30-alpha.4 → 0.1.30-alpha.40

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 (156) hide show
  1. package/README.md +32 -113
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs +2084 -57
  3. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
  4. package/dist/agent-verifier/{chunk-XQXDOBYB.mjs → chunk-4I2WWAPK.mjs} +27 -10
  5. package/dist/agent-verifier/chunk-4I2WWAPK.mjs.map +1 -0
  6. package/dist/agent-verifier/{chunk-C3VW3DTA.mjs → chunk-BWBN2TDJ.mjs} +535 -633
  7. package/dist/agent-verifier/chunk-BWBN2TDJ.mjs.map +1 -0
  8. package/dist/agent-verifier/{chunk-TAEQKBJB.mjs → chunk-GWRZRWCF.mjs} +1 -1
  9. package/dist/agent-verifier/chunk-GWRZRWCF.mjs.map +1 -0
  10. package/dist/agent-verifier/chunk-HUBV22JQ.mjs +89 -0
  11. package/dist/agent-verifier/chunk-HUBV22JQ.mjs.map +1 -0
  12. package/dist/agent-verifier/{chunk-MW2QIWWA.mjs → chunk-KAA3B4DI.mjs} +215 -223
  13. package/dist/agent-verifier/chunk-KAA3B4DI.mjs.map +1 -0
  14. package/dist/agent-verifier/{chunk-27EEIZCI.mjs → chunk-KDAQ4CZY.mjs} +34 -27
  15. package/dist/agent-verifier/chunk-KDAQ4CZY.mjs.map +1 -0
  16. package/dist/agent-verifier/{chunk-IAYRNVUC.mjs → chunk-LMW66VBH.mjs} +2 -13
  17. package/dist/agent-verifier/{chunk-IAYRNVUC.mjs.map → chunk-LMW66VBH.mjs.map} +1 -1
  18. package/dist/agent-verifier/{chunk-776W3UGV.mjs → chunk-LROY5SN2.mjs} +7 -45
  19. package/dist/agent-verifier/chunk-LROY5SN2.mjs.map +1 -0
  20. package/dist/agent-verifier/{chunk-H76MT5UR.mjs → chunk-M7UVBANQ.mjs} +2 -1
  21. package/dist/agent-verifier/chunk-M7UVBANQ.mjs.map +1 -0
  22. package/dist/agent-verifier/{chunk-5NYBTZB4.mjs → chunk-MIRGCMUC.mjs} +112 -26
  23. package/dist/agent-verifier/chunk-MIRGCMUC.mjs.map +1 -0
  24. package/dist/agent-verifier/{chunk-NAK77WXW.mjs → chunk-MYMVXTZT.mjs} +4 -5
  25. package/dist/agent-verifier/chunk-MYMVXTZT.mjs.map +1 -0
  26. package/dist/agent-verifier/chunk-OJFZVGEL.mjs +492 -0
  27. package/dist/agent-verifier/chunk-OJFZVGEL.mjs.map +1 -0
  28. package/dist/agent-verifier/{chunk-XKCJBIRY.mjs → chunk-QD4SQNUP.mjs} +2 -2
  29. package/dist/agent-verifier/{chunk-QBAF7EYR.mjs → chunk-TTB7AIHZ.mjs} +4 -4
  30. package/dist/agent-verifier/{chunk-QBAF7EYR.mjs.map → chunk-TTB7AIHZ.mjs.map} +1 -1
  31. package/dist/agent-verifier/{chunk-F2DIOJJZ.mjs → chunk-XCQQIPCO.mjs} +5 -46
  32. package/dist/agent-verifier/chunk-XCQQIPCO.mjs.map +1 -0
  33. package/dist/agent-verifier/{global-config-NYCSCAUI.mjs → global-config-2NUESNEQ.mjs} +5 -5
  34. package/dist/agent-verifier/{keychain-backend-A3MRWLPF.mjs → keychain-backend-FF4I6ODB.mjs} +11 -6
  35. package/dist/agent-verifier/keychain-backend-FF4I6ODB.mjs.map +1 -0
  36. package/dist/agent-verifier/{local-files-QVJ2H3MH.mjs → local-files-OF4QFISU.mjs} +8 -8
  37. package/dist/agent-verifier/{chunk-UIOLGH4A.mjs → local-typecheck-DHVLM37Z.mjs} +4 -4
  38. package/dist/agent-verifier/local-typecheck-DHVLM37Z.mjs.map +1 -0
  39. package/dist/agent-verifier/{materialize-workspace-OZKOQCSQ.mjs → materialize-workspace-JBDL6LF4.mjs} +22 -22
  40. package/dist/agent-verifier/materialize-workspace-JBDL6LF4.mjs.map +1 -0
  41. package/dist/agent-verifier/{chunk-Z6OZWUIZ.mjs → reducer-bundle-preflight-GLUJKTWU.mjs} +75 -24
  42. package/dist/agent-verifier/reducer-bundle-preflight-GLUJKTWU.mjs.map +1 -0
  43. package/dist/agent-verifier/{chunk-YDIOW2BO.mjs → reducer-contract-preflight-WVQQPW5F.mjs} +7 -6
  44. package/dist/agent-verifier/reducer-contract-preflight-WVQQPW5F.mjs.map +1 -0
  45. package/dist/agent-verifier/{chunk-ON62IGWK.mjs → reducer-native-test-harness-XQUPIT5D.mjs} +480 -703
  46. package/dist/agent-verifier/reducer-native-test-harness-XQUPIT5D.mjs.map +1 -0
  47. package/dist/agent-verifier/static-scaffold-U5DXE23S.mjs +24 -0
  48. package/dist/agent-verifier/{workspace-codegen-WPZHMATU.mjs → workspace-codegen-SPPVHURX.mjs} +3 -3
  49. package/dist/agent-verifier/{workspace-dependencies-B6A2ZX55.mjs → workspace-dependencies-5HEEKZFP.mjs} +5 -3
  50. package/dist/authoring-compatibility-internal.js +12 -0
  51. package/dist/chunk-5IYJOVUA.js +3902 -0
  52. package/dist/chunk-5IYJOVUA.js.map +1 -0
  53. package/dist/chunk-6NYVJYN4.js +313 -0
  54. package/dist/chunk-6NYVJYN4.js.map +1 -0
  55. package/dist/chunk-EQNBQVIW.js +204 -0
  56. package/dist/chunk-EQNBQVIW.js.map +1 -0
  57. package/dist/{chunk-M4SCKH5M.js → chunk-USZAPMQ4.js} +2488 -4993
  58. package/dist/chunk-USZAPMQ4.js.map +1 -0
  59. package/dist/{global-config-YBFEGJQG.js → global-config-RBMW7IVA.js} +3 -2
  60. package/dist/index.js +3099 -6188
  61. package/dist/index.js.map +1 -1
  62. package/dist/internal.js +35 -9
  63. package/dist/internal.js.map +1 -1
  64. package/dist/{keychain-backend-JHTXAKWC.js → keychain-backend-FSNTNTZE.js} +11 -6
  65. package/dist/keychain-backend-FSNTNTZE.js.map +1 -0
  66. package/package.json +9 -19
  67. package/release/authoring-release-set.json +38 -0
  68. package/skills/dreamboard/SKILL.md +32 -30
  69. package/skills/dreamboard/references/building-your-first-game.md +16 -16
  70. package/skills/dreamboard/references/cli.md +54 -54
  71. package/skills/dreamboard/references/manifest-authoring.md +11 -3
  72. package/skills/dreamboard/references/quickstart.md +19 -16
  73. package/skills/dreamboard/references/testing.md +6 -13
  74. package/dist/agent-verifier/chunk-27EEIZCI.mjs.map +0 -1
  75. package/dist/agent-verifier/chunk-5NYBTZB4.mjs.map +0 -1
  76. package/dist/agent-verifier/chunk-776W3UGV.mjs.map +0 -1
  77. package/dist/agent-verifier/chunk-C3VW3DTA.mjs.map +0 -1
  78. package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +0 -1
  79. package/dist/agent-verifier/chunk-G42BGGG2.mjs +0 -70
  80. package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +0 -1
  81. package/dist/agent-verifier/chunk-H76MT5UR.mjs.map +0 -1
  82. package/dist/agent-verifier/chunk-IDVQXGAO.mjs +0 -222
  83. package/dist/agent-verifier/chunk-IDVQXGAO.mjs.map +0 -1
  84. package/dist/agent-verifier/chunk-JO5AMVZU.mjs +0 -1744
  85. package/dist/agent-verifier/chunk-JO5AMVZU.mjs.map +0 -1
  86. package/dist/agent-verifier/chunk-KDBSVLCF.mjs +0 -624
  87. package/dist/agent-verifier/chunk-KDBSVLCF.mjs.map +0 -1
  88. package/dist/agent-verifier/chunk-MW2QIWWA.mjs.map +0 -1
  89. package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +0 -1
  90. package/dist/agent-verifier/chunk-ON62IGWK.mjs.map +0 -1
  91. package/dist/agent-verifier/chunk-QZH6IEZS.mjs +0 -39
  92. package/dist/agent-verifier/chunk-QZH6IEZS.mjs.map +0 -1
  93. package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +0 -1
  94. package/dist/agent-verifier/chunk-UIOLGH4A.mjs.map +0 -1
  95. package/dist/agent-verifier/chunk-XQXDOBYB.mjs.map +0 -1
  96. package/dist/agent-verifier/chunk-YDIOW2BO.mjs.map +0 -1
  97. package/dist/agent-verifier/chunk-Z6OZWUIZ.mjs.map +0 -1
  98. package/dist/agent-verifier/compile-576O7TYP.mjs +0 -312
  99. package/dist/agent-verifier/compile-576O7TYP.mjs.map +0 -1
  100. package/dist/agent-verifier/keychain-backend-A3MRWLPF.mjs.map +0 -1
  101. package/dist/agent-verifier/local-typecheck-2JWG5IGL.mjs +0 -10
  102. package/dist/agent-verifier/materialize-workspace-OZKOQCSQ.mjs.map +0 -1
  103. package/dist/agent-verifier/reducer-bundle-preflight-7NYZF5ZT.mjs +0 -20
  104. package/dist/agent-verifier/reducer-contract-preflight-COD2CO22.mjs +0 -11
  105. package/dist/agent-verifier/reducer-native-test-harness-QC7HZUK4.mjs +0 -50
  106. package/dist/agent-verifier/static-scaffold-JBUE3ROP.mjs +0 -27
  107. package/dist/agent-verifier/sync-C6S3OGCD.mjs +0 -588
  108. package/dist/agent-verifier/sync-C6S3OGCD.mjs.map +0 -1
  109. package/dist/agent-verifier/test-Y5UGQV7J.mjs +0 -353
  110. package/dist/agent-verifier/test-Y5UGQV7J.mjs.map +0 -1
  111. package/dist/agent-verifier/workspace-codegen-WPZHMATU.mjs.map +0 -1
  112. package/dist/agent-verifier/workspace-dependencies-B6A2ZX55.mjs.map +0 -1
  113. package/dist/chunk-3NRROR4P.js +0 -432
  114. package/dist/chunk-3NRROR4P.js.map +0 -1
  115. package/dist/chunk-M4SCKH5M.js.map +0 -1
  116. package/dist/dev-host/components/drawer.tsx +0 -132
  117. package/dist/dev-host/components/input.tsx +0 -21
  118. package/dist/dev-host/dev-api-proxy-plugin.ts +0 -328
  119. package/dist/dev-host/dev-author-dom-warnings.ts +0 -100
  120. package/dist/dev-host/dev-diagnostics.ts +0 -62
  121. package/dist/dev-host/dev-fallback-stylesheet.ts +0 -53
  122. package/dist/dev-host/dev-hmr-guard-plugin.ts +0 -47
  123. package/dist/dev-host/dev-host-controller.ts +0 -674
  124. package/dist/dev-host/dev-host-player-query.ts +0 -17
  125. package/dist/dev-host/dev-host-session-transport.ts +0 -52
  126. package/dist/dev-host/dev-host-storage.ts +0 -56
  127. package/dist/dev-host/dev-log-relay-plugin.ts +0 -510
  128. package/dist/dev-host/dev-runtime-config.ts +0 -14
  129. package/dist/dev-host/dev-runtime-platform.ts +0 -335
  130. package/dist/dev-host/dev-virtual-modules-plugin.ts +0 -64
  131. package/dist/dev-host/host-main.css +0 -224
  132. package/dist/dev-host/host-main.tsx +0 -948
  133. package/dist/dev-host/index.html +0 -56
  134. package/dist/dev-host/lib/utils.ts +0 -6
  135. package/dist/dev-host/plugin-main.ts +0 -61
  136. package/dist/dev-host/plugin.html +0 -24
  137. package/dist/dev-host/shared-styles.css +0 -144
  138. package/dist/dev-host/start-dev-server.ts +0 -140
  139. package/dist/dev-host/virtual-modules.d.ts +0 -27
  140. package/dist/global-config-YBFEGJQG.js.map +0 -1
  141. package/dist/keychain-backend-JHTXAKWC.js.map +0 -1
  142. package/skills/dreamboard/scripts/events-extract.mjs +0 -218
  143. /package/dist/agent-verifier/{chunk-XKCJBIRY.mjs.map → chunk-QD4SQNUP.mjs.map} +0 -0
  144. /package/dist/agent-verifier/{global-config-NYCSCAUI.mjs.map → global-config-2NUESNEQ.mjs.map} +0 -0
  145. /package/dist/agent-verifier/{local-files-QVJ2H3MH.mjs.map → local-files-OF4QFISU.mjs.map} +0 -0
  146. /package/dist/agent-verifier/{local-typecheck-2JWG5IGL.mjs.map → static-scaffold-U5DXE23S.mjs.map} +0 -0
  147. /package/dist/agent-verifier/{reducer-bundle-preflight-7NYZF5ZT.mjs.map → workspace-codegen-SPPVHURX.mjs.map} +0 -0
  148. /package/dist/agent-verifier/{reducer-contract-preflight-COD2CO22.mjs.map → workspace-dependencies-5HEEKZFP.mjs.map} +0 -0
  149. /package/dist/{agent-verifier/reducer-native-test-harness-QC7HZUK4.mjs.map → authoring-compatibility-internal.js.map} +0 -0
  150. /package/dist/{agent-verifier/static-scaffold-JBUE3ROP.mjs.map → global-config-RBMW7IVA.js.map} +0 -0
  151. /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.framework.json +0 -0
  152. /package/{dist/scaffold → scaffold}/assets/static/app/tsconfig.json +0 -0
  153. /package/{dist/scaffold → scaffold}/assets/static/ui/index.tsx +0 -0
  154. /package/{dist/scaffold → scaffold}/assets/static/ui/style.css +0 -0
  155. /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.framework.json +0 -0
  156. /package/{dist/scaffold → scaffold}/assets/static/ui/tsconfig.json +0 -0
@@ -1,49 +1,89 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REDUCER_TESTING_TYPES_WRAPPER_CONTENT
4
- } from "./chunk-F2DIOJJZ.mjs";
4
+ } from "./chunk-XCQQIPCO.mjs";
5
5
  import {
6
- IS_PUBLISHED_BUILD,
7
- loadProjectConfig
8
- } from "./chunk-776W3UGV.mjs";
6
+ ensureDir
7
+ } from "./chunk-LMW66VBH.mjs";
9
8
  import {
10
9
  isDynamicSeedPath,
11
10
  materializeManifest
12
- } from "./chunk-C3VW3DTA.mjs";
11
+ } from "./chunk-BWBN2TDJ.mjs";
13
12
  import {
14
- resolveCliRepoRoot
15
- } from "./chunk-QBAF7EYR.mjs";
16
- import {
17
- ensureDir,
18
- exists,
19
- readJsonFile,
20
- readTextFile,
21
- readTextFileIfExists,
22
- writeTextFile
23
- } from "./chunk-IAYRNVUC.mjs";
13
+ normalizeOwnedProjectPath,
14
+ readWorkspaceTextFile,
15
+ readWorkspaceTextFileIfExists,
16
+ removeWorkspacePath,
17
+ resolveWorkspacePath,
18
+ unlinkWorkspaceFile,
19
+ workspacePathExists,
20
+ writeWorkspaceTextFile
21
+ } from "./chunk-OJFZVGEL.mjs";
24
22
  import {
25
23
  FRAMEWORK_PNPM_OVERRIDES,
26
24
  FRAMEWORK_REACT_DEPENDENCIES,
27
25
  FRAMEWORK_ZOD_VERSION
28
26
  } from "./chunk-ZEELHSY3.mjs";
29
27
  import {
30
- MANIFEST_TYPECHECK_CONFIG_FILE,
31
- PROJECT_CONFIG_FILE,
32
- PROJECT_DIR_NAME
33
- } from "./chunk-H76MT5UR.mjs";
28
+ MANIFEST_TYPECHECK_CONFIG_FILE
29
+ } from "./chunk-M7UVBANQ.mjs";
34
30
 
35
31
  // src/services/project/static-scaffold.ts
36
- import { existsSync, readFileSync } from "fs";
37
- import { readdir, readFile, rm, rmdir, unlink } from "fs/promises";
32
+ import { existsSync } from "fs";
33
+ import { readdir, readFile, rmdir } from "fs/promises";
38
34
  import path from "path";
39
35
  import { fileURLToPath } from "url";
40
- var DREAMBOARD_SYNC_COMMAND = "dreamboard sync";
36
+
37
+ // src/release/authoring-release-set.generated.ts
38
+ var AUTHORING_RELEASE_SET = {
39
+ "schemaVersion": 1,
40
+ "channel": "public",
41
+ "packages": {
42
+ "cli": {
43
+ "name": "@dreamboard-games/cli",
44
+ "version": "0.1.30-alpha.40"
45
+ },
46
+ "sdk": {
47
+ "name": "@dreamboard-games/sdk",
48
+ "version": "0.4.0-alpha.6"
49
+ },
50
+ "apiClient": {
51
+ "name": "@dreamboard-games/api-client",
52
+ "version": "0.3.0-alpha.4"
53
+ },
54
+ "devHost": {
55
+ "name": "@dreamboard-games/dev-host",
56
+ "version": "0.1.30-alpha.27"
57
+ }
58
+ },
59
+ "protocols": {
60
+ "authoringAdapter": 1,
61
+ "devHost": 1,
62
+ "verifier": 1
63
+ },
64
+ "schemas": {
65
+ "scaffold": 2,
66
+ "manifest": 2,
67
+ "generatedArtifacts": 1
68
+ },
69
+ "registry": {
70
+ "kind": "public-npm",
71
+ "portable": true
72
+ },
73
+ "packageManager": "pnpm@10.4.1",
74
+ "releaseSetId": "sha256:b1ba68e0bd81fbf6c44d39665e716f5fba81342036f04f1d102b12da77c73f1c"
75
+ };
76
+
77
+ // src/services/project/static-scaffold.ts
78
+ var DREAMBOARD_SCAFFOLD_REFRESH_COMMAND = "dreamboard project create or dreamboard project clone";
41
79
  var DREAMBOARD_GITIGNORE_BLOCK = [
42
80
  "# Dreamboard local state",
43
81
  ".dreamboard/state.json",
44
82
  ".dreamboard/snapshot.json",
45
83
  ".dreamboard/dev/",
46
84
  ".dreamboard/generated/",
85
+ "node_modules/",
86
+ "ui/node_modules/",
47
87
  ""
48
88
  ].join("\n");
49
89
  var TESTING_TYPES_STUB = "export function defineScenario(scenario) { return scenario; }\n";
@@ -82,26 +122,25 @@ export default defineScenario({
82
122
  "Sanity check that the scaffolded workspace boots into its initial phase.",
83
123
  from: "initial-turn",
84
124
  when: async () => undefined,
85
- then: ({ expect, interactions, players, state }) => {
125
+ then: ({ expect, players, state }) => {
86
126
  const playerIds = players();
87
127
  expect(playerIds).toHaveLength(playerIds.length);
88
128
  expect(playerIds.length).toBeGreaterThanOrEqual(1);
89
129
  expect(state()).toBe("setup");
90
- for (const playerId of playerIds) {
91
- expect(interactions(playerId)).toEqual([]);
92
- }
93
130
  },
94
131
  });
95
132
  `;
96
133
  var STATIC_ASSET_ROOT = resolveStaticAssetRoot();
97
- var SDK_PACKAGE_PATHS = {
98
- "@dreamboard-games/sdk": ["packages", "sdk", "package.json"]
134
+ var SDK_DEPENDENCY_RANGES = {
135
+ "@dreamboard-games/sdk": AUTHORING_RELEASE_SET.packages.sdk.version
99
136
  };
100
- var DEFAULT_SDK_DEPENDENCY_RANGES = {
101
- "@dreamboard-games/sdk": "0.4.0-alpha.0"
137
+ var DEV_HOST_DEPENDENCY_RANGES = {
138
+ "@dreamboard-games/dev-host": AUTHORING_RELEASE_SET.packages.devHost.version
102
139
  };
103
- var SDK_DEPENDENCY_RANGES = {
104
- "@dreamboard-games/sdk": resolveSdkDependencyRange("@dreamboard-games/sdk")
140
+ var DREAMBOARD_PACKAGE_OVERRIDES = {
141
+ "@dreamboard-games/api-client": AUTHORING_RELEASE_SET.packages.apiClient.version,
142
+ "@dreamboard-games/dev-host": AUTHORING_RELEASE_SET.packages.devHost.version,
143
+ "@dreamboard-games/sdk": AUTHORING_RELEASE_SET.packages.sdk.version
105
144
  };
106
145
  var FRAMEWORK_SCRIPTS = {
107
146
  dev: "dreamboard dev",
@@ -128,50 +167,38 @@ var SHARED_DEV_DEPENDENCIES = {
128
167
  async function scaffoldStaticWorkspace(projectRoot, mode, options = {}) {
129
168
  await writeFrameworkStaticFiles(projectRoot, mode, options);
130
169
  await ensureDreamboardGitignore(projectRoot);
131
- await writeManifestTypecheckTsconfig(
132
- path.join(projectRoot, MANIFEST_TYPECHECK_CONFIG_FILE)
133
- );
170
+ await writeManifestTypecheckTsconfig(projectRoot);
134
171
  await removeLegacyVendoredSdkPaths(projectRoot);
135
172
  await removeLegacyDreamboardComponentPath(projectRoot);
136
- const testDir = path.join(projectRoot, "test");
137
- const basesDir = path.join(testDir, "bases");
138
- const scenariosDir = path.join(testDir, "scenarios");
139
- const generatedDir = path.join(testDir, "generated");
140
- await ensureDir(basesDir);
141
- await ensureDir(scenariosDir);
142
- await ensureDir(generatedDir);
143
- await writeTestReadme(path.join(testDir, "README.md"));
144
- await writeGeneratedTestingStubs(generatedDir, mode);
173
+ await ensureDir(resolveWorkspacePath(projectRoot, "test/bases"));
174
+ await ensureDir(resolveWorkspacePath(projectRoot, "test/scenarios"));
175
+ await ensureDir(resolveWorkspacePath(projectRoot, "test/generated"));
176
+ await writeTestReadme(projectRoot);
177
+ await writeGeneratedTestingStubs(projectRoot, mode);
145
178
  const initialTestPlayerCount = await inferInitialTestPlayerCount(projectRoot);
146
- await writeInitialBase(
147
- path.join(basesDir, "initial-turn.base.ts"),
148
- mode,
149
- initialTestPlayerCount
150
- );
151
- await writeInitialScenario(
152
- path.join(scenariosDir, "smoke-initial-turn.scenario.ts"),
153
- mode
154
- );
155
- await writeTestingTypes(path.join(testDir, "testing-types.ts"), mode);
156
- await writeTestTsconfig(path.join(testDir, "tsconfig.json"));
157
- const staleDtsPath = path.join(testDir, "testing-types.d.ts");
158
- if (await exists(staleDtsPath)) {
159
- await unlink(staleDtsPath);
179
+ await writeInitialBase(projectRoot, mode, initialTestPlayerCount);
180
+ await writeInitialScenario(projectRoot, mode);
181
+ await writeTestingTypes(projectRoot, mode);
182
+ await writeTestTsconfig(projectRoot);
183
+ if (await workspacePathExists(projectRoot, "test/testing-types.d.ts")) {
184
+ await unlinkWorkspaceFile(projectRoot, "test/testing-types.d.ts");
160
185
  }
161
- const staleBaseScenariosPath = path.join(testDir, "base-scenarios.json");
162
- if (await exists(staleBaseScenariosPath)) {
163
- await unlink(staleBaseScenariosPath);
186
+ if (await workspacePathExists(projectRoot, "test/base-scenarios.json")) {
187
+ await unlinkWorkspaceFile(projectRoot, "test/base-scenarios.json");
164
188
  }
165
189
  await migrateLegacyScenarioImports(projectRoot);
166
190
  }
167
191
  async function ensureDreamboardGitignore(projectRoot) {
168
- const gitignorePath = path.join(projectRoot, ".gitignore");
169
- const existing = await readTextFileIfExists(gitignorePath);
192
+ const existing = await readWorkspaceTextFileIfExists(
193
+ projectRoot,
194
+ ".gitignore"
195
+ );
170
196
  if (existing?.includes(".dreamboard/state.json")) {
171
197
  return;
172
198
  }
173
- await writeTextFile(
174
- gitignorePath,
199
+ await writeWorkspaceTextFile(
200
+ projectRoot,
201
+ ".gitignore",
175
202
  `${existing ? `${existing.trimEnd()}
176
203
 
177
204
  ` : ""}${DREAMBOARD_GITIGNORE_BLOCK}`
@@ -181,14 +208,18 @@ async function assertCliStaticScaffoldComplete(projectRoot, deletedPaths = []) {
181
208
  const expectedEntries = await getExpectedStaticEntries(projectRoot);
182
209
  const missingOrBlankPaths = [];
183
210
  for (const entry of expectedEntries) {
184
- const fullPath = path.join(projectRoot, entry.targetPath);
185
- const content = await readTextFileIfExists(fullPath);
211
+ const content = await readWorkspaceTextFileIfExists(
212
+ projectRoot,
213
+ entry.targetPath
214
+ );
186
215
  if (content === null || content.trim().length === 0) {
187
216
  missingOrBlankPaths.push(entry.targetPath);
188
217
  }
189
218
  }
190
219
  const staticPaths = new Set(expectedEntries.map((entry) => entry.targetPath));
191
- const deletedStaticPaths = deletedPaths.map(normalizeProjectPath).filter((filePath) => staticPaths.has(filePath)).sort();
220
+ const deletedStaticPaths = deletedPaths.map(normalizeOwnedProjectPath).filter(
221
+ (filePath) => filePath !== null && staticPaths.has(filePath)
222
+ ).sort();
192
223
  if (missingOrBlankPaths.length === 0 && deletedStaticPaths.length === 0) {
193
224
  return;
194
225
  }
@@ -202,54 +233,54 @@ async function assertCliStaticScaffoldComplete(projectRoot, deletedPaths = []) {
202
233
  problems.push(`deleted: ${summarizePaths(deletedStaticPaths)}`);
203
234
  }
204
235
  throw new Error(
205
- `CLI static scaffold is incomplete (${problems.join("; ")}). Run \`${DREAMBOARD_SYNC_COMMAND}\` to refresh the scaffold before compiling.`
236
+ `CLI static scaffold is incomplete (${problems.join("; ")}). Refresh the project scaffold with ${DREAMBOARD_SCAFFOLD_REFRESH_COMMAND} before building or testing.`
206
237
  );
207
238
  }
208
239
  async function writeFrameworkStaticFiles(projectRoot, mode, options) {
209
240
  const assetEntries = await getStaticAssetEntries();
210
241
  for (const entry of assetEntries) {
211
- const fullPath = path.join(projectRoot, entry.targetPath);
212
242
  if (mode === "update" && isDynamicSeedPath(entry.targetPath)) {
213
- const existing = await readTextFileIfExists(fullPath);
243
+ const existing = await readWorkspaceTextFileIfExists(
244
+ projectRoot,
245
+ entry.targetPath
246
+ );
214
247
  if (existing !== null && existing.trim().length > 0) {
215
248
  continue;
216
249
  }
217
250
  }
218
- await writeTextFile(fullPath, entry.content);
251
+ await writeWorkspaceTextFile(projectRoot, entry.targetPath, entry.content);
219
252
  }
220
253
  for (const entry of await getDynamicStaticEntries(
221
254
  projectRoot,
222
255
  mode,
223
256
  options
224
257
  )) {
225
- await writeTextFile(
226
- path.join(projectRoot, entry.targetPath),
227
- entry.content
228
- );
258
+ await writeWorkspaceTextFile(projectRoot, entry.targetPath, entry.content);
229
259
  }
230
260
  if (!options.localMaintainerRegistry) {
231
- await rm(path.join(projectRoot, ".npmrc"), { force: true });
261
+ await removeWorkspacePath(projectRoot, ".npmrc", { force: true });
232
262
  }
233
263
  }
234
264
  async function removeLegacyVendoredSdkPaths(projectRoot) {
235
- await rm(path.join(projectRoot, "app", "sdk"), {
265
+ await removeWorkspacePath(projectRoot, "app/sdk", {
236
266
  recursive: true,
237
267
  force: true
238
268
  });
239
- await rm(path.join(projectRoot, "ui", "sdk"), {
269
+ await removeWorkspacePath(projectRoot, "ui/sdk", {
240
270
  recursive: true,
241
271
  force: true
242
272
  });
243
273
  }
244
274
  async function removeLegacyDreamboardComponentPath(projectRoot) {
245
- const legacyDirPath = path.join(
275
+ const legacyIndexProjectPath = "ui/components/dreamboard/index.ts";
276
+ const legacyDirPath = resolveWorkspacePath(
277
+ projectRoot,
278
+ "ui/components/dreamboard"
279
+ );
280
+ const existing = await readWorkspaceTextFileIfExists(
246
281
  projectRoot,
247
- "ui",
248
- "components",
249
- "dreamboard"
282
+ legacyIndexProjectPath
250
283
  );
251
- const legacyIndexPath = path.join(legacyDirPath, "index.ts");
252
- const existing = await readTextFileIfExists(legacyIndexPath);
253
284
  const removableLegacyContents = /* @__PURE__ */ new Set([
254
285
  LEGACY_DREAMBOARD_COMPONENT_INDEX_CONTENT.trim(),
255
286
  OLD_LEGACY_DREAMBOARD_COMPONENT_INDEX_CONTENT.trim(),
@@ -258,24 +289,26 @@ async function removeLegacyDreamboardComponentPath(projectRoot) {
258
289
  if (existing === null || !removableLegacyContents.has(existing.trim())) {
259
290
  return;
260
291
  }
261
- await unlink(legacyIndexPath);
292
+ await unlinkWorkspaceFile(projectRoot, legacyIndexProjectPath);
262
293
  const remainingEntries = await readdir(legacyDirPath).catch(() => []);
263
294
  if (remainingEntries.length === 0) {
264
295
  await rmdir(legacyDirPath);
265
296
  }
266
297
  }
267
- async function writeTestReadme(filePath) {
268
- await writeTextFile(
269
- filePath,
270
- "# Dreamboard Test Workspace\n\nTypeScript bases live in `test/bases/*.base.ts` and scenarios live in `test/scenarios/*.scenario.ts`.\n\n1. Define reusable seeded bases with `defineBase({ id, seed, players, setupProfileId?, setup })`.\n2. Define scenarios with `defineScenario({ id, from, when, then })`.\n3. Scenario assertions can read `players()`, `state()`, `view(playerId)`, and `interactions(playerId)`.\n4. Generate deterministic base snapshots: `dreamboard test generate`.\n5. Run tests: `dreamboard test run`.\n\nImport test helpers from `../testing-types`.\n\nGenerated artifacts are written to `test/generated/*` and should not be edited manually.\n"
298
+ async function writeTestReadme(projectRoot) {
299
+ await writeWorkspaceTextFile(
300
+ projectRoot,
301
+ "test/README.md",
302
+ "# Dreamboard Test Workspace\n\nTypeScript bases live in `test/bases/*.base.ts` and scenarios live in `test/scenarios/*.scenario.ts`.\n\n1. Define reusable seeded bases with `defineBase({ id, seed, players, setupProfileId?, setup })`.\n2. Define scenarios with `defineScenario({ id, from, when, then })`.\n3. Scenario assertions can read `players()`, `state()`, `view(playerId)`, and `interactions(playerId)`.\n4. Run deterministic scenario tests: `dreamboard test`.\n5. Run a single scenario when needed: `dreamboard test --scenario <scenario-id>`.\n\nImport test helpers from `../testing-types`.\n\nGenerated artifacts are written to `test/generated/*` and should not be edited manually.\n"
271
303
  );
272
304
  }
273
- async function writeInitialBase(filePath, mode, players) {
305
+ async function writeInitialBase(projectRoot, mode, players) {
274
306
  if (mode === "update") {
275
307
  return;
276
308
  }
277
- await writeTextFile(
278
- filePath,
309
+ await writeWorkspaceTextFile(
310
+ projectRoot,
311
+ "test/bases/initial-turn.base.ts",
279
312
  `import { defineBase } from "../testing-types";
280
313
 
281
314
  export default defineBase({
@@ -287,44 +320,69 @@ export default defineBase({
287
320
  `
288
321
  );
289
322
  }
290
- async function writeInitialScenario(filePath, mode) {
323
+ async function writeInitialScenario(projectRoot, mode) {
291
324
  if (mode === "new") {
292
- await writeTextFile(filePath, INITIAL_SCENARIO_CONTENT);
325
+ await writeWorkspaceTextFile(
326
+ projectRoot,
327
+ "test/scenarios/smoke-initial-turn.scenario.ts",
328
+ INITIAL_SCENARIO_CONTENT
329
+ );
293
330
  return;
294
331
  }
295
- const existing = await readTextFileIfExists(filePath);
296
- if (existing === null || existing.trim().length === 0 || existing === INITIAL_SCENARIO_CONTENT) {
297
- await writeTextFile(filePath, INITIAL_SCENARIO_CONTENT);
332
+ const existing = await readWorkspaceTextFileIfExists(
333
+ projectRoot,
334
+ "test/scenarios/smoke-initial-turn.scenario.ts"
335
+ );
336
+ if (existing === null || existing.trim().length === 0 || existing.startsWith(GENERATED_SCENARIO_PREFIX)) {
337
+ await writeWorkspaceTextFile(
338
+ projectRoot,
339
+ "test/scenarios/smoke-initial-turn.scenario.ts",
340
+ INITIAL_SCENARIO_CONTENT
341
+ );
298
342
  }
299
343
  }
300
- async function writeTestingTypes(filePath, mode) {
344
+ async function writeTestingTypes(projectRoot, mode) {
301
345
  if (mode === "new") {
302
- await writeTextFile(filePath, REDUCER_TESTING_TYPES_WRAPPER_CONTENT);
346
+ await writeWorkspaceTextFile(
347
+ projectRoot,
348
+ "test/testing-types.ts",
349
+ REDUCER_TESTING_TYPES_WRAPPER_CONTENT
350
+ );
303
351
  return;
304
352
  }
305
- const existing = await readTextFileIfExists(filePath);
353
+ const existing = await readWorkspaceTextFileIfExists(
354
+ projectRoot,
355
+ "test/testing-types.ts"
356
+ );
306
357
  if (shouldRefreshGeneratedTestingTypes(existing)) {
307
- await writeTextFile(filePath, REDUCER_TESTING_TYPES_WRAPPER_CONTENT);
358
+ await writeWorkspaceTextFile(
359
+ projectRoot,
360
+ "test/testing-types.ts",
361
+ REDUCER_TESTING_TYPES_WRAPPER_CONTENT
362
+ );
308
363
  }
309
364
  }
310
- async function writeGeneratedTestingStubs(generatedDir, mode) {
365
+ async function writeGeneratedTestingStubs(projectRoot, mode) {
311
366
  const header = "// Generated by dreamboard scaffold. Do not edit by hand.\n";
312
367
  await writeGeneratedTestingStubFile(
313
- path.join(generatedDir, "base-states.generated.ts"),
368
+ projectRoot,
369
+ "test/generated/base-states.generated.ts",
314
370
  `${header}export const BASE_STATES = {} as const;
315
371
  export const BASE_STATES_CONTRACT_FINGERPRINT = undefined;
316
372
  `,
317
373
  mode
318
374
  );
319
375
  await writeGeneratedTestingStubFile(
320
- path.join(generatedDir, "base-states.generated.d.ts"),
376
+ projectRoot,
377
+ "test/generated/base-states.generated.d.ts",
321
378
  `${header}export declare const BASE_STATES: Record<string, unknown>;
322
379
  export declare const BASE_STATES_CONTRACT_FINGERPRINT: string | undefined;
323
380
  `,
324
381
  mode
325
382
  );
326
383
  await writeGeneratedTestingStubFile(
327
- path.join(generatedDir, "testing-contract.ts"),
384
+ projectRoot,
385
+ "test/generated/testing-contract.ts",
328
386
  `${header}export type BaseId = string;
329
387
  export type GameView = unknown;
330
388
  export type InteractionId = string;
@@ -333,7 +391,6 @@ export type PhaseName = string;
333
391
  export type PlayerId = string;
334
392
  export type RejectionCode = string;
335
393
  export type StateName = string;
336
- export type TestRunner = "reducer" | "remote" | "browser";
337
394
  export type ViewByPhase = Record<string, GameView>;
338
395
  export type WorkspaceStageName<_Phase extends string = string> = string;
339
396
  export type Expectation = { [matcher: string]: (...args: unknown[]) => unknown; not: Expectation };
@@ -344,32 +401,37 @@ export interface ScenarioGameApi { start(): Promise<void>; submit<Id extends Int
344
401
  export interface BaseContext { game: ScenarioGameApi; players(): readonly PlayerId[]; seat(index: number): PlayerId; }
345
402
  export interface SharedScenarioContext { game: ScenarioGameApi; players(): readonly PlayerId[]; seat(index: number): PlayerId; state(): StateName; view(playerId: PlayerId): GameView; interactions(playerId: PlayerId): readonly InteractionDescriptorFor[]; explain(playerId: PlayerId, interactionId: InteractionId): InteractionExplanation; expect: ExpectFn; }
346
403
  export type ScenarioContext<Phase extends PhaseName | undefined = undefined> = Omit<SharedScenarioContext, "state" | "view"> & { state(): Phase extends PhaseName ? Phase : StateName; view(playerId: PlayerId): Phase extends PhaseName ? ViewByPhase[Phase] : GameView; };
347
- export type ScenarioThenContext<_Runners extends readonly TestRunner[] = readonly ["reducer"], Phase extends PhaseName | undefined = undefined> = ScenarioContext<Phase>;
404
+ export type ScenarioThenContext<Phase extends PhaseName | undefined = undefined> = ScenarioContext<Phase>;
348
405
  export interface BaseDefinition { id: string; seed?: number; players?: number; setupProfileId?: string; extends?: BaseId | string; setup: (ctx: BaseContext) => void | Promise<void>; }
349
- export interface ScenarioDefinition<Runners extends readonly TestRunner[] = readonly ["reducer"], Phase extends PhaseName | undefined = undefined> { id: string; description?: string; from: BaseId | string; runners?: Runners; phase?: Phase; stage?: Phase extends PhaseName ? WorkspaceStageName<Phase> : never; when: (ctx: ScenarioContext<Phase>) => void | Promise<void>; then: (ctx: ScenarioThenContext<Runners, Phase>) => void | Promise<void>; }
406
+ export interface ScenarioDefinition<Phase extends PhaseName | undefined = undefined> { id: string; description?: string; from: BaseId | string; phase?: Phase; stage?: Phase extends PhaseName ? WorkspaceStageName<Phase> : never; when: (ctx: ScenarioContext<Phase>) => void | Promise<void>; then: (ctx: ScenarioThenContext<Phase>) => void | Promise<void>; }
350
407
  `,
351
408
  mode
352
409
  );
353
410
  await writeGeneratedTestingStubFile(
354
- path.join(generatedDir, "scenario-manifest.generated.ts"),
411
+ projectRoot,
412
+ "test/generated/scenario-manifest.generated.ts",
355
413
  `${header}export const SCENARIO_MANIFEST = [] as const;
356
414
  `,
357
415
  mode
358
416
  );
359
417
  }
360
- async function writeGeneratedTestingStubFile(filePath, content, mode) {
418
+ async function writeGeneratedTestingStubFile(projectRoot, projectPath, content, mode) {
361
419
  if (mode === "new") {
362
- await writeTextFile(filePath, content);
420
+ await writeWorkspaceTextFile(projectRoot, projectPath, content);
363
421
  return;
364
422
  }
365
- const existing = await readTextFileIfExists(filePath);
423
+ const existing = await readWorkspaceTextFileIfExists(
424
+ projectRoot,
425
+ projectPath
426
+ );
366
427
  if (existing === null || existing.trim().length === 0 || existing.startsWith(GENERATED_SCENARIO_PREFIX)) {
367
- await writeTextFile(filePath, content);
428
+ await writeWorkspaceTextFile(projectRoot, projectPath, content);
368
429
  }
369
430
  }
370
- async function writeTestTsconfig(filePath) {
371
- await writeTextFile(
372
- filePath,
431
+ async function writeTestTsconfig(projectRoot) {
432
+ await writeWorkspaceTextFile(
433
+ projectRoot,
434
+ "test/tsconfig.json",
373
435
  `${JSON.stringify(
374
436
  {
375
437
  compilerOptions: {
@@ -394,9 +456,10 @@ async function writeTestTsconfig(filePath) {
394
456
  `
395
457
  );
396
458
  }
397
- async function writeManifestTypecheckTsconfig(filePath) {
398
- await writeTextFile(
399
- filePath,
459
+ async function writeManifestTypecheckTsconfig(projectRoot) {
460
+ await writeWorkspaceTextFile(
461
+ projectRoot,
462
+ MANIFEST_TYPECHECK_CONFIG_FILE,
400
463
  `${JSON.stringify(
401
464
  {
402
465
  compilerOptions: {
@@ -418,11 +481,12 @@ async function writeManifestTypecheckTsconfig(filePath) {
418
481
  );
419
482
  }
420
483
  async function migrateLegacyScenarioImports(projectRoot) {
421
- const scenariosRoot = path.join(projectRoot, "test", "scenarios");
422
- if (!await exists(scenariosRoot)) return;
484
+ if (!await workspacePathExists(projectRoot, "test/scenarios")) return;
485
+ const scenariosRoot = resolveWorkspacePath(projectRoot, "test/scenarios");
423
486
  const scenarioFiles = await collectScenarioFiles(scenariosRoot);
424
487
  for (const filePath of scenarioFiles) {
425
- const content = await readTextFile(filePath);
488
+ const projectPath = toWorkspaceProjectPath(projectRoot, filePath);
489
+ const content = await readWorkspaceTextFile(projectRoot, projectPath);
426
490
  if (!content.includes("@dreamboard/cli/testing")) continue;
427
491
  const relativeToTestingTypes = normalizeImportPath(
428
492
  path.relative(
@@ -432,7 +496,7 @@ async function migrateLegacyScenarioImports(projectRoot) {
432
496
  );
433
497
  const migrated = content.replaceAll('"@dreamboard/cli/testing"', `"${relativeToTestingTypes}"`).replaceAll("'@dreamboard/cli/testing'", `'${relativeToTestingTypes}'`);
434
498
  if (migrated !== content) {
435
- await writeTextFile(filePath, migrated);
499
+ await writeWorkspaceTextFile(projectRoot, projectPath, migrated);
436
500
  }
437
501
  }
438
502
  }
@@ -446,8 +510,7 @@ function shouldRefreshGeneratedTestingTypes(existingContent) {
446
510
  return existingContent.startsWith(GENERATED_TESTING_TYPES_PREFIX);
447
511
  }
448
512
  async function inferInitialTestPlayerCount(projectRoot) {
449
- const manifestPath = path.join(projectRoot, "manifest.ts");
450
- if (!await exists(manifestPath)) {
513
+ if (!await workspacePathExists(projectRoot, "manifest.ts")) {
451
514
  return 4;
452
515
  }
453
516
  try {
@@ -494,9 +557,12 @@ async function getStaticAssetEntries() {
494
557
  const files = await walkFiles(STATIC_ASSET_ROOT);
495
558
  const entries = [];
496
559
  for (const filePath of files) {
497
- const targetPath = normalizeProjectPath(
498
- path.relative(STATIC_ASSET_ROOT, filePath)
560
+ const targetPath = normalizeOwnedProjectPath(
561
+ path.relative(STATIC_ASSET_ROOT, filePath).replaceAll(path.sep, "/")
499
562
  );
563
+ if (targetPath === null) {
564
+ throw new Error(`Unsafe static scaffold asset path: ${filePath}`);
565
+ }
500
566
  entries.push({
501
567
  targetPath,
502
568
  content: await readFile(filePath, "utf8")
@@ -526,24 +592,12 @@ async function getDynamicStaticEntries(projectRoot, mode, options = {}) {
526
592
  }
527
593
  return entries;
528
594
  }
529
- async function readProjectLocalMaintainerRegistry(projectRoot) {
530
- const projectConfigPath = path.join(
531
- projectRoot,
532
- PROJECT_DIR_NAME,
533
- PROJECT_CONFIG_FILE
534
- );
535
- if (!await exists(projectConfigPath)) {
536
- return null;
537
- }
538
- const projectConfig = await loadProjectConfig(projectRoot);
539
- return projectConfig.localMaintainerRegistry ?? null;
540
- }
541
595
  async function getExpectedStaticEntries(projectRoot) {
542
596
  const entries = [
543
- ...await getStaticAssetEntries(),
544
- ...await getDynamicStaticEntries(projectRoot, "update", {
545
- localMaintainerRegistry: await readProjectLocalMaintainerRegistry(projectRoot)
546
- })
597
+ ...(await getStaticAssetEntries()).filter(
598
+ (entry) => entry.targetPath !== ".npmrc"
599
+ ),
600
+ ...await getDynamicStaticEntries(projectRoot, "update")
547
601
  ];
548
602
  entries.sort(
549
603
  (left, right) => left.targetPath.localeCompare(right.targetPath)
@@ -574,8 +628,9 @@ async function buildRootPackageJson(projectRoot, mode, options) {
574
628
  ...SDK_DEPENDENCY_RANGES,
575
629
  ...options.localMaintainerRegistry?.packages ?? {}
576
630
  };
577
- const packageJsonPath = path.join(projectRoot, "package.json");
578
- const existingPackageJson = mode === "update" && await exists(packageJsonPath) ? await readJsonFile(packageJsonPath) : null;
631
+ const existingPackageJson = mode === "update" && await workspacePathExists(projectRoot, "package.json") ? JSON.parse(
632
+ await readWorkspaceTextFile(projectRoot, "package.json")
633
+ ) : null;
579
634
  const {
580
635
  dreamboardFrameworkVersion: _legacyFrameworkVersion,
581
636
  ...existingPackageJsonWithoutLegacyVersion
@@ -586,11 +641,13 @@ async function buildRootPackageJson(projectRoot, mode, options) {
586
641
  ...ROOT_APP_DEPENDENCIES
587
642
  };
588
643
  const frameworkDevDependencies = {
589
- ...SHARED_DEV_DEPENDENCIES
644
+ ...SHARED_DEV_DEPENDENCIES,
645
+ ...DEV_HOST_DEPENDENCY_RANGES
590
646
  };
591
647
  const nextPackageJson = {
592
648
  ...existingPackageJsonWithoutLegacyVersion,
593
649
  private: true,
650
+ packageManager: AUTHORING_RELEASE_SET.packageManager,
594
651
  scripts: {
595
652
  ...existingPackageJson?.scripts ?? {},
596
653
  ...FRAMEWORK_SCRIPTS
@@ -614,7 +671,8 @@ function mergePnpmConfig(existingPnpm) {
614
671
  ...existingPnpm ?? {},
615
672
  overrides: {
616
673
  ...existingOverrides,
617
- ...FRAMEWORK_PNPM_OVERRIDES
674
+ ...FRAMEWORK_PNPM_OVERRIDES,
675
+ ...DREAMBOARD_PACKAGE_OVERRIDES
618
676
  }
619
677
  };
620
678
  }
@@ -634,83 +692,18 @@ function buildUiPackageJson() {
634
692
  )}
635
693
  `;
636
694
  }
637
- function readPackageVersion(packageJsonPath, packageName) {
638
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
639
- if (typeof packageJson.version !== "string" || packageJson.version.trim().length === 0) {
640
- return null;
641
- }
642
- return `^${packageJson.version.trim()}`;
643
- }
644
- function findNearestPackageJsonPath(importMetaUrl = import.meta.url) {
645
- let current = path.dirname(fileURLToPath(importMetaUrl));
646
- while (true) {
647
- const candidate = path.join(current, "package.json");
648
- if (existsSync(candidate)) {
649
- return candidate;
650
- }
651
- const parent = path.dirname(current);
652
- if (parent === current) {
653
- return null;
654
- }
655
- current = parent;
656
- }
657
- }
658
- function isSourceCheckoutCliPackageJsonPath(packageJsonPath, importMetaUrl = import.meta.url) {
659
- try {
660
- return path.resolve(packageJsonPath) === path.join(
661
- resolveCliRepoRoot(importMetaUrl),
662
- "apps",
663
- "dreamboard-cli",
664
- "package.json"
665
- );
666
- } catch {
667
- return false;
668
- }
669
- }
670
- function readPackagedSdkDependencyRange(packageName, importMetaUrl = import.meta.url) {
671
- const packageJsonPath = findNearestPackageJsonPath(importMetaUrl);
672
- if (!packageJsonPath) {
673
- return null;
674
- }
675
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
676
- const packagedRange = packageJson.dependencies?.[packageName];
677
- if (typeof packagedRange !== "string" || packagedRange.trim().length === 0 || packagedRange.startsWith("workspace:") || packagedRange.startsWith("link:") || packagedRange.startsWith("file:") && !IS_PUBLISHED_BUILD && isSourceCheckoutCliPackageJsonPath(packageJsonPath, importMetaUrl)) {
678
- return null;
679
- }
680
- return packagedRange.trim();
681
- }
682
- function stripLocalSnapshotSuffix(range) {
683
- return range.replace(/-local\..*$/, "");
684
- }
685
- function resolveSdkDependencyRange(packageName, importMetaUrl = import.meta.url) {
686
- const packagedRange = readPackagedSdkDependencyRange(
687
- packageName,
688
- importMetaUrl
689
- );
690
- if (packagedRange) {
691
- return stripLocalSnapshotSuffix(packagedRange);
692
- }
693
- try {
694
- const repoRoot = resolveCliRepoRoot(importMetaUrl);
695
- const packageJsonPath = path.join(
696
- repoRoot,
697
- ...SDK_PACKAGE_PATHS[packageName]
698
- );
699
- const repoRange = readPackageVersion(packageJsonPath, packageName);
700
- if (repoRange) {
701
- return stripLocalSnapshotSuffix(repoRange);
702
- }
703
- } catch {
704
- }
705
- return DEFAULT_SDK_DEPENDENCY_RANGES[packageName];
706
- }
707
695
  function normalizeImportPath(relativePath) {
708
696
  const normalized = relativePath.replaceAll("\\", "/");
709
697
  if (normalized.startsWith(".")) return normalized;
710
698
  return `./${normalized}`;
711
699
  }
712
- function normalizeProjectPath(filePath) {
713
- return filePath.replace(/^\.\//, "").replace(/^\/+/, "").replace(/\\/g, "/");
700
+ function toWorkspaceProjectPath(projectRoot, filePath) {
701
+ const relativePath = path.relative(path.resolve(projectRoot), path.resolve(filePath)).replaceAll(path.sep, "/");
702
+ const projectPath = normalizeOwnedProjectPath(relativePath);
703
+ if (projectPath === null) {
704
+ throw new Error(`Unsafe project path: ${relativePath}`);
705
+ }
706
+ return projectPath;
714
707
  }
715
708
  function summarizePaths(paths) {
716
709
  const maxShown = 5;
@@ -723,7 +716,6 @@ export {
723
716
  scaffoldStaticWorkspace,
724
717
  assertCliStaticScaffoldComplete,
725
718
  migrateLegacyScenarioImports,
726
- resolveStaticAssetRoot,
727
- resolveSdkDependencyRange
719
+ resolveStaticAssetRoot
728
720
  };
729
- //# sourceMappingURL=chunk-MW2QIWWA.mjs.map
721
+ //# sourceMappingURL=chunk-KAA3B4DI.mjs.map