@dreamboard-games/sdk 0.5.0-alpha.2 → 0.5.0-alpha.3

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 (150) hide show
  1. package/README.md +136 -45
  2. package/dist/chunk-DMFVAZI2.js +16 -0
  3. package/dist/chunk-DMFVAZI2.js.map +1 -0
  4. package/dist/chunk-FMM5LVJW.js +833 -0
  5. package/dist/chunk-FMM5LVJW.js.map +1 -0
  6. package/dist/{chunk-S2JEDVWH.js → chunk-LRILEVKC.js} +6113 -6489
  7. package/dist/chunk-LRILEVKC.js.map +1 -0
  8. package/dist/chunk-SP234IY4.js +1363 -0
  9. package/dist/chunk-SP234IY4.js.map +1 -0
  10. package/dist/chunk-VUWNJXLJ.js +52 -0
  11. package/dist/chunk-VUWNJXLJ.js.map +1 -0
  12. package/dist/chunk-ZPRKWPEP.js +511 -0
  13. package/dist/chunk-ZPRKWPEP.js.map +1 -0
  14. package/dist/definition-BaHNPZol.d.ts +4639 -0
  15. package/dist/diagnostics-B0lgnuZ6.d.ts +65 -0
  16. package/dist/index.d.ts +3553 -1
  17. package/dist/index.js +1045 -6
  18. package/dist/index.js.map +1 -1
  19. package/dist/model-BHro6yXu.d.ts +288 -0
  20. package/dist/react.d.ts +32 -0
  21. package/dist/react.js +80 -0
  22. package/dist/react.js.map +1 -0
  23. package/dist/reducer.d.ts +1194 -79
  24. package/dist/reducer.js +4326 -121
  25. package/dist/reducer.js.map +1 -1
  26. package/dist/testing.d.ts +518 -564
  27. package/dist/testing.js +2448 -915
  28. package/dist/testing.js.map +1 -1
  29. package/dist/types-DimqnJBq.d.ts +86 -0
  30. package/package.json +26 -131
  31. package/dist/HandView-Bi2lxzQP.d.ts +0 -79
  32. package/dist/ResourceCounter-BFxJknqp.d.ts +0 -98
  33. package/dist/ThemeProvider-CElaL2ik.d.ts +0 -99
  34. package/dist/attributes-DbvyMbXw.d.ts +0 -68
  35. package/dist/browser-interaction.d.ts +0 -910
  36. package/dist/browser-interaction.js +0 -119
  37. package/dist/browser-interaction.js.map +0 -1
  38. package/dist/chunk-32PFKDV7.js +0 -11705
  39. package/dist/chunk-32PFKDV7.js.map +0 -1
  40. package/dist/chunk-3BAD4VC2.js +0 -263
  41. package/dist/chunk-3BAD4VC2.js.map +0 -1
  42. package/dist/chunk-3SKDNDPG.js +0 -104
  43. package/dist/chunk-3SKDNDPG.js.map +0 -1
  44. package/dist/chunk-5YV2WHJ4.js +0 -25
  45. package/dist/chunk-5YV2WHJ4.js.map +0 -1
  46. package/dist/chunk-ANRB4XKA.js +0 -90
  47. package/dist/chunk-ANRB4XKA.js.map +0 -1
  48. package/dist/chunk-BI4G3PM2.js +0 -1864
  49. package/dist/chunk-BI4G3PM2.js.map +0 -1
  50. package/dist/chunk-EVCLTY4Q.js +0 -935
  51. package/dist/chunk-EVCLTY4Q.js.map +0 -1
  52. package/dist/chunk-GDPKTBUR.js +0 -564
  53. package/dist/chunk-GDPKTBUR.js.map +0 -1
  54. package/dist/chunk-H6VDGFL5.js +0 -2903
  55. package/dist/chunk-H6VDGFL5.js.map +0 -1
  56. package/dist/chunk-LR3ZTWQF.js +0 -5960
  57. package/dist/chunk-LR3ZTWQF.js.map +0 -1
  58. package/dist/chunk-PF7L4BMG.js +0 -117
  59. package/dist/chunk-PF7L4BMG.js.map +0 -1
  60. package/dist/chunk-PN5O6GG2.js +0 -32
  61. package/dist/chunk-PN5O6GG2.js.map +0 -1
  62. package/dist/chunk-PZ5AY32C.js +0 -10
  63. package/dist/chunk-PZ5AY32C.js.map +0 -1
  64. package/dist/chunk-S2JEDVWH.js.map +0 -1
  65. package/dist/chunk-T3ZKNUZ7.js +0 -1
  66. package/dist/chunk-T3ZKNUZ7.js.map +0 -1
  67. package/dist/chunk-UGH54WZ2.js +0 -223
  68. package/dist/chunk-UGH54WZ2.js.map +0 -1
  69. package/dist/chunk-VCDWP5VL.js +0 -746
  70. package/dist/chunk-VCDWP5VL.js.map +0 -1
  71. package/dist/chunk-VDXOF4FW.js +0 -69
  72. package/dist/chunk-VDXOF4FW.js.map +0 -1
  73. package/dist/chunk-WHR5UW3F.js +0 -1988
  74. package/dist/chunk-WHR5UW3F.js.map +0 -1
  75. package/dist/chunk-Y75CFE77.js +0 -17
  76. package/dist/chunk-Y75CFE77.js.map +0 -1
  77. package/dist/chunk-Z7QCREWI.js +0 -3435
  78. package/dist/chunk-Z7QCREWI.js.map +0 -1
  79. package/dist/chunk-ZZGN2ATS.js +0 -1941
  80. package/dist/chunk-ZZGN2ATS.js.map +0 -1
  81. package/dist/components-gAbIz7hK.d.ts +0 -1284
  82. package/dist/definitions-BgmV_GhC.d.ts +0 -300
  83. package/dist/diagnostics-DIi3ina7.d.ts +0 -50
  84. package/dist/digest.d.ts +0 -8
  85. package/dist/game-CsZScpcn.d.ts +0 -763
  86. package/dist/hex-board-view-aKkblDp6.d.ts +0 -1228
  87. package/dist/index-CcT9Q7N7.d.ts +0 -193
  88. package/dist/index.d-DjzoK7zn.d.ts +0 -2101
  89. package/dist/package-set.d.ts +0 -13
  90. package/dist/package-set.js +0 -12
  91. package/dist/package-set.js.map +0 -1
  92. package/dist/player-state-Cqpyeql0.d.ts +0 -371
  93. package/dist/plugin-runtime-contract.d.ts +0 -17
  94. package/dist/plugin-runtime-contract.js +0 -92
  95. package/dist/plugin-runtime-contract.js.map +0 -1
  96. package/dist/primitive-props-BNHDkgd7.d.ts +0 -16
  97. package/dist/protocol-dYgafTYY.d.ts +0 -314
  98. package/dist/reducer/advanced.d.ts +0 -82
  99. package/dist/reducer/advanced.js +0 -51
  100. package/dist/reducer/advanced.js.map +0 -1
  101. package/dist/reducer-contract.d.ts +0 -11
  102. package/dist/reducer-contract.js +0 -16
  103. package/dist/reducer-contract.js.map +0 -1
  104. package/dist/reference-games/index.d.ts +0 -31
  105. package/dist/reference-games/index.js +0 -48
  106. package/dist/reference-games/index.js.map +0 -1
  107. package/dist/runtime/primitives.d.ts +0 -250
  108. package/dist/runtime/primitives.js +0 -189
  109. package/dist/runtime/primitives.js.map +0 -1
  110. package/dist/runtime/runtime-api.d.ts +0 -2
  111. package/dist/runtime/runtime-api.js +0 -1
  112. package/dist/runtime/runtime-api.js.map +0 -1
  113. package/dist/runtime/workspace-contract.d.ts +0 -392
  114. package/dist/runtime/workspace-contract.js +0 -28
  115. package/dist/runtime/workspace-contract.js.map +0 -1
  116. package/dist/runtime-RJ5orDJU.d.ts +0 -1699
  117. package/dist/runtime-api-Bz5pwNU_.d.ts +0 -296
  118. package/dist/runtime-json-CQ9QbLZ5.d.ts +0 -5
  119. package/dist/runtime.d.ts +0 -83
  120. package/dist/runtime.js +0 -242
  121. package/dist/runtime.js.map +0 -1
  122. package/dist/schema.d.ts +0 -379
  123. package/dist/stale-contract-artifact-error-XLaweZtF.d.ts +0 -18
  124. package/dist/testing-compiler.d.ts +0 -37
  125. package/dist/testing-compiler.js +0 -272
  126. package/dist/testing-compiler.js.map +0 -1
  127. package/dist/testing-runtime.d.ts +0 -119
  128. package/dist/testing-runtime.js +0 -212
  129. package/dist/testing-runtime.js.map +0 -1
  130. package/dist/types-DJj5MJkl.d.ts +0 -256
  131. package/dist/types-DR7DoB1x.d.ts +0 -28
  132. package/dist/types-JWCYHmu7.d.ts +0 -122
  133. package/dist/types.d.ts +0 -1958
  134. package/dist/types.js +0 -14
  135. package/dist/types.js.map +0 -1
  136. package/dist/ui/components.d.ts +0 -17
  137. package/dist/ui/components.js +0 -216
  138. package/dist/ui/components.js.map +0 -1
  139. package/dist/ui/defaults.d.ts +0 -19
  140. package/dist/ui/defaults.js +0 -104
  141. package/dist/ui/defaults.js.map +0 -1
  142. package/dist/ui/player-state.d.ts +0 -2
  143. package/dist/ui/player-state.js +0 -1
  144. package/dist/ui/player-state.js.map +0 -1
  145. package/dist/ui/plugin-styles.css +0 -2
  146. package/dist/ui-contract-GTUPkf8z.d.ts +0 -1168
  147. package/dist/ui.d.ts +0 -317
  148. package/dist/ui.js +0 -277
  149. package/dist/ui.js.map +0 -1
  150. package/dist/views-BpuWcOyN.d.ts +0 -1641
@@ -1,272 +0,0 @@
1
- import "./chunk-PZ5AY32C.js";
2
-
3
- // src/testing/compile-scenario-replay.ts
4
- import { createHash } from "crypto";
5
- import { createRequire } from "module";
6
- import {
7
- lstat,
8
- mkdtemp,
9
- readFile,
10
- realpath,
11
- rm,
12
- stat,
13
- writeFile
14
- } from "fs/promises";
15
- import { tmpdir } from "os";
16
- import path from "path";
17
- import { pathToFileURL } from "url";
18
- import { build } from "esbuild";
19
- var scenarioSourceDigestVersion = "dreamboard-scenario-source-closure@1";
20
- var syntheticSourceFile = "__dreamboard_compile_scenario_replay__.ts";
21
- async function compileScenarioReplay(options) {
22
- const source = await resolveScenarioSource(options.scenarioPath);
23
- const syntheticSource = buildSyntheticSource(source);
24
- const [
25
- reducerEntry,
26
- reducerAdvancedEntry,
27
- testingEntry,
28
- testingRuntimeEntry,
29
- typesEntry
30
- ] = await Promise.all([
31
- resolveCurrentSdkFacade("reducer"),
32
- resolveCurrentSdkFacade("reducer/advanced"),
33
- resolveCurrentSdkFacade("testing"),
34
- resolveCurrentSdkFacade("testing-runtime"),
35
- resolveCurrentSdkFacade("types")
36
- ]);
37
- const bundled = await build({
38
- absWorkingDir: source.projectRoot,
39
- stdin: {
40
- contents: syntheticSource,
41
- loader: "ts",
42
- resolveDir: source.projectRoot,
43
- sourcefile: syntheticSourceFile
44
- },
45
- bundle: true,
46
- alias: {
47
- "@dreamboard-games/sdk/reducer": reducerEntry,
48
- "@dreamboard-games/sdk/reducer/advanced": reducerAdvancedEntry,
49
- "@dreamboard-games/sdk/testing": testingEntry,
50
- "@dreamboard-games/sdk/testing-runtime": testingRuntimeEntry,
51
- "@dreamboard-games/sdk/types": typesEntry,
52
- zod: createRequire(import.meta.url).resolve("zod")
53
- },
54
- format: "esm",
55
- platform: "node",
56
- target: "node24",
57
- sourcemap: "inline",
58
- metafile: true,
59
- write: false,
60
- logLevel: "silent"
61
- });
62
- const output = bundled.outputFiles?.[0];
63
- if (!output || !bundled.metafile) {
64
- throw new Error("Scenario replay compilation did not produce a bundle.");
65
- }
66
- const sourceDigest = await digestSourceClosure({
67
- projectRoot: source.projectRoot,
68
- inputPaths: Object.keys(bundled.metafile.inputs)
69
- });
70
- const tempRoot = await mkdtemp(
71
- path.join(tmpdir(), "dreamboard-compiled-scenario-")
72
- );
73
- const outputPath = path.join(tempRoot, "compiled-scenario.mjs");
74
- try {
75
- await writeFile(outputPath, output.text);
76
- const loaded = await import(`${pathToFileURL(outputPath).href}?source=${sourceDigest.slice(7, 19)}`);
77
- if (typeof loaded.compile !== "function") {
78
- throw new Error("Scenario replay bundle is missing compile().");
79
- }
80
- const materialized = await loaded.compile({
81
- ...options.at === void 0 ? {} : { at: options.at },
82
- scenarioPath: source.relativeScenarioPath,
83
- sourceDigest
84
- });
85
- const compiled = {
86
- schemaVersion: 1,
87
- scenario: {
88
- path: source.relativeScenarioPath,
89
- sourceDigest
90
- },
91
- definition: materialized.definition,
92
- checkpoint: materialized.checkpoint,
93
- expected: materialized.expected
94
- };
95
- return assertSerializableCompiledReplay(compiled);
96
- } finally {
97
- await rm(tempRoot, { recursive: true, force: true });
98
- }
99
- }
100
- async function resolveCurrentSdkFacade(name) {
101
- const candidates = [
102
- path.resolve(import.meta.dirname, `../${name}.ts`),
103
- path.resolve(import.meta.dirname, `${name}.js`)
104
- ];
105
- for (const candidate of candidates) {
106
- if (await isFile(candidate)) return candidate;
107
- }
108
- throw new Error(
109
- `Could not resolve the current @dreamboard-games/sdk/${name} facade from ${import.meta.dirname}.`
110
- );
111
- }
112
- async function resolveScenarioSource(requestedPath) {
113
- if (typeof requestedPath !== "string" || requestedPath.length === 0) {
114
- throw new Error("scenarioPath must be a non-empty string.");
115
- }
116
- const requestedAbsolute = path.resolve(process.cwd(), requestedPath);
117
- const requestedStats = await lstat(requestedAbsolute).catch((error) => {
118
- if (isMissingPathError(error)) return null;
119
- throw error;
120
- });
121
- if (!requestedStats?.isFile()) {
122
- throw new Error(`Scenario path does not name a file: ${requestedPath}.`);
123
- }
124
- const scenarioPath = await realpath(requestedAbsolute);
125
- const projectRoot = await findProjectRoot(path.dirname(scenarioPath));
126
- const canonicalProjectRoot = await realpath(projectRoot);
127
- const scenarioRoot = path.join(canonicalProjectRoot, "test", "scenarios");
128
- const canonicalScenarioRoot = await realpath(scenarioRoot).catch((error) => {
129
- if (isMissingPathError(error)) return null;
130
- throw error;
131
- });
132
- if (canonicalScenarioRoot === null || !isWithinDirectory(canonicalScenarioRoot, scenarioPath) || !scenarioPath.endsWith(".scenario.ts")) {
133
- throw new Error(
134
- "scenarioPath must resolve to test/scenarios/**/*.scenario.ts inside one game package."
135
- );
136
- }
137
- const gamePath = path.join(canonicalProjectRoot, "app", "game.ts");
138
- if (!await isFile(gamePath)) {
139
- throw new Error(`Game package is missing ${gamePath}.`);
140
- }
141
- return {
142
- projectRoot: canonicalProjectRoot,
143
- scenarioPath,
144
- relativeScenarioPath: toPosix(
145
- path.relative(canonicalProjectRoot, scenarioPath)
146
- ),
147
- gamePath
148
- };
149
- }
150
- async function findProjectRoot(start) {
151
- let current = path.resolve(start);
152
- for (; ; ) {
153
- if (await isFile(path.join(current, "package.json")) && await isFile(path.join(current, "app", "game.ts"))) {
154
- return current;
155
- }
156
- const parent = path.dirname(current);
157
- if (parent === current) {
158
- throw new Error(
159
- "Could not find a game package containing package.json and app/game.ts."
160
- );
161
- }
162
- current = parent;
163
- }
164
- }
165
- function buildSyntheticSource(source) {
166
- const gameSpecifier = localImportSpecifier(
167
- source.projectRoot,
168
- source.gamePath
169
- );
170
- const scenarioSpecifier = localImportSpecifier(
171
- source.projectRoot,
172
- source.scenarioPath
173
- );
174
- return [
175
- `import * as gameModule from ${JSON.stringify(gameSpecifier)};`,
176
- `import * as scenarioModule from ${JSON.stringify(scenarioSpecifier)};`,
177
- 'import { inspectScenario, toScenarioReplayDefinition } from "@dreamboard-games/sdk/testing";',
178
- 'import { digestScenarioProjection, scenarioProjectionParityFromInspectNode } from "@dreamboard-games/sdk/testing-runtime";',
179
- "const game = gameModule.game ?? gameModule.default;",
180
- "const scenario = scenarioModule.scenario ?? scenarioModule.default;",
181
- "export async function compile(options) {",
182
- " if (!game || !scenario) {",
183
- ' throw new Error("Compiled scenario entry is missing game or scenario authority.");',
184
- " }",
185
- " const definition = toScenarioReplayDefinition(scenario);",
186
- " const checkpoint = typeof options.at === 'string' ? scenario.checkpoints?.[options.at] : options.at;",
187
- " if (typeof options.at === 'string' && checkpoint === undefined) {",
188
- " const available = Object.keys(scenario.checkpoints ?? {}).sort();",
189
- " throw new Error(`Unknown checkpoint '${options.at}'; available checkpoints: ${available.join(', ') || 'none'}.`);",
190
- " }",
191
- " const inspected = await inspectScenario({",
192
- " game,",
193
- " scenario: definition,",
194
- " identity: {",
195
- " id: definition.id,",
196
- " path: options.scenarioPath,",
197
- " sourceDigest: options.sourceDigest,",
198
- " },",
199
- ' perspective: { kind: "spectator" },',
200
- " ...(checkpoint === undefined ? {} : { at: checkpoint }),",
201
- " });",
202
- " return {",
203
- " definition,",
204
- " checkpoint: inspected.node.checkpoint,",
205
- " expected: {",
206
- " checkpointDigest: inspected.node.checkpointDigest,",
207
- " publicProjectionDigest: digestScenarioProjection(",
208
- " scenarioProjectionParityFromInspectNode(inspected.node),",
209
- " ),",
210
- " },",
211
- " };",
212
- "}"
213
- ].join("\n");
214
- }
215
- async function digestSourceClosure(options) {
216
- const syntheticPath = path.resolve(options.projectRoot, syntheticSourceFile);
217
- const localPaths = options.inputPaths.map(
218
- (inputPath) => path.isAbsolute(inputPath) ? inputPath : path.resolve(options.projectRoot, inputPath)
219
- ).filter(
220
- (inputPath) => inputPath !== syntheticPath && isWithinDirectory(options.projectRoot, inputPath) && !toPosix(path.relative(options.projectRoot, inputPath)).split("/").includes("node_modules")
221
- );
222
- const inputs = await Promise.all(
223
- [...new Set(localPaths)].map(async (inputPath) => {
224
- const content = await readFile(inputPath);
225
- return {
226
- path: toPosix(path.relative(options.projectRoot, inputPath)),
227
- sha256: createHash("sha256").update(content).digest("hex")
228
- };
229
- })
230
- );
231
- inputs.sort(
232
- (left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0
233
- );
234
- return `sha256:${createHash("sha256").update(
235
- JSON.stringify({
236
- digestVersion: scenarioSourceDigestVersion,
237
- inputs
238
- })
239
- ).digest("hex")}`;
240
- }
241
- function assertSerializableCompiledReplay(value) {
242
- const serialized = JSON.stringify(value);
243
- const parsed = JSON.parse(serialized);
244
- if (parsed.schemaVersion !== 1 || !/^sha256:[a-f0-9]{64}$/.test(parsed.scenario.sourceDigest) || !/^sha256:[a-f0-9]{64}$/.test(parsed.expected.checkpointDigest) || !/^sha256:[a-f0-9]{64}$/.test(parsed.expected.publicProjectionDigest)) {
245
- throw new Error("Compiled scenario replay failed digest validation.");
246
- }
247
- return parsed;
248
- }
249
- function localImportSpecifier(projectRoot, filePath) {
250
- const relative = toPosix(path.relative(projectRoot, filePath));
251
- return relative.startsWith(".") ? relative : `./${relative}`;
252
- }
253
- function isWithinDirectory(directory, filePath) {
254
- const relative = path.relative(directory, filePath);
255
- return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
256
- }
257
- async function isFile(filePath) {
258
- return stat(filePath).then((value) => value.isFile()).catch((error) => {
259
- if (isMissingPathError(error)) return false;
260
- throw error;
261
- });
262
- }
263
- function isMissingPathError(error) {
264
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
265
- }
266
- function toPosix(value) {
267
- return value.split(path.sep).join("/");
268
- }
269
- export {
270
- compileScenarioReplay
271
- };
272
- //# sourceMappingURL=testing-compiler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/testing/compile-scenario-replay.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { createRequire } from \"node:module\";\nimport {\n lstat,\n mkdtemp,\n readFile,\n realpath,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { build } from \"esbuild\";\nimport type {\n ScenarioCheckpoint,\n ScenarioCheckpointSelector,\n ScenarioReplayDefinition,\n} from \"./definitions.js\";\nimport type { ScenarioDefinitionGameLike } from \"./scenario-definition-validation.js\";\n\nexport type CompiledScenarioReplay<\n Game extends ScenarioDefinitionGameLike = ScenarioDefinitionGameLike,\n> = {\n readonly schemaVersion: 1;\n readonly scenario: {\n readonly path: string;\n /** Covers the local game/scenario module graph, including assertions. */\n readonly sourceDigest: `sha256:${string}`;\n };\n /** Canonical serializable scenario projection; never contains `then`. */\n readonly definition: ScenarioReplayDefinition<Game>;\n readonly checkpoint: ScenarioCheckpoint;\n readonly expected: {\n readonly checkpointDigest: `sha256:${string}`;\n readonly publicProjectionDigest: `sha256:${string}`;\n };\n};\n\nexport type CompileScenarioReplayOptions = {\n readonly scenarioPath: string;\n readonly at?: ScenarioCheckpointSelector;\n};\n\ntype SyntheticCompileResult = Omit<\n CompiledScenarioReplay,\n \"schemaVersion\" | \"scenario\"\n>;\n\ntype SyntheticCompileModule = {\n readonly compile: (options: {\n readonly at?: ScenarioCheckpointSelector;\n readonly scenarioPath: string;\n readonly sourceDigest: `sha256:${string}`;\n }) => Promise<SyntheticCompileResult>;\n};\n\ntype ScenarioSource = {\n readonly projectRoot: string;\n readonly scenarioPath: string;\n readonly relativeScenarioPath: string;\n readonly gamePath: string;\n};\n\nconst scenarioSourceDigestVersion = \"dreamboard-scenario-source-closure@1\";\nconst syntheticSourceFile = \"__dreamboard_compile_scenario_replay__.ts\";\n\n/**\n * Compile one authored scenario into the trusted, serializable replay DTO used\n * by dev-host, Workbench, demo, and performance adapters.\n *\n * The DTO may contain sealed/private command parameters. It must never cross a\n * player, spectator, browser, or ordinary-log boundary.\n */\nexport async function compileScenarioReplay(\n options: CompileScenarioReplayOptions,\n): Promise<CompiledScenarioReplay> {\n const source = await resolveScenarioSource(options.scenarioPath);\n const syntheticSource = buildSyntheticSource(source);\n const [\n reducerEntry,\n reducerAdvancedEntry,\n testingEntry,\n testingRuntimeEntry,\n typesEntry,\n ] = await Promise.all([\n resolveCurrentSdkFacade(\"reducer\"),\n resolveCurrentSdkFacade(\"reducer/advanced\"),\n resolveCurrentSdkFacade(\"testing\"),\n resolveCurrentSdkFacade(\"testing-runtime\"),\n resolveCurrentSdkFacade(\"types\"),\n ]);\n const bundled = await build({\n absWorkingDir: source.projectRoot,\n stdin: {\n contents: syntheticSource,\n loader: \"ts\",\n resolveDir: source.projectRoot,\n sourcefile: syntheticSourceFile,\n },\n bundle: true,\n alias: {\n \"@dreamboard-games/sdk/reducer\": reducerEntry,\n \"@dreamboard-games/sdk/reducer/advanced\": reducerAdvancedEntry,\n \"@dreamboard-games/sdk/testing\": testingEntry,\n \"@dreamboard-games/sdk/testing-runtime\": testingRuntimeEntry,\n \"@dreamboard-games/sdk/types\": typesEntry,\n zod: createRequire(import.meta.url).resolve(\"zod\"),\n },\n format: \"esm\",\n platform: \"node\",\n target: \"node24\",\n sourcemap: \"inline\",\n metafile: true,\n write: false,\n logLevel: \"silent\",\n });\n const output = bundled.outputFiles?.[0];\n if (!output || !bundled.metafile) {\n throw new Error(\"Scenario replay compilation did not produce a bundle.\");\n }\n const sourceDigest = await digestSourceClosure({\n projectRoot: source.projectRoot,\n inputPaths: Object.keys(bundled.metafile.inputs),\n });\n\n const tempRoot = await mkdtemp(\n path.join(tmpdir(), \"dreamboard-compiled-scenario-\"),\n );\n const outputPath = path.join(tempRoot, \"compiled-scenario.mjs\");\n try {\n await writeFile(outputPath, output.text);\n const loaded = (await import(\n `${pathToFileURL(outputPath).href}?source=${sourceDigest.slice(7, 19)}`\n )) as SyntheticCompileModule;\n if (typeof loaded.compile !== \"function\") {\n throw new Error(\"Scenario replay bundle is missing compile().\");\n }\n const materialized = await loaded.compile({\n ...(options.at === undefined ? {} : { at: options.at }),\n scenarioPath: source.relativeScenarioPath,\n sourceDigest,\n });\n const compiled = {\n schemaVersion: 1,\n scenario: {\n path: source.relativeScenarioPath,\n sourceDigest,\n },\n definition: materialized.definition,\n checkpoint: materialized.checkpoint,\n expected: materialized.expected,\n } satisfies CompiledScenarioReplay;\n return assertSerializableCompiledReplay(compiled);\n } finally {\n await rm(tempRoot, { recursive: true, force: true });\n }\n}\n\nasync function resolveCurrentSdkFacade(name: string): Promise<string> {\n const candidates = [\n path.resolve(import.meta.dirname, `../${name}.ts`),\n path.resolve(import.meta.dirname, `${name}.js`),\n ];\n for (const candidate of candidates) {\n if (await isFile(candidate)) return candidate;\n }\n throw new Error(\n `Could not resolve the current @dreamboard-games/sdk/${name} facade from ${import.meta.dirname}.`,\n );\n}\n\nasync function resolveScenarioSource(\n requestedPath: string,\n): Promise<ScenarioSource> {\n if (typeof requestedPath !== \"string\" || requestedPath.length === 0) {\n throw new Error(\"scenarioPath must be a non-empty string.\");\n }\n const requestedAbsolute = path.resolve(process.cwd(), requestedPath);\n const requestedStats = await lstat(requestedAbsolute).catch((error) => {\n if (isMissingPathError(error)) return null;\n throw error;\n });\n if (!requestedStats?.isFile()) {\n throw new Error(`Scenario path does not name a file: ${requestedPath}.`);\n }\n const scenarioPath = await realpath(requestedAbsolute);\n const projectRoot = await findProjectRoot(path.dirname(scenarioPath));\n const canonicalProjectRoot = await realpath(projectRoot);\n const scenarioRoot = path.join(canonicalProjectRoot, \"test\", \"scenarios\");\n const canonicalScenarioRoot = await realpath(scenarioRoot).catch((error) => {\n if (isMissingPathError(error)) return null;\n throw error;\n });\n if (\n canonicalScenarioRoot === null ||\n !isWithinDirectory(canonicalScenarioRoot, scenarioPath) ||\n !scenarioPath.endsWith(\".scenario.ts\")\n ) {\n throw new Error(\n \"scenarioPath must resolve to test/scenarios/**/*.scenario.ts inside one game package.\",\n );\n }\n const gamePath = path.join(canonicalProjectRoot, \"app\", \"game.ts\");\n if (!(await isFile(gamePath))) {\n throw new Error(`Game package is missing ${gamePath}.`);\n }\n return {\n projectRoot: canonicalProjectRoot,\n scenarioPath,\n relativeScenarioPath: toPosix(\n path.relative(canonicalProjectRoot, scenarioPath),\n ),\n gamePath,\n };\n}\n\nasync function findProjectRoot(start: string): Promise<string> {\n let current = path.resolve(start);\n for (;;) {\n if (\n (await isFile(path.join(current, \"package.json\"))) &&\n (await isFile(path.join(current, \"app\", \"game.ts\")))\n ) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n throw new Error(\n \"Could not find a game package containing package.json and app/game.ts.\",\n );\n }\n current = parent;\n }\n}\n\nfunction buildSyntheticSource(source: ScenarioSource): string {\n const gameSpecifier = localImportSpecifier(\n source.projectRoot,\n source.gamePath,\n );\n const scenarioSpecifier = localImportSpecifier(\n source.projectRoot,\n source.scenarioPath,\n );\n return [\n `import * as gameModule from ${JSON.stringify(gameSpecifier)};`,\n `import * as scenarioModule from ${JSON.stringify(scenarioSpecifier)};`,\n 'import { inspectScenario, toScenarioReplayDefinition } from \"@dreamboard-games/sdk/testing\";',\n 'import { digestScenarioProjection, scenarioProjectionParityFromInspectNode } from \"@dreamboard-games/sdk/testing-runtime\";',\n \"const game = gameModule.game ?? gameModule.default;\",\n \"const scenario = scenarioModule.scenario ?? scenarioModule.default;\",\n \"export async function compile(options) {\",\n \" if (!game || !scenario) {\",\n ' throw new Error(\"Compiled scenario entry is missing game or scenario authority.\");',\n \" }\",\n \" const definition = toScenarioReplayDefinition(scenario);\",\n \" const checkpoint = typeof options.at === 'string' ? scenario.checkpoints?.[options.at] : options.at;\",\n \" if (typeof options.at === 'string' && checkpoint === undefined) {\",\n \" const available = Object.keys(scenario.checkpoints ?? {}).sort();\",\n \" throw new Error(`Unknown checkpoint '${options.at}'; available checkpoints: ${available.join(', ') || 'none'}.`);\",\n \" }\",\n \" const inspected = await inspectScenario({\",\n \" game,\",\n \" scenario: definition,\",\n \" identity: {\",\n \" id: definition.id,\",\n \" path: options.scenarioPath,\",\n \" sourceDigest: options.sourceDigest,\",\n \" },\",\n ' perspective: { kind: \"spectator\" },',\n \" ...(checkpoint === undefined ? {} : { at: checkpoint }),\",\n \" });\",\n \" return {\",\n \" definition,\",\n \" checkpoint: inspected.node.checkpoint,\",\n \" expected: {\",\n \" checkpointDigest: inspected.node.checkpointDigest,\",\n \" publicProjectionDigest: digestScenarioProjection(\",\n \" scenarioProjectionParityFromInspectNode(inspected.node),\",\n \" ),\",\n \" },\",\n \" };\",\n \"}\",\n ].join(\"\\n\");\n}\n\nasync function digestSourceClosure(options: {\n readonly projectRoot: string;\n readonly inputPaths: readonly string[];\n}): Promise<`sha256:${string}`> {\n const syntheticPath = path.resolve(options.projectRoot, syntheticSourceFile);\n const localPaths = options.inputPaths\n .map((inputPath) =>\n path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(options.projectRoot, inputPath),\n )\n .filter(\n (inputPath) =>\n inputPath !== syntheticPath &&\n isWithinDirectory(options.projectRoot, inputPath) &&\n !toPosix(path.relative(options.projectRoot, inputPath))\n .split(\"/\")\n .includes(\"node_modules\"),\n );\n const inputs = await Promise.all(\n [...new Set(localPaths)].map(async (inputPath) => {\n const content = await readFile(inputPath);\n return {\n path: toPosix(path.relative(options.projectRoot, inputPath)),\n sha256: createHash(\"sha256\").update(content).digest(\"hex\"),\n };\n }),\n );\n inputs.sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n );\n return `sha256:${createHash(\"sha256\")\n .update(\n JSON.stringify({\n digestVersion: scenarioSourceDigestVersion,\n inputs,\n }),\n )\n .digest(\"hex\")}`;\n}\n\nfunction assertSerializableCompiledReplay(\n value: CompiledScenarioReplay,\n): CompiledScenarioReplay {\n const serialized = JSON.stringify(value);\n const parsed = JSON.parse(serialized) as CompiledScenarioReplay;\n if (\n parsed.schemaVersion !== 1 ||\n !/^sha256:[a-f0-9]{64}$/.test(parsed.scenario.sourceDigest) ||\n !/^sha256:[a-f0-9]{64}$/.test(parsed.expected.checkpointDigest) ||\n !/^sha256:[a-f0-9]{64}$/.test(parsed.expected.publicProjectionDigest)\n ) {\n throw new Error(\"Compiled scenario replay failed digest validation.\");\n }\n return parsed;\n}\n\nfunction localImportSpecifier(projectRoot: string, filePath: string): string {\n const relative = toPosix(path.relative(projectRoot, filePath));\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n}\n\nfunction isWithinDirectory(directory: string, filePath: string): boolean {\n const relative = path.relative(directory, filePath);\n return (\n relative !== \"\" &&\n relative !== \"..\" &&\n !relative.startsWith(`..${path.sep}`) &&\n !path.isAbsolute(relative)\n );\n}\n\nasync function isFile(filePath: string): Promise<boolean> {\n return stat(filePath)\n .then((value) => value.isFile())\n .catch((error) => {\n if (isMissingPathError(error)) return false;\n throw error;\n });\n}\n\nfunction isMissingPathError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { readonly code?: unknown }).code === \"ENOENT\"\n );\n}\n\nfunction toPosix(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n"],"mappings":"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","names":[]}
@@ -1,119 +0,0 @@
1
- import { D as DispatchTraceSummaryEntry } from './diagnostics-DIi3ina7.js';
2
- import { o as ScenarioDefinitionGameLike, n as ScenarioDefinition } from './definitions-BgmV_GhC.js';
3
- import { i as Sha256Digest, d as InspectNode } from './types-JWCYHmu7.js';
4
- export { h as ScenarioRuntimeCheckpointMaterialization, m as materializeScenarioRuntimeCheckpoint } from './types-JWCYHmu7.js';
5
- import 'zod';
6
- import './views-BpuWcOyN.js';
7
- import './runtime-RJ5orDJU.js';
8
- import './types.js';
9
- import './protocol-dYgafTYY.js';
10
- import './index.d-DjzoK7zn.js';
11
-
12
- type GameLike = {
13
- readonly phases: Readonly<Record<string, unknown>>;
14
- };
15
- declare function resolveScenarioCommandParams(options: {
16
- readonly game: GameLike;
17
- readonly phase: string;
18
- readonly interactionId: string;
19
- readonly params: unknown;
20
- readonly playerIds: readonly string[];
21
- readonly path: string;
22
- }): Record<string, unknown>;
23
-
24
- type ScenarioProjectionInteractionInput = {
25
- readonly key: string;
26
- readonly kind: string;
27
- readonly domain: unknown;
28
- };
29
- /** Shared SDK normalization for inspect DTOs and backend parity projections. */
30
- declare function scenarioProjectionInputMetadata(input: ScenarioProjectionInteractionInput): {
31
- readonly key: string;
32
- readonly kind: string;
33
- readonly eligibleCount: number | "lazy";
34
- };
35
- type ScenarioProjectionParity = {
36
- readonly perspective: "spectator" | {
37
- readonly seat: number;
38
- };
39
- readonly flow: {
40
- readonly phase: string;
41
- readonly step: string | null;
42
- readonly activeSeats: readonly number[];
43
- readonly pendingSeats: readonly number[];
44
- readonly continuationWaiterSeats: readonly number[];
45
- readonly blockedBy: readonly {
46
- readonly actorSeat: number;
47
- readonly blockerSeats: readonly number[];
48
- }[];
49
- };
50
- readonly view: unknown;
51
- readonly interactions: readonly {
52
- readonly actorSeat: number;
53
- readonly interactionId: string;
54
- readonly availability: {
55
- readonly status: string;
56
- readonly code?: string;
57
- readonly reason?: string;
58
- };
59
- readonly inputs: readonly {
60
- readonly key: string;
61
- readonly kind: string;
62
- readonly eligibleCount: number | "lazy";
63
- }[];
64
- }[];
65
- };
66
- /**
67
- * Canonical local/backend parity authority. It deliberately excludes raw
68
- * reducer public/private state, interaction explanations, entropy, and trace:
69
- * backend gameplay frames expose the selected projection, not reducer state.
70
- */
71
- declare function scenarioProjectionParityFromInspectNode(node: InspectNode): ScenarioProjectionParity;
72
- declare function digestScenarioProjection(projection: ScenarioProjectionParity): Sha256Digest;
73
-
74
- type CandidateVerificationScenario<Game extends ScenarioDefinitionGameLike> = ScenarioDefinition<Game>;
75
- type CandidateVerificationInput<Game extends ScenarioDefinitionGameLike> = {
76
- /** The authored reducer game definition used by production dispatch. */
77
- readonly reducer: Game;
78
- readonly scenarios: Readonly<Record<string, CandidateVerificationScenario<Game>>> | readonly CandidateVerificationScenario<Game>[];
79
- readonly maxScenarios?: number;
80
- readonly maxStepsPerScenario?: number;
81
- };
82
- type CandidateVerificationReplayDiagnostic = {
83
- readonly kind: "replay";
84
- readonly message: string;
85
- readonly scenarioId?: string;
86
- readonly segment?: "given" | "when";
87
- readonly index?: number;
88
- readonly interactionId?: string;
89
- readonly errorCode?: string;
90
- readonly reducerMessage?: string;
91
- readonly trace?: readonly DispatchTraceSummaryEntry[];
92
- };
93
- type CandidateVerificationAssertionDiagnostic = {
94
- readonly kind: "assertion";
95
- readonly message: string;
96
- };
97
- type CandidateVerificationLimitDiagnostic = {
98
- readonly kind: "limit";
99
- readonly message: string;
100
- readonly actualSteps: number;
101
- readonly maxStepsPerScenario: number;
102
- };
103
- type CandidateVerificationScenarioResult = {
104
- readonly id: string;
105
- readonly status: "passed" | "failed";
106
- readonly diagnostic?: CandidateVerificationReplayDiagnostic | CandidateVerificationAssertionDiagnostic | CandidateVerificationLimitDiagnostic;
107
- };
108
- type CandidateVerificationResult = {
109
- readonly status: "passed" | "failed";
110
- readonly scenarioSummary: {
111
- readonly total: number;
112
- readonly passed: number;
113
- readonly failed: number;
114
- readonly scenarios: readonly CandidateVerificationScenarioResult[];
115
- };
116
- };
117
- declare function runCandidateVerification<const Game extends ScenarioDefinitionGameLike>(input: CandidateVerificationInput<Game>): Promise<CandidateVerificationResult>;
118
-
119
- export { type CandidateVerificationAssertionDiagnostic, type CandidateVerificationInput, type CandidateVerificationLimitDiagnostic, type CandidateVerificationReplayDiagnostic, type CandidateVerificationResult, type CandidateVerificationScenario, type CandidateVerificationScenarioResult, type ScenarioProjectionInteractionInput, type ScenarioProjectionParity, digestScenarioProjection, resolveScenarioCommandParams, runCandidateVerification, scenarioProjectionInputMetadata, scenarioProjectionParityFromInspectNode };
@@ -1,212 +0,0 @@
1
- import {
2
- ScenarioReplayError,
3
- assertScenario,
4
- digestScenarioJson,
5
- materializeScenarioRuntimeCheckpoint,
6
- replayScenario,
7
- resolveScenarioCommandParams
8
- } from "./chunk-BI4G3PM2.js";
9
- import {
10
- interactionDomainEligibleCount
11
- } from "./chunk-S2JEDVWH.js";
12
- import "./chunk-PN5O6GG2.js";
13
- import "./chunk-VCDWP5VL.js";
14
- import "./chunk-H6VDGFL5.js";
15
- import "./chunk-PF7L4BMG.js";
16
- import "./chunk-UGH54WZ2.js";
17
- import "./chunk-PZ5AY32C.js";
18
-
19
- // src/testing/scenario-projection-digest.ts
20
- function scenarioProjectionInputMetadata(input) {
21
- return {
22
- key: input.key,
23
- kind: input.kind,
24
- eligibleCount: interactionDomainEligibleCount(input.domain)
25
- };
26
- }
27
- function scenarioProjectionParityFromInspectNode(node) {
28
- return {
29
- perspective: node.perspective.kind === "spectator" ? "spectator" : { seat: node.perspective.actor.seat },
30
- flow: {
31
- phase: node.flow.phase,
32
- step: node.flow.step,
33
- activeSeats: node.flow.activeActors.map(({ seat }) => seat),
34
- pendingSeats: node.flow.pendingActors.map(({ seat }) => seat),
35
- continuationWaiterSeats: node.flow.continuationWaiters.map(
36
- ({ seat }) => seat
37
- ),
38
- blockedBy: node.flow.blockedBy.map(({ actor, blockers }) => ({
39
- actorSeat: actor.seat,
40
- blockerSeats: blockers.map(({ seat }) => seat)
41
- }))
42
- },
43
- view: node.view,
44
- interactions: node.interactions.map(
45
- ({ actor, interactionId, availability, inputs }) => ({
46
- actorSeat: actor.seat,
47
- interactionId,
48
- availability,
49
- inputs
50
- })
51
- )
52
- };
53
- }
54
- function digestScenarioProjection(projection) {
55
- return digestScenarioJson({
56
- digestVersion: "scenario-projection@1",
57
- projection
58
- });
59
- }
60
-
61
- // src/testing-runtime.ts
62
- var CANDIDATE_INPUT_FIELDS = /* @__PURE__ */ new Set([
63
- "reducer",
64
- "scenarios",
65
- "maxScenarios",
66
- "maxStepsPerScenario"
67
- ]);
68
- var MAX_DIAGNOSTIC_MESSAGE_LENGTH = 2e3;
69
- var MAX_DIAGNOSTIC_TRACE_ENTRIES = 100;
70
- async function runCandidateVerification(input) {
71
- assertCandidateInputFields(input);
72
- const scenarios = normalizeScenarios(input.scenarios);
73
- if (scenarios.length === 0) {
74
- throw new Error("Candidate verification requires at least one scenario.");
75
- }
76
- const maxScenarios = input.maxScenarios ?? scenarios.length;
77
- assertPositiveInteger(maxScenarios, "maxScenarios");
78
- if (scenarios.length > maxScenarios) {
79
- throw new Error(
80
- `Candidate verification contains ${scenarios.length} scenarios, exceeding limit ${maxScenarios}.`
81
- );
82
- }
83
- const maxStepsPerScenario = input.maxStepsPerScenario ?? 1e3;
84
- assertPositiveInteger(maxStepsPerScenario, "maxStepsPerScenario");
85
- const results = [];
86
- for (const scenario of scenarios) {
87
- results.push(
88
- await runScenario({
89
- reducer: input.reducer,
90
- scenario,
91
- maxStepsPerScenario
92
- })
93
- );
94
- }
95
- const failed = results.filter((result) => result.status === "failed").length;
96
- return {
97
- status: failed === 0 ? "passed" : "failed",
98
- scenarioSummary: {
99
- total: results.length,
100
- passed: results.length - failed,
101
- failed,
102
- scenarios: results
103
- }
104
- };
105
- }
106
- async function runScenario(input) {
107
- const actualSteps = input.scenario.given.length + input.scenario.when.length;
108
- if (actualSteps > input.maxStepsPerScenario) {
109
- return {
110
- id: input.scenario.id,
111
- status: "failed",
112
- diagnostic: {
113
- kind: "limit",
114
- message: `Scenario contains ${actualSteps} replay steps, exceeding maxStepsPerScenario limit ${input.maxStepsPerScenario}.`,
115
- actualSteps,
116
- maxStepsPerScenario: input.maxStepsPerScenario
117
- }
118
- };
119
- }
120
- let replay;
121
- try {
122
- replay = await replayScenario({
123
- game: input.reducer,
124
- scenario: input.scenario
125
- });
126
- } catch (error) {
127
- return {
128
- id: input.scenario.id,
129
- status: "failed",
130
- diagnostic: replayDiagnostic(error)
131
- };
132
- }
133
- try {
134
- await assertScenario({ replay, assertion: input.scenario.then });
135
- return { id: input.scenario.id, status: "passed" };
136
- } catch (error) {
137
- return {
138
- id: input.scenario.id,
139
- status: "failed",
140
- diagnostic: {
141
- kind: "assertion",
142
- message: boundedMessage(error)
143
- }
144
- };
145
- }
146
- }
147
- function assertCandidateInputFields(input) {
148
- for (const field of Object.keys(input)) {
149
- if (!CANDIDATE_INPUT_FIELDS.has(field)) {
150
- throw new Error(
151
- `Candidate verification input contains unsupported field '${field}'.`
152
- );
153
- }
154
- }
155
- }
156
- function assertPositiveInteger(value, field) {
157
- if (!Number.isSafeInteger(value) || value < 1) {
158
- throw new Error(`${field} must be a positive safe integer.`);
159
- }
160
- }
161
- function normalizeScenarios(input) {
162
- if (typeof input !== "object" || input === null) {
163
- throw new Error(
164
- "Candidate verification scenarios must be an array or record."
165
- );
166
- }
167
- const scenarios = Array.isArray(input) ? [...input] : Object.values(input);
168
- const seenIds = /* @__PURE__ */ new Set();
169
- for (const scenario of scenarios) {
170
- if (typeof scenario?.id !== "string" || scenario.id.length === 0) {
171
- throw new Error("Candidate verification scenario id is required.");
172
- }
173
- if (seenIds.has(scenario.id)) {
174
- throw new Error(
175
- `Candidate verification scenario id '${scenario.id}' is duplicated.`
176
- );
177
- }
178
- seenIds.add(scenario.id);
179
- }
180
- return scenarios;
181
- }
182
- function replayDiagnostic(error) {
183
- if (error instanceof ScenarioReplayError) {
184
- return {
185
- kind: "replay",
186
- message: boundedMessage(error),
187
- scenarioId: error.scenarioId,
188
- segment: error.segment,
189
- index: error.index,
190
- interactionId: error.interactionId,
191
- errorCode: error.errorCode,
192
- ...error.reducerMessage === void 0 ? {} : { reducerMessage: boundedText(error.reducerMessage) },
193
- trace: error.trace.slice(0, MAX_DIAGNOSTIC_TRACE_ENTRIES)
194
- };
195
- }
196
- return { kind: "replay", message: boundedMessage(error) };
197
- }
198
- function boundedMessage(error) {
199
- return boundedText(error instanceof Error ? error.message : String(error));
200
- }
201
- function boundedText(value) {
202
- return value.slice(0, MAX_DIAGNOSTIC_MESSAGE_LENGTH);
203
- }
204
- export {
205
- digestScenarioProjection,
206
- materializeScenarioRuntimeCheckpoint,
207
- resolveScenarioCommandParams,
208
- runCandidateVerification,
209
- scenarioProjectionInputMetadata,
210
- scenarioProjectionParityFromInspectNode
211
- };
212
- //# sourceMappingURL=testing-runtime.js.map