@dreamboard-games/sdk 0.4.0-alpha.13 → 0.4.0-alpha.14

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 (81) hide show
  1. package/README.md +29 -11
  2. package/dist/authoring/index.d.ts +3 -6
  3. package/dist/authoring/index.js +2 -2
  4. package/dist/authoring-compiler.d.ts +3 -3
  5. package/dist/authoring-compiler.js +3 -4
  6. package/dist/authoring-materialize-cli.js +5 -6
  7. package/dist/authoring-materialize-cli.js.map +1 -1
  8. package/dist/browser-interaction.d.ts +21 -21
  9. package/dist/{chunk-3PFDHTR7.js → chunk-3VSOH3TZ.js} +29 -2
  10. package/dist/chunk-3VSOH3TZ.js.map +1 -0
  11. package/dist/{chunk-OFIDC7DJ.js → chunk-73YISGYO.js} +4 -4
  12. package/dist/chunk-73YISGYO.js.map +1 -0
  13. package/dist/{chunk-YNW3KBDE.js → chunk-7QKE5BFU.js} +2 -2
  14. package/dist/{chunk-KZFHTUI5.js → chunk-CHOXM43O.js} +4 -4
  15. package/dist/chunk-CSIEFYTC.js +9 -0
  16. package/dist/chunk-CSIEFYTC.js.map +1 -0
  17. package/dist/{chunk-MLFHVYF7.js → chunk-KH6AET7P.js} +4 -4
  18. package/dist/chunk-KH6AET7P.js.map +1 -0
  19. package/dist/{chunk-MPVC2SU6.js → chunk-LMHCGCA6.js} +2 -2
  20. package/dist/{chunk-WAQUD4IG.js → chunk-NLZDRIVW.js} +16 -16
  21. package/dist/{chunk-5XTAQ4EQ.js → chunk-TO6WRLRN.js} +2 -2
  22. package/dist/{chunk-42HQLHVA.js → chunk-VJVKGWHW.js} +4 -7
  23. package/dist/chunk-VJVKGWHW.js.map +1 -0
  24. package/dist/{chunk-YOLIZMXR.js → chunk-VRRR6QZT.js} +3 -3
  25. package/dist/{chunk-YOLIZMXR.js.map → chunk-VRRR6QZT.js.map} +1 -1
  26. package/dist/{chunk-XDGRC6OR.js → chunk-WASWAYYX.js} +3 -3
  27. package/dist/{chunk-7JBPOJOF.js → chunk-ZGQGFXFG.js} +9 -9
  28. package/dist/{index.d-C7Ztirg6.d.ts → index.d-90ms7Mwh.d.ts} +124 -115
  29. package/dist/index.js +2 -2
  30. package/dist/package-set.d.ts +2 -2
  31. package/dist/package-set.js +2 -2
  32. package/dist/reducer/advanced.js +3 -3
  33. package/dist/reducer-contract.d.ts +1 -1
  34. package/dist/reducer-contract.js +3 -1
  35. package/dist/reducer.d.ts +1 -1
  36. package/dist/reducer.js +3 -3
  37. package/dist/reference-games/index.d.ts +29 -11
  38. package/dist/reference-games/index.js +43 -45
  39. package/dist/reference-games/index.js.map +1 -1
  40. package/dist/runtime/primitives.js +4 -4
  41. package/dist/runtime/workspace-contract.js +8 -8
  42. package/dist/runtime.js +12 -12
  43. package/dist/testing-compiler.d.ts +1 -1
  44. package/dist/testing-compiler.js +1 -4
  45. package/dist/testing-compiler.js.map +1 -1
  46. package/dist/testing-runtime.d.ts +3 -3
  47. package/dist/testing-runtime.js +5 -5
  48. package/dist/testing.d.ts +5 -140
  49. package/dist/testing.js +5 -450
  50. package/dist/testing.js.map +1 -1
  51. package/dist/{types-B-FI0jrx.d.ts → types-Cs_Jp0cf.d.ts} +1 -1
  52. package/dist/ui/components.js +1 -1
  53. package/dist/ui.js +2 -2
  54. package/package.json +22 -29
  55. package/REFERENCE.md +0 -25375
  56. package/dist/chunk-3PFDHTR7.js.map +0 -1
  57. package/dist/chunk-42HQLHVA.js.map +0 -1
  58. package/dist/chunk-MLFHVYF7.js.map +0 -1
  59. package/dist/chunk-OFIDC7DJ.js.map +0 -1
  60. package/dist/chunk-THWT4V3Z.js +0 -12
  61. package/dist/chunk-THWT4V3Z.js.map +0 -1
  62. package/dist/chunk-UNVCT5Z7.js +0 -73
  63. package/dist/chunk-UNVCT5Z7.js.map +0 -1
  64. package/dist/chunk-UTSBXZAM.js +0 -435
  65. package/dist/chunk-UTSBXZAM.js.map +0 -1
  66. package/dist/chunk-YN5W67YL.js +0 -174
  67. package/dist/chunk-YN5W67YL.js.map +0 -1
  68. package/dist/reference-game-compiler.d.ts +0 -45
  69. package/dist/reference-game-compiler.js +0 -25
  70. package/dist/reference-game-compiler.js.map +0 -1
  71. package/dist/reference-game-source-manifest-cli.d.ts +0 -1
  72. package/dist/reference-game-source-manifest-cli.js +0 -84
  73. package/dist/reference-game-source-manifest-cli.js.map +0 -1
  74. package/dist/schema-CJc0UfjJ.d.ts +0 -216
  75. /package/dist/{chunk-YNW3KBDE.js.map → chunk-7QKE5BFU.js.map} +0 -0
  76. /package/dist/{chunk-KZFHTUI5.js.map → chunk-CHOXM43O.js.map} +0 -0
  77. /package/dist/{chunk-MPVC2SU6.js.map → chunk-LMHCGCA6.js.map} +0 -0
  78. /package/dist/{chunk-WAQUD4IG.js.map → chunk-NLZDRIVW.js.map} +0 -0
  79. /package/dist/{chunk-5XTAQ4EQ.js.map → chunk-TO6WRLRN.js.map} +0 -0
  80. /package/dist/{chunk-XDGRC6OR.js.map → chunk-WASWAYYX.js.map} +0 -0
  81. /package/dist/{chunk-7JBPOJOF.js.map → chunk-ZGQGFXFG.js.map} +0 -0
@@ -1,435 +0,0 @@
1
- import {
2
- REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION,
3
- parseReferenceGameManifestV4,
4
- parseReferenceGameSourceManifest
5
- } from "./chunk-YN5W67YL.js";
6
- import {
7
- compareReferenceGameCanonicalStrings,
8
- computeReferenceGameSourceFingerprint
9
- } from "./chunk-UNVCT5Z7.js";
10
- import {
11
- WORKSPACE_CODEGEN_OWNERSHIP
12
- } from "./chunk-HIH6Y4FA.js";
13
-
14
- // src/reference-games/source-inventory-policy-core.mjs
15
- var CANONICAL_REFERENCE_GAME_IDS = Object.freeze([
16
- "automa-river-rival",
17
- "deck-building-market",
18
- "hearts",
19
- "hex-network-trading",
20
- "multiplayer-ranking-and-ties",
21
- "roll-and-write-scorecard",
22
- "simultaneous-card-drafting",
23
- "solo-countdown-puzzle",
24
- "worker-placement-tableau"
25
- ]);
26
- function createReferenceGameSourceInventoryPolicy(ownership) {
27
- return Object.freeze({
28
- schemaVersion: 1,
29
- workspaceOwnershipVersion: ownership.version,
30
- excludedGameRelativePaths: Object.freeze(
31
- [...ownership.dynamic.generatedFiles].sort()
32
- ),
33
- excludedGameRelativePrefixes: Object.freeze(
34
- [
35
- ".dreamboard/",
36
- ".turbo/",
37
- "build/",
38
- "coverage/",
39
- "dist/",
40
- "node_modules/",
41
- "playwright-report/",
42
- "test-results/",
43
- "test/bases/",
44
- "test/generated/",
45
- "test/screenshots/"
46
- ].sort()
47
- )
48
- });
49
- }
50
- function referenceGamePathIdentity(repositoryPath) {
51
- const prefix = "examples/reference-games/";
52
- if (!repositoryPath.startsWith(prefix)) return null;
53
- const remainder = repositoryPath.slice(prefix.length);
54
- const separator = remainder.indexOf("/");
55
- if (separator < 1) return null;
56
- const gameId = remainder.slice(0, separator);
57
- if (!/^[a-z0-9][a-z0-9-]*$/u.test(gameId)) return null;
58
- return { gameId, relativePath: remainder.slice(separator + 1) };
59
- }
60
- function classifyReferenceGameSourcePath(repositoryPath, policy) {
61
- const identity = referenceGamePathIdentity(repositoryPath);
62
- if (!identity) return "included";
63
- if (policy.excludedGameRelativePaths.includes(identity.relativePath)) {
64
- return "workspace-generated";
65
- }
66
- const matchedPrefix = policy.excludedGameRelativePrefixes.find(
67
- (prefix) => identity.relativePath.startsWith(prefix)
68
- );
69
- if (!matchedPrefix) return "included";
70
- if (matchedPrefix === "test/generated/") return "test-generated";
71
- if (matchedPrefix === "test/bases/") return "test-base";
72
- if (matchedPrefix === "test/screenshots/") return "obsolete-screenshot";
73
- return "derived-output";
74
- }
75
- function shouldDescendIntoReferenceGameDirectory(repositoryPath, policy) {
76
- const normalized = repositoryPath.endsWith("/") ? repositoryPath : `${repositoryPath}/`;
77
- const identity = referenceGamePathIdentity(normalized);
78
- if (!identity) return true;
79
- return !policy.excludedGameRelativePrefixes.some(
80
- (prefix) => identity.relativePath.startsWith(prefix)
81
- );
82
- }
83
-
84
- // src/reference-games/source-inventory-policy.ts
85
- var REFERENCE_GAME_SOURCE_INVENTORY_POLICY = createReferenceGameSourceInventoryPolicy(WORKSPACE_CODEGEN_OWNERSHIP);
86
- function classifyReferenceGameSourcePath2(repositoryPath) {
87
- return classifyReferenceGameSourcePath(repositoryPath, REFERENCE_GAME_SOURCE_INVENTORY_POLICY);
88
- }
89
- function isReferenceGameSourceObject(repositoryPath) {
90
- return classifyReferenceGameSourcePath2(repositoryPath) === "included";
91
- }
92
- function shouldDescendIntoReferenceGameDirectory2(repositoryPath) {
93
- return shouldDescendIntoReferenceGameDirectory(repositoryPath, REFERENCE_GAME_SOURCE_INVENTORY_POLICY);
94
- }
95
-
96
- // src/reference-games/source-collector.ts
97
- import { createHash } from "crypto";
98
- import { readFile, readdir, stat } from "fs/promises";
99
- import path from "path";
100
- async function collectReferenceGameSourceManifest(options) {
101
- const sourceRoot = path.resolve(options.sourceRoot);
102
- const referenceGamesRoot = path.join(sourceRoot, "examples/reference-games");
103
- const gameIds = await listGameIds(referenceGamesRoot);
104
- if (gameIds.length === 0) {
105
- throw new Error("No reference-game packages were found.");
106
- }
107
- const objects = await collectReferenceGameSourceObjects({
108
- referenceGamesRoot,
109
- sourceRoot
110
- });
111
- const games = await Promise.all(
112
- gameIds.map(async (gameId) => {
113
- const gameRoot = path.join(referenceGamesRoot, gameId);
114
- const metadata = parseReferenceGameManifestV4(
115
- await readJson(path.join(gameRoot, "reference-game.json"))
116
- );
117
- return buildGameEntry({
118
- gameId,
119
- gameRoot,
120
- sourceRoot,
121
- metadata,
122
- objects
123
- });
124
- })
125
- );
126
- const payload = {
127
- inventoryPolicy: {
128
- schemaVersion: REFERENCE_GAME_SOURCE_INVENTORY_POLICY.schemaVersion,
129
- workspaceOwnershipVersion: REFERENCE_GAME_SOURCE_INVENTORY_POLICY.workspaceOwnershipVersion,
130
- excludedGameRelativePaths: [
131
- ...REFERENCE_GAME_SOURCE_INVENTORY_POLICY.excludedGameRelativePaths
132
- ],
133
- excludedGameRelativePrefixes: [
134
- ...REFERENCE_GAME_SOURCE_INVENTORY_POLICY.excludedGameRelativePrefixes
135
- ]
136
- },
137
- games: games.sort(
138
- (left, right) => compareReferenceGameCanonicalStrings(left.id, right.id)
139
- ),
140
- objects: objects.sort(
141
- (left, right) => compareReferenceGameCanonicalStrings(left.path, right.path)
142
- )
143
- };
144
- return parseReferenceGameSourceManifest({
145
- schemaVersion: REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION,
146
- manifestType: "dreamboard.reference-game-source",
147
- sourceFingerprint: computeReferenceGameSourceFingerprint(payload),
148
- payload,
149
- provenance: options.provenance
150
- });
151
- }
152
- async function collectReferenceGameSourceObjects(options) {
153
- const files = await walkFiles(options.referenceGamesRoot, {
154
- shouldDescend: (directory) => shouldDescendIntoReferenceGameDirectory2(
155
- toPosix(path.relative(options.sourceRoot, directory))
156
- )
157
- });
158
- const objects = [];
159
- for (const relative of files) {
160
- const absolute = path.join(options.referenceGamesRoot, relative);
161
- const repositoryPath = toPosix(path.relative(options.sourceRoot, absolute));
162
- if (!isReferenceGameSourceObject(repositoryPath)) continue;
163
- const content = await readFile(absolute);
164
- objects.push({
165
- path: repositoryPath,
166
- sha256: `sha256:${sha256Buffer(content)}`,
167
- byteLength: content.length
168
- });
169
- }
170
- return objects;
171
- }
172
- async function buildGameEntry(options) {
173
- const root = `examples/reference-games/${options.gameId}`;
174
- const workspace = options.metadata.workspace;
175
- const packageJsonPath = path.join(options.gameRoot, "package.json");
176
- const lockfilePath = path.join(options.gameRoot, "pnpm-lock.yaml");
177
- const packageJson = await readJson(packageJsonPath);
178
- const sdkSpecifier = findSdkSpecifier(packageJson);
179
- if (!sdkSpecifier) {
180
- throw new Error(`${root}/package.json must declare @dreamboard-games/sdk.`);
181
- }
182
- const mechanics = options.metadata.mechanics;
183
- if (mechanics.length === 0) {
184
- throw new Error(`${root}/reference-game.json must declare mechanics.`);
185
- }
186
- const teaching = options.metadata.teaching;
187
- const entry = {
188
- id: options.gameId,
189
- root,
190
- sourceSha256: sourceSha256ForGameObjects(options.objects, root),
191
- packageJsonSha256: `sha256:${await sha256File(packageJsonPath)}`,
192
- lockfileSha256: `sha256:${await sha256File(lockfilePath)}`,
193
- sdkSpecifier,
194
- manifest: await firstExistingRelative(options.gameRoot, [
195
- workspace.manifest,
196
- "manifest.ts",
197
- "reference-game.json"
198
- ]),
199
- reducer: await firstExistingRelative(options.gameRoot, [
200
- workspace.reducer,
201
- "app/game.ts"
202
- ]),
203
- ui: await firstExistingRelative(options.gameRoot, [
204
- workspace.ui,
205
- "ui/index.tsx"
206
- ]),
207
- behaviorScenarios: await collectScenarioEntries(
208
- options.gameRoot,
209
- "test/scenarios"
210
- ),
211
- uiScenarios: await collectScenarioEntries(
212
- options.gameRoot,
213
- "test/ui-scenarios"
214
- ),
215
- mechanics,
216
- readFirst: teaching.readFirst.length > 0 ? teaching.readFirst : await deriveReadFirst(options.gameRoot, options.sourceRoot)
217
- };
218
- assertGameEntryPathsAreSourceObjects(entry, options.objects);
219
- return entry;
220
- }
221
- function assertGameEntryPathsAreSourceObjects(entry, objects) {
222
- const objectPaths = new Set(
223
- objects.map(({ path: objectPath }) => objectPath)
224
- );
225
- const paths = [
226
- entry.manifest,
227
- entry.reducer,
228
- entry.ui,
229
- ...entry.behaviorScenarios,
230
- ...entry.uiScenarios,
231
- ...entry.readFirst
232
- ];
233
- for (const relativePath of paths) {
234
- if (path.isAbsolute(relativePath) || relativePath.split(/[\\/]+/u).includes("..")) {
235
- throw new Error(
236
- `${entry.root} source entry must stay within the game root: ${relativePath}.`
237
- );
238
- }
239
- const repositoryPath = path.posix.join(entry.root, toPosix(relativePath));
240
- if (!objectPaths.has(repositoryPath)) {
241
- throw new Error(
242
- `${entry.root} source entry is missing from the authored object inventory: ${relativePath}.`
243
- );
244
- }
245
- }
246
- }
247
- async function listGameIds(referenceGamesRoot) {
248
- const entries = await readdir(referenceGamesRoot, { withFileTypes: true });
249
- const discovered = [];
250
- for (const entry of entries.filter(
251
- (entry2) => entry2.isDirectory() && /^[a-z0-9][a-z0-9-]*$/u.test(entry2.name)
252
- ).sort(
253
- (left, right) => compareReferenceGameCanonicalStrings(left.name, right.name)
254
- )) {
255
- if (await isFile(
256
- path.join(referenceGamesRoot, entry.name, "reference-game.json")
257
- )) {
258
- discovered.push(entry.name);
259
- }
260
- }
261
- const expected = [...CANONICAL_REFERENCE_GAME_IDS];
262
- const missing = expected.filter((gameId) => !discovered.includes(gameId));
263
- const extra = discovered.filter((gameId) => !expected.includes(gameId));
264
- if (missing.length > 0 || extra.length > 0) {
265
- throw new Error(
266
- `Reference-game identity mismatch (missing: ${missing.join(", ") || "none"}; extra: ${extra.join(", ") || "none"}).`
267
- );
268
- }
269
- return expected;
270
- }
271
- async function deriveReadFirst(gameRoot, sourceRoot) {
272
- const candidates = [
273
- "README.md",
274
- "rule.md",
275
- "manifest.ts",
276
- "app/game.ts",
277
- "ui/index.tsx"
278
- ];
279
- const existing = [];
280
- for (const candidate of candidates) {
281
- if (await isFile(path.join(gameRoot, candidate))) existing.push(candidate);
282
- }
283
- if (existing.length === 0) {
284
- throw new Error(
285
- `${path.relative(sourceRoot, gameRoot)} must provide at least one readFirst file.`
286
- );
287
- }
288
- return existing.slice(0, 5);
289
- }
290
- async function firstExistingRelative(root, candidates) {
291
- const paths = candidates.filter(
292
- (candidate) => typeof candidate === "string" && candidate.length > 0
293
- );
294
- for (const candidate of paths) {
295
- if (path.isAbsolute(candidate) || candidate.includes("..")) {
296
- throw new Error(`${candidate} must be a relative path within ${root}.`);
297
- }
298
- if (await isFile(path.join(root, candidate))) return candidate;
299
- }
300
- throw new Error(`${root} must provide one of: ${paths.join(", ")}`);
301
- }
302
- async function collectScenarioEntries(gameRoot, directory) {
303
- const absolute = path.join(gameRoot, directory);
304
- if (!await isDirectory(absolute)) {
305
- throw new Error(`${gameRoot} must provide ${directory}.`);
306
- }
307
- const files = [];
308
- const rejectedDirectories = /* @__PURE__ */ new Set([
309
- "build",
310
- "dist",
311
- "generated",
312
- "node_modules"
313
- ]);
314
- async function visit(current) {
315
- const entries = await readdir(current, { withFileTypes: true });
316
- for (const entry of entries.sort(
317
- (left, right) => compareReferenceGameCanonicalStrings(left.name, right.name)
318
- )) {
319
- const entryPath = path.join(current, entry.name);
320
- if (entry.isSymbolicLink()) {
321
- throw new Error(`${entryPath} must not be a symbolic link.`);
322
- }
323
- if (entry.isDirectory()) {
324
- if (rejectedDirectories.has(entry.name)) {
325
- throw new Error(
326
- `${entryPath} is not an authored scenario directory.`
327
- );
328
- }
329
- await visit(entryPath);
330
- } else if (entry.isFile() && entry.name.endsWith(".scenario.ts")) {
331
- files.push(
332
- path.posix.join(
333
- directory,
334
- toPosix(path.relative(absolute, entryPath))
335
- )
336
- );
337
- }
338
- }
339
- }
340
- await visit(absolute);
341
- if (files.length === 0) {
342
- throw new Error(
343
- `${gameRoot} must provide at least one ${directory}/**/*.scenario.ts entry.`
344
- );
345
- }
346
- return files.sort(compareReferenceGameCanonicalStrings);
347
- }
348
- async function walkFiles(root, options = {}) {
349
- const files = [];
350
- async function visit(current) {
351
- const entries = await readdir(current, { withFileTypes: true });
352
- for (const entry of entries.sort(
353
- (left, right) => compareReferenceGameCanonicalStrings(left.name, right.name)
354
- )) {
355
- const entryPath = path.join(current, entry.name);
356
- if (entry.isDirectory()) {
357
- if (!options.shouldDescend || options.shouldDescend(entryPath)) {
358
- await visit(entryPath);
359
- }
360
- } else if (entry.isFile()) {
361
- files.push(path.relative(root, entryPath));
362
- }
363
- }
364
- }
365
- await visit(root);
366
- return files.sort();
367
- }
368
- async function readJson(filePath) {
369
- const value = JSON.parse(await readFile(filePath, "utf8"));
370
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
371
- throw new Error(`${filePath} must contain a JSON object.`);
372
- }
373
- return value;
374
- }
375
- function findSdkSpecifier(packageJson) {
376
- for (const group of ["dependencies", "devDependencies", "peerDependencies"]) {
377
- const value = objectValue(packageJson[group])["@dreamboard-games/sdk"];
378
- if (typeof value === "string" && value.length > 0) return value;
379
- }
380
- return null;
381
- }
382
- function objectValue(value) {
383
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
384
- }
385
- async function sha256File(filePath) {
386
- return sha256Buffer(await readFile(filePath));
387
- }
388
- function sourceSha256ForGameObjects(objects, gameRoot) {
389
- const hash = createHash("sha256");
390
- hash.update("reference-game-authored-objects@1\0");
391
- for (const object of objects.filter(({ path: objectPath }) => objectPath.startsWith(`${gameRoot}/`)).sort(
392
- (left, right) => compareReferenceGameCanonicalStrings(left.path, right.path)
393
- )) {
394
- hash.update(object.path.slice(gameRoot.length + 1));
395
- hash.update("\0");
396
- hash.update(object.sha256);
397
- hash.update("\0");
398
- hash.update(String(object.byteLength));
399
- hash.update("\0");
400
- }
401
- return `sha256:${hash.digest("hex")}`;
402
- }
403
- function sha256Buffer(buffer) {
404
- return createHash("sha256").update(buffer).digest("hex");
405
- }
406
- async function isFile(filePath) {
407
- return stat(filePath).then((value) => value.isFile()).catch((error) => {
408
- if (isMissingPathError(error)) return false;
409
- throw error;
410
- });
411
- }
412
- async function isDirectory(filePath) {
413
- return stat(filePath).then((value) => value.isDirectory()).catch((error) => {
414
- if (isMissingPathError(error)) return false;
415
- throw error;
416
- });
417
- }
418
- function isMissingPathError(error) {
419
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
420
- }
421
- function toPosix(value) {
422
- return value.split(path.sep).join("/");
423
- }
424
-
425
- export {
426
- CANONICAL_REFERENCE_GAME_IDS,
427
- referenceGamePathIdentity,
428
- REFERENCE_GAME_SOURCE_INVENTORY_POLICY,
429
- classifyReferenceGameSourcePath2 as classifyReferenceGameSourcePath,
430
- isReferenceGameSourceObject,
431
- shouldDescendIntoReferenceGameDirectory2 as shouldDescendIntoReferenceGameDirectory,
432
- collectReferenceGameSourceManifest,
433
- collectReferenceGameSourceObjects
434
- };
435
- //# sourceMappingURL=chunk-UTSBXZAM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/reference-games/source-inventory-policy-core.mjs","../src/reference-games/source-inventory-policy.ts","../src/reference-games/source-collector.ts"],"sourcesContent":["export const CANONICAL_REFERENCE_GAME_IDS = Object.freeze([\n \"automa-river-rival\",\n \"deck-building-market\",\n \"hearts\",\n \"hex-network-trading\",\n \"multiplayer-ranking-and-ties\",\n \"roll-and-write-scorecard\",\n \"simultaneous-card-drafting\",\n \"solo-countdown-puzzle\",\n \"worker-placement-tableau\",\n]);\n\nexport function createReferenceGameSourceInventoryPolicy(ownership) {\n return Object.freeze({\n schemaVersion: 1,\n workspaceOwnershipVersion: ownership.version,\n excludedGameRelativePaths: Object.freeze(\n [...ownership.dynamic.generatedFiles].sort(),\n ),\n excludedGameRelativePrefixes: Object.freeze(\n [\n \".dreamboard/\",\n \".turbo/\",\n \"build/\",\n \"coverage/\",\n \"dist/\",\n \"node_modules/\",\n \"playwright-report/\",\n \"test-results/\",\n \"test/bases/\",\n \"test/generated/\",\n \"test/screenshots/\",\n ].sort(),\n ),\n });\n}\n\nexport function referenceGamePathIdentity(repositoryPath) {\n const prefix = \"examples/reference-games/\";\n if (!repositoryPath.startsWith(prefix)) return null;\n const remainder = repositoryPath.slice(prefix.length);\n const separator = remainder.indexOf(\"/\");\n if (separator < 1) return null;\n const gameId = remainder.slice(0, separator);\n if (!/^[a-z0-9][a-z0-9-]*$/u.test(gameId)) return null;\n return { gameId, relativePath: remainder.slice(separator + 1) };\n}\n\nexport function classifyReferenceGameSourcePath(repositoryPath, policy) {\n const identity = referenceGamePathIdentity(repositoryPath);\n if (!identity) return \"included\";\n if (policy.excludedGameRelativePaths.includes(identity.relativePath)) {\n return \"workspace-generated\";\n }\n const matchedPrefix = policy.excludedGameRelativePrefixes.find((prefix) =>\n identity.relativePath.startsWith(prefix),\n );\n if (!matchedPrefix) return \"included\";\n if (matchedPrefix === \"test/generated/\") return \"test-generated\";\n if (matchedPrefix === \"test/bases/\") return \"test-base\";\n if (matchedPrefix === \"test/screenshots/\") return \"obsolete-screenshot\";\n return \"derived-output\";\n}\n\nexport function shouldDescendIntoReferenceGameDirectory(\n repositoryPath,\n policy,\n) {\n const normalized = repositoryPath.endsWith(\"/\")\n ? repositoryPath\n : `${repositoryPath}/`;\n const identity = referenceGamePathIdentity(normalized);\n if (!identity) return true;\n return !policy.excludedGameRelativePrefixes.some((prefix) =>\n identity.relativePath.startsWith(prefix),\n );\n}\n","import { WORKSPACE_CODEGEN_OWNERSHIP } from \"@dreamboard-games/workspace-codegen\";\n\nimport {\n CANONICAL_REFERENCE_GAME_IDS,\n classifyReferenceGameSourcePath as classifyPath,\n createReferenceGameSourceInventoryPolicy,\n referenceGamePathIdentity,\n shouldDescendIntoReferenceGameDirectory as shouldDescend,\n type ReferenceGameSourcePathClass,\n} from \"./source-inventory-policy-core.mjs\";\n\nexport const REFERENCE_GAME_SOURCE_INVENTORY_POLICY =\n createReferenceGameSourceInventoryPolicy(WORKSPACE_CODEGEN_OWNERSHIP);\n\nexport {\n CANONICAL_REFERENCE_GAME_IDS,\n referenceGamePathIdentity,\n type ReferenceGameSourcePathClass,\n};\n\nexport function classifyReferenceGameSourcePath(\n repositoryPath: string,\n): ReferenceGameSourcePathClass {\n return classifyPath(repositoryPath, REFERENCE_GAME_SOURCE_INVENTORY_POLICY);\n}\n\nexport function isReferenceGameSourceObject(repositoryPath: string): boolean {\n return classifyReferenceGameSourcePath(repositoryPath) === \"included\";\n}\n\nexport function shouldDescendIntoReferenceGameDirectory(\n repositoryPath: string,\n): boolean {\n return shouldDescend(repositoryPath, REFERENCE_GAME_SOURCE_INVENTORY_POLICY);\n}\n","import { createHash } from \"node:crypto\";\nimport { readFile, readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION,\n parseReferenceGameManifestV4,\n parseReferenceGameSourceManifest,\n type ReferenceGameSourceManifest,\n type ReferenceGameSourceProvenance,\n} from \"./schema.js\";\nimport {\n compareReferenceGameCanonicalStrings,\n computeReferenceGameSourceFingerprint,\n} from \"./canonical.js\";\nimport {\n CANONICAL_REFERENCE_GAME_IDS,\n REFERENCE_GAME_SOURCE_INVENTORY_POLICY,\n isReferenceGameSourceObject,\n shouldDescendIntoReferenceGameDirectory,\n} from \"./source-inventory-policy.js\";\n\nexport {\n CANONICAL_REFERENCE_GAME_IDS,\n REFERENCE_GAME_SOURCE_INVENTORY_POLICY,\n classifyReferenceGameSourcePath,\n isReferenceGameSourceObject,\n referenceGamePathIdentity,\n shouldDescendIntoReferenceGameDirectory,\n type ReferenceGameSourcePathClass,\n} from \"./source-inventory-policy.js\";\n\nexport async function collectReferenceGameSourceManifest(options: {\n readonly sourceRoot: string;\n readonly provenance: ReferenceGameSourceProvenance;\n}): Promise<ReferenceGameSourceManifest> {\n const sourceRoot = path.resolve(options.sourceRoot);\n const referenceGamesRoot = path.join(sourceRoot, \"examples/reference-games\");\n const gameIds = await listGameIds(referenceGamesRoot);\n if (gameIds.length === 0) {\n throw new Error(\"No reference-game packages were found.\");\n }\n const objects = await collectReferenceGameSourceObjects({\n referenceGamesRoot,\n sourceRoot,\n });\n const games = await Promise.all(\n gameIds.map(async (gameId) => {\n const gameRoot = path.join(referenceGamesRoot, gameId);\n const metadata = parseReferenceGameManifestV4(\n await readJson(path.join(gameRoot, \"reference-game.json\")),\n );\n return buildGameEntry({\n gameId,\n gameRoot,\n sourceRoot,\n metadata,\n objects,\n });\n }),\n );\n const payload = {\n inventoryPolicy: {\n schemaVersion: REFERENCE_GAME_SOURCE_INVENTORY_POLICY.schemaVersion,\n workspaceOwnershipVersion:\n REFERENCE_GAME_SOURCE_INVENTORY_POLICY.workspaceOwnershipVersion,\n excludedGameRelativePaths: [\n ...REFERENCE_GAME_SOURCE_INVENTORY_POLICY.excludedGameRelativePaths,\n ],\n excludedGameRelativePrefixes: [\n ...REFERENCE_GAME_SOURCE_INVENTORY_POLICY.excludedGameRelativePrefixes,\n ],\n },\n games: games.sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.id, right.id),\n ),\n objects: objects.sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.path, right.path),\n ),\n };\n return parseReferenceGameSourceManifest({\n schemaVersion: REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION,\n manifestType: \"dreamboard.reference-game-source\",\n sourceFingerprint: computeReferenceGameSourceFingerprint(payload),\n payload,\n provenance: options.provenance,\n });\n}\n\nexport async function collectReferenceGameSourceObjects(options: {\n readonly referenceGamesRoot: string;\n readonly sourceRoot: string;\n}): Promise<\n Array<{\n readonly path: string;\n readonly sha256: string;\n readonly byteLength: number;\n }>\n> {\n const files = await walkFiles(options.referenceGamesRoot, {\n shouldDescend: (directory) =>\n shouldDescendIntoReferenceGameDirectory(\n toPosix(path.relative(options.sourceRoot, directory)),\n ),\n });\n const objects = [];\n for (const relative of files) {\n const absolute = path.join(options.referenceGamesRoot, relative);\n const repositoryPath = toPosix(path.relative(options.sourceRoot, absolute));\n if (!isReferenceGameSourceObject(repositoryPath)) continue;\n const content = await readFile(absolute);\n objects.push({\n path: repositoryPath,\n sha256: `sha256:${sha256Buffer(content)}`,\n byteLength: content.length,\n });\n }\n return objects;\n}\n\nasync function buildGameEntry(options: {\n readonly gameId: string;\n readonly gameRoot: string;\n readonly sourceRoot: string;\n readonly metadata: ReturnType<typeof parseReferenceGameManifestV4>;\n readonly objects: readonly {\n readonly path: string;\n readonly sha256: string;\n readonly byteLength: number;\n }[];\n}) {\n const root = `examples/reference-games/${options.gameId}`;\n const workspace = options.metadata.workspace;\n const packageJsonPath = path.join(options.gameRoot, \"package.json\");\n const lockfilePath = path.join(options.gameRoot, \"pnpm-lock.yaml\");\n const packageJson = await readJson(packageJsonPath);\n const sdkSpecifier = findSdkSpecifier(packageJson);\n if (!sdkSpecifier) {\n throw new Error(`${root}/package.json must declare @dreamboard-games/sdk.`);\n }\n const mechanics = options.metadata.mechanics;\n if (mechanics.length === 0) {\n throw new Error(`${root}/reference-game.json must declare mechanics.`);\n }\n const teaching = options.metadata.teaching;\n const entry = {\n id: options.gameId,\n root,\n sourceSha256: sourceSha256ForGameObjects(options.objects, root),\n packageJsonSha256: `sha256:${await sha256File(packageJsonPath)}`,\n lockfileSha256: `sha256:${await sha256File(lockfilePath)}`,\n sdkSpecifier,\n manifest: await firstExistingRelative(options.gameRoot, [\n workspace.manifest,\n \"manifest.ts\",\n \"reference-game.json\",\n ]),\n reducer: await firstExistingRelative(options.gameRoot, [\n workspace.reducer,\n \"app/game.ts\",\n ]),\n ui: await firstExistingRelative(options.gameRoot, [\n workspace.ui,\n \"ui/index.tsx\",\n ]),\n behaviorScenarios: await collectScenarioEntries(\n options.gameRoot,\n \"test/scenarios\",\n ),\n uiScenarios: await collectScenarioEntries(\n options.gameRoot,\n \"test/ui-scenarios\",\n ),\n mechanics,\n readFirst:\n teaching.readFirst.length > 0\n ? teaching.readFirst\n : await deriveReadFirst(options.gameRoot, options.sourceRoot),\n };\n assertGameEntryPathsAreSourceObjects(entry, options.objects);\n return entry;\n}\n\nfunction assertGameEntryPathsAreSourceObjects(\n entry: {\n readonly root: string;\n readonly manifest: string;\n readonly reducer: string;\n readonly ui: string;\n readonly behaviorScenarios: readonly string[];\n readonly uiScenarios: readonly string[];\n readonly readFirst: readonly string[];\n },\n objects: readonly { readonly path: string }[],\n): void {\n const objectPaths = new Set(\n objects.map(({ path: objectPath }) => objectPath),\n );\n const paths = [\n entry.manifest,\n entry.reducer,\n entry.ui,\n ...entry.behaviorScenarios,\n ...entry.uiScenarios,\n ...entry.readFirst,\n ];\n for (const relativePath of paths) {\n if (\n path.isAbsolute(relativePath) ||\n relativePath.split(/[\\\\/]+/u).includes(\"..\")\n ) {\n throw new Error(\n `${entry.root} source entry must stay within the game root: ${relativePath}.`,\n );\n }\n const repositoryPath = path.posix.join(entry.root, toPosix(relativePath));\n if (!objectPaths.has(repositoryPath)) {\n throw new Error(\n `${entry.root} source entry is missing from the authored object inventory: ${relativePath}.`,\n );\n }\n }\n}\n\nasync function listGameIds(referenceGamesRoot: string): Promise<string[]> {\n const entries = await readdir(referenceGamesRoot, { withFileTypes: true });\n const discovered: string[] = [];\n for (const entry of entries\n .filter(\n (entry) =>\n entry.isDirectory() && /^[a-z0-9][a-z0-9-]*$/u.test(entry.name),\n )\n .sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.name, right.name),\n )) {\n if (\n await isFile(\n path.join(referenceGamesRoot, entry.name, \"reference-game.json\"),\n )\n ) {\n discovered.push(entry.name);\n }\n }\n const expected = [...CANONICAL_REFERENCE_GAME_IDS];\n const missing = expected.filter((gameId) => !discovered.includes(gameId));\n const extra = discovered.filter((gameId) => !expected.includes(gameId));\n if (missing.length > 0 || extra.length > 0) {\n throw new Error(\n `Reference-game identity mismatch (missing: ${missing.join(\", \") || \"none\"}; extra: ${extra.join(\", \") || \"none\"}).`,\n );\n }\n return expected;\n}\n\nasync function deriveReadFirst(gameRoot: string, sourceRoot: string) {\n const candidates = [\n \"README.md\",\n \"rule.md\",\n \"manifest.ts\",\n \"app/game.ts\",\n \"ui/index.tsx\",\n ];\n const existing = [];\n for (const candidate of candidates) {\n if (await isFile(path.join(gameRoot, candidate))) existing.push(candidate);\n }\n if (existing.length === 0) {\n throw new Error(\n `${path.relative(sourceRoot, gameRoot)} must provide at least one readFirst file.`,\n );\n }\n return existing.slice(0, 5);\n}\n\nasync function firstExistingRelative(root: string, candidates: unknown[]) {\n const paths = candidates.filter(\n (candidate): candidate is string =>\n typeof candidate === \"string\" && candidate.length > 0,\n );\n for (const candidate of paths) {\n if (path.isAbsolute(candidate) || candidate.includes(\"..\")) {\n throw new Error(`${candidate} must be a relative path within ${root}.`);\n }\n if (await isFile(path.join(root, candidate))) return candidate;\n }\n throw new Error(`${root} must provide one of: ${paths.join(\", \")}`);\n}\n\nasync function collectScenarioEntries(gameRoot: string, directory: string) {\n const absolute = path.join(gameRoot, directory);\n if (!(await isDirectory(absolute))) {\n throw new Error(`${gameRoot} must provide ${directory}.`);\n }\n const files: string[] = [];\n const rejectedDirectories = new Set([\n \"build\",\n \"dist\",\n \"generated\",\n \"node_modules\",\n ]);\n async function visit(current: string): Promise<void> {\n const entries = await readdir(current, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.name, right.name),\n )) {\n const entryPath = path.join(current, entry.name);\n if (entry.isSymbolicLink()) {\n throw new Error(`${entryPath} must not be a symbolic link.`);\n }\n if (entry.isDirectory()) {\n if (rejectedDirectories.has(entry.name)) {\n throw new Error(\n `${entryPath} is not an authored scenario directory.`,\n );\n }\n await visit(entryPath);\n } else if (entry.isFile() && entry.name.endsWith(\".scenario.ts\")) {\n files.push(\n path.posix.join(\n directory,\n toPosix(path.relative(absolute, entryPath)),\n ),\n );\n }\n }\n }\n await visit(absolute);\n if (files.length === 0) {\n throw new Error(\n `${gameRoot} must provide at least one ${directory}/**/*.scenario.ts entry.`,\n );\n }\n return files.sort(compareReferenceGameCanonicalStrings);\n}\n\nasync function walkFiles(\n root: string,\n options: { readonly shouldDescend?: (directory: string) => boolean } = {},\n): Promise<string[]> {\n const files: string[] = [];\n async function visit(current: string) {\n const entries = await readdir(current, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.name, right.name),\n )) {\n const entryPath = path.join(current, entry.name);\n if (entry.isDirectory()) {\n if (!options.shouldDescend || options.shouldDescend(entryPath)) {\n await visit(entryPath);\n }\n } else if (entry.isFile()) {\n files.push(path.relative(root, entryPath));\n }\n }\n }\n await visit(root);\n return files.sort();\n}\n\nasync function readJson(filePath: string): Promise<Record<string, unknown>> {\n const value = JSON.parse(await readFile(filePath, \"utf8\")) as unknown;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(`${filePath} must contain a JSON object.`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction findSdkSpecifier(packageJson: Record<string, unknown>): string | null {\n for (const group of [\"dependencies\", \"devDependencies\", \"peerDependencies\"]) {\n const value = objectValue(packageJson[group])[\"@dreamboard-games/sdk\"];\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return null;\n}\n\nfunction objectValue(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nasync function sha256File(filePath: string): Promise<string> {\n return sha256Buffer(await readFile(filePath));\n}\n\nfunction sourceSha256ForGameObjects(\n objects: readonly {\n readonly path: string;\n readonly sha256: string;\n readonly byteLength: number;\n }[],\n gameRoot: string,\n) {\n const hash = createHash(\"sha256\");\n hash.update(\"reference-game-authored-objects@1\\0\");\n for (const object of objects\n .filter(({ path: objectPath }) => objectPath.startsWith(`${gameRoot}/`))\n .sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.path, right.path),\n )) {\n hash.update(object.path.slice(gameRoot.length + 1));\n hash.update(\"\\0\");\n hash.update(object.sha256);\n hash.update(\"\\0\");\n hash.update(String(object.byteLength));\n hash.update(\"\\0\");\n }\n return `sha256:${hash.digest(\"hex\")}`;\n}\n\nfunction sha256Buffer(buffer: Uint8Array): string {\n return createHash(\"sha256\").update(buffer).digest(\"hex\");\n}\n\nasync function isFile(filePath: string): Promise<boolean> {\n return stat(filePath)\n .then((value) => value.isFile())\n .catch((error: unknown) => {\n if (isMissingPathError(error)) return false;\n throw error;\n });\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n return stat(filePath)\n .then((value) => value.isDirectory())\n .catch((error: unknown) => {\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":["classifyReferenceGameSourcePath","shouldDescendIntoReferenceGameDirectory","shouldDescendIntoReferenceGameDirectory","entry"]}
@@ -1,174 +0,0 @@
1
- import {
2
- computeReferenceGameSourceFingerprint
3
- } from "./chunk-UNVCT5Z7.js";
4
-
5
- // src/reference-games/schema.ts
6
- import { z } from "zod";
7
- var REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION = 3;
8
- var REFERENCE_GAME_MANIFEST_SCHEMA_VERSION = 4;
9
- var referenceGameSha256DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
10
- var referenceGameSourceObjectSchema = z.object({
11
- path: z.string().min(1),
12
- sha256: referenceGameSha256DigestSchema,
13
- byteLength: z.number().int().nonnegative()
14
- }).strict();
15
- var referenceGameSourceEntrySchema = z.object({
16
- id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
17
- root: z.string().regex(/^examples\/reference-games\/[a-z0-9-]+$/),
18
- sourceSha256: referenceGameSha256DigestSchema,
19
- packageJsonSha256: referenceGameSha256DigestSchema,
20
- lockfileSha256: referenceGameSha256DigestSchema,
21
- sdkSpecifier: z.string().min(1),
22
- manifest: z.string().min(1),
23
- reducer: z.string().min(1),
24
- ui: z.string().min(1),
25
- behaviorScenarios: z.array(z.string().min(1)).min(1),
26
- uiScenarios: z.array(z.string().min(1)).min(1),
27
- mechanics: z.array(z.string().min(1)).min(1),
28
- readFirst: z.array(z.string().min(1)).min(1)
29
- }).strict();
30
- var referenceGameSourceInventoryPolicySchema = z.object({
31
- schemaVersion: z.literal(1),
32
- workspaceOwnershipVersion: z.number().int().positive(),
33
- excludedGameRelativePaths: z.array(z.string().min(1)),
34
- excludedGameRelativePrefixes: z.array(z.string().min(1))
35
- }).strict();
36
- var referenceGameSourceManifestPayloadSchema = z.object({
37
- inventoryPolicy: referenceGameSourceInventoryPolicySchema,
38
- games: z.array(referenceGameSourceEntrySchema).min(1),
39
- objects: z.array(referenceGameSourceObjectSchema).min(1)
40
- }).strict();
41
- var referenceGameSourceProvenanceSchema = z.discriminatedUnion(
42
- "kind",
43
- [
44
- z.object({ kind: z.literal("worktree") }).strict(),
45
- z.object({
46
- kind: z.literal("git"),
47
- repository: z.literal("dreamboard-games/dreamboard-sdk"),
48
- revision: z.string().regex(/^[a-f0-9]{40}$/)
49
- }).strict()
50
- ]
51
- );
52
- var referenceGameSourceManifestSchema = z.object({
53
- schemaVersion: z.literal(REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION),
54
- manifestType: z.literal("dreamboard.reference-game-source"),
55
- sourceFingerprint: referenceGameSha256DigestSchema,
56
- payload: referenceGameSourceManifestPayloadSchema,
57
- provenance: referenceGameSourceProvenanceSchema
58
- }).strict().superRefine((value, context) => {
59
- const fingerprint = computeReferenceGameSourceFingerprint(value.payload);
60
- if (value.sourceFingerprint !== fingerprint) {
61
- context.addIssue({
62
- code: "custom",
63
- path: ["sourceFingerprint"],
64
- message: "sourceFingerprint must match the canonical authored-object inventory"
65
- });
66
- }
67
- });
68
- var referenceGameIdSchema = z.string().regex(/^[a-z0-9][a-z0-9-]*$/);
69
- var referenceGameWorkspacePathSchema = z.string().min(1);
70
- var referenceGameAssetPathSchema = z.string().regex(/^assets\/(?:[A-Za-z0-9._-]+\/)*[A-Za-z0-9._-]+$/).refine(
71
- (value) => value.split("/").every((segment) => segment !== "." && segment !== ".."),
72
- { message: "asset path must stay inside the game assets directory" }
73
- );
74
- var referenceGameWorkspaceSchema = z.object({
75
- manifest: referenceGameWorkspacePathSchema,
76
- reducer: referenceGameWorkspacePathSchema,
77
- ui: referenceGameWorkspacePathSchema
78
- }).strict();
79
- var referenceGameTeachingSchema = z.object({
80
- whatThisTeaches: z.array(z.string().min(1)).min(1),
81
- whenToCopyThisPattern: z.array(z.string().min(1)).min(1),
82
- readFirst: z.array(referenceGameWorkspacePathSchema).min(1)
83
- }).strict();
84
- var referenceGameDemoReleaseSchema = z.object({
85
- slug: referenceGameIdSchema,
86
- name: z.string().min(1),
87
- description: z.string().min(1),
88
- overview: z.string().min(1),
89
- creator: z.string().min(1),
90
- minPlayers: z.number().int().positive(),
91
- maxPlayers: z.number().int().positive(),
92
- playTimeMinMinutes: z.number().int().positive(),
93
- playTimeMaxMinutes: z.number().int().positive(),
94
- difficulty: z.number().int().min(1).max(5),
95
- mechanics: z.array(z.string().min(1)).min(1),
96
- categories: z.array(z.string().min(1)).min(1),
97
- thumbnailPath: referenceGameAssetPathSchema,
98
- estimatedMinutes: z.number().int().positive(),
99
- demoPlayerCount: z.number().int().positive()
100
- }).strict().superRefine((value, context) => {
101
- if (value.maxPlayers < value.minPlayers) {
102
- context.addIssue({
103
- code: "custom",
104
- path: ["maxPlayers"],
105
- message: "maxPlayers must be greater than or equal to minPlayers"
106
- });
107
- }
108
- if (value.playTimeMaxMinutes < value.playTimeMinMinutes) {
109
- context.addIssue({
110
- code: "custom",
111
- path: ["playTimeMaxMinutes"],
112
- message: "playTimeMaxMinutes must be greater than or equal to playTimeMinMinutes"
113
- });
114
- }
115
- });
116
- var referenceGameRightsSchema = z.object({
117
- mechanicsProvenance: z.string().min(1),
118
- sourceCode: z.string().min(1),
119
- codeLicense: z.string().min(1),
120
- ruleText: z.string().min(1),
121
- artwork: z.string().min(1),
122
- assetLicenseManifest: z.string().min(1),
123
- thirdPartyMarks: z.array(z.string()),
124
- reviewStatus: z.literal("approved"),
125
- reviewedBy: z.string().min(1),
126
- reviewedAt: z.string().min(1)
127
- }).strict();
128
- var referenceGameSdkPolicySchema = z.object({
129
- dependency: z.literal("@dreamboard-games/sdk"),
130
- versionPolicy: z.literal("exact")
131
- }).strict();
132
- var referenceGameManifestV4Schema = z.object({
133
- schemaVersion: z.literal(REFERENCE_GAME_MANIFEST_SCHEMA_VERSION),
134
- id: referenceGameIdSchema,
135
- displayName: z.string().min(1),
136
- workspace: referenceGameWorkspaceSchema,
137
- teaching: referenceGameTeachingSchema,
138
- demoRelease: referenceGameDemoReleaseSchema.optional(),
139
- mechanics: z.array(z.string().min(1)).min(1),
140
- uiPatterns: z.array(z.string().min(1)).min(1),
141
- rights: referenceGameRightsSchema,
142
- sdk: referenceGameSdkPolicySchema
143
- }).strict();
144
- function parseReferenceGameSourceManifest(value) {
145
- return referenceGameSourceManifestSchema.parse(value);
146
- }
147
- function parseReferenceGameManifestV4(value) {
148
- return referenceGameManifestV4Schema.parse(value);
149
- }
150
- function isPackageableReferenceGame(game) {
151
- return game.demoRelease !== void 0;
152
- }
153
-
154
- export {
155
- REFERENCE_GAME_SOURCE_MANIFEST_SCHEMA_VERSION,
156
- REFERENCE_GAME_MANIFEST_SCHEMA_VERSION,
157
- referenceGameSha256DigestSchema,
158
- referenceGameSourceObjectSchema,
159
- referenceGameSourceEntrySchema,
160
- referenceGameSourceInventoryPolicySchema,
161
- referenceGameSourceManifestPayloadSchema,
162
- referenceGameSourceProvenanceSchema,
163
- referenceGameSourceManifestSchema,
164
- referenceGameWorkspaceSchema,
165
- referenceGameTeachingSchema,
166
- referenceGameDemoReleaseSchema,
167
- referenceGameRightsSchema,
168
- referenceGameSdkPolicySchema,
169
- referenceGameManifestV4Schema,
170
- parseReferenceGameSourceManifest,
171
- parseReferenceGameManifestV4,
172
- isPackageableReferenceGame
173
- };
174
- //# sourceMappingURL=chunk-YN5W67YL.js.map