@dreamboard-games/workspace-codegen 0.1.2 → 0.1.4
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.
- package/dist/manifest-contract.js +38 -14
- package/dist/seeds.js +307 -260
- package/package.json +2 -2
- package/src/authoring-benchmark.test.ts +146 -29
- package/src/manifest-contract.test.ts +1 -1
- package/src/manifest-contract.ts +59 -14
- package/src/seeds.ts +311 -260
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dreamboard-games/workspace-codegen",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Internal Dreamboard workspace source generator",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@dreamboard/sdk-types": "npm:@dreamboard-games/sdk-types@0.1.2",
|
|
24
|
-
"@dreamboard/ui-sdk": "npm:@dreamboard-games/ui-sdk@0.0.
|
|
24
|
+
"@dreamboard/ui-sdk": "npm:@dreamboard-games/ui-sdk@0.0.46"
|
|
25
25
|
},
|
|
26
26
|
"license": "SEE LICENSE IN LICENSE",
|
|
27
27
|
"publishConfig": {
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
lstat,
|
|
3
|
+
mkdir,
|
|
4
|
+
mkdtemp,
|
|
5
|
+
readFile,
|
|
6
|
+
readlink,
|
|
7
|
+
rm,
|
|
8
|
+
symlink,
|
|
9
|
+
} from "node:fs/promises";
|
|
2
10
|
import os from "node:os";
|
|
3
11
|
import path from "node:path";
|
|
4
12
|
import process from "node:process";
|
|
@@ -34,7 +42,8 @@ const EXPECTED_UI_FRAMEWORK_TSCONFIG = `{
|
|
|
34
42
|
"jsx": "react-jsx",
|
|
35
43
|
"strict": true,
|
|
36
44
|
"esModuleInterop": true,
|
|
37
|
-
"skipLibCheck":
|
|
45
|
+
"skipLibCheck": false,
|
|
46
|
+
"types": [],
|
|
38
47
|
"paths": {
|
|
39
48
|
"@dreamboard/manifest-contract": [
|
|
40
49
|
"../shared/manifest-contract.ts"
|
|
@@ -59,6 +68,44 @@ const EXPECTED_UI_FRAMEWORK_TSCONFIG = `{
|
|
|
59
68
|
}
|
|
60
69
|
`;
|
|
61
70
|
|
|
71
|
+
const EXPECTED_APP_FRAMEWORK_TSCONFIG = `{
|
|
72
|
+
"compilerOptions": {
|
|
73
|
+
"target": "ES2020",
|
|
74
|
+
"module": "ESNext",
|
|
75
|
+
"moduleResolution": "bundler",
|
|
76
|
+
"strict": true,
|
|
77
|
+
"esModuleInterop": true,
|
|
78
|
+
"skipLibCheck": false,
|
|
79
|
+
"types": [],
|
|
80
|
+
"declaration": false,
|
|
81
|
+
"rootDir": "..",
|
|
82
|
+
"outDir": "./dist",
|
|
83
|
+
"paths": {
|
|
84
|
+
"@dreamboard/manifest-contract": [
|
|
85
|
+
"../shared/manifest-contract.ts"
|
|
86
|
+
],
|
|
87
|
+
"@dreamboard/ui-contract": [
|
|
88
|
+
"../shared/generated/ui-contract.ts"
|
|
89
|
+
],
|
|
90
|
+
"@shared/*": [
|
|
91
|
+
"../shared/*"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"include": [
|
|
96
|
+
"./**/*.ts",
|
|
97
|
+
"./**/*.d.ts",
|
|
98
|
+
"../shared/manifest-*.ts",
|
|
99
|
+
"../shared/manifest-*.d.ts"
|
|
100
|
+
],
|
|
101
|
+
"exclude": [
|
|
102
|
+
"node_modules",
|
|
103
|
+
"dist",
|
|
104
|
+
"../shared/generated"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
|
|
62
109
|
async function loadBenchmarkManifest(): Promise<GameTopologyManifest> {
|
|
63
110
|
return materializeManifest(benchmarkRoot) as Promise<GameTopologyManifest>;
|
|
64
111
|
}
|
|
@@ -79,6 +126,32 @@ async function ensureSymlink(targetPath: string, linkPath: string) {
|
|
|
79
126
|
);
|
|
80
127
|
}
|
|
81
128
|
|
|
129
|
+
async function ensurePackageSymlink(targetPath: string, linkPath: string) {
|
|
130
|
+
try {
|
|
131
|
+
const stats = await lstat(linkPath);
|
|
132
|
+
if (stats.isSymbolicLink()) {
|
|
133
|
+
const existingTarget = await readlink(linkPath);
|
|
134
|
+
const resolvedExistingTarget = path.resolve(
|
|
135
|
+
path.dirname(linkPath),
|
|
136
|
+
existingTarget,
|
|
137
|
+
);
|
|
138
|
+
if (resolvedExistingTarget === targetPath) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
await rm(linkPath, { recursive: true, force: true });
|
|
143
|
+
} catch {
|
|
144
|
+
// Fall through and create the symlink.
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
await mkdir(path.dirname(linkPath), { recursive: true });
|
|
148
|
+
await symlink(
|
|
149
|
+
targetPath,
|
|
150
|
+
linkPath,
|
|
151
|
+
process.platform === "win32" ? "junction" : "dir",
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
82
155
|
function collectComponentHomeTypes(
|
|
83
156
|
manifest: GameTopologyManifest,
|
|
84
157
|
): Set<string> {
|
|
@@ -258,12 +331,15 @@ test("authoritative ui framework tsconfig uses the scaffold format", async () =>
|
|
|
258
331
|
await loadBenchmarkManifest(),
|
|
259
332
|
);
|
|
260
333
|
|
|
334
|
+
expect(authoritativeFiles["app/tsconfig.framework.json"]).toBe(
|
|
335
|
+
EXPECTED_APP_FRAMEWORK_TSCONFIG,
|
|
336
|
+
);
|
|
261
337
|
expect(authoritativeFiles["ui/tsconfig.framework.json"]).toBe(
|
|
262
338
|
EXPECTED_UI_FRAMEWORK_TSCONFIG,
|
|
263
339
|
);
|
|
264
340
|
});
|
|
265
341
|
|
|
266
|
-
test("generated ui-contract.ts exposes
|
|
342
|
+
test("generated ui-contract.ts exposes typed hex board view primitives", async () => {
|
|
267
343
|
const manifest = await loadBenchmarkManifest();
|
|
268
344
|
const authoritativeFiles = generateAuthoritativeFiles(manifest);
|
|
269
345
|
|
|
@@ -274,20 +350,31 @@ test("generated ui-contract.ts exposes a typed useHexBoardView wrapper", async (
|
|
|
274
350
|
);
|
|
275
351
|
}
|
|
276
352
|
|
|
277
|
-
// Imports static topology and exports the workspace-typed
|
|
353
|
+
// Imports static topology and exports the workspace-typed component.
|
|
278
354
|
expect(uiContract).toContain("staticBoards");
|
|
279
|
-
expect(uiContract).toContain(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
355
|
+
expect(uiContract).toContain(
|
|
356
|
+
"type BoardHexViewProps as BoardHexViewPropsGeneric",
|
|
357
|
+
);
|
|
358
|
+
expect(uiContract).toContain(
|
|
359
|
+
"type BoardHexGridProps as BoardHexGridPropsGeneric",
|
|
360
|
+
);
|
|
361
|
+
expect(uiContract).toContain("export type HexBoardViewProps");
|
|
362
|
+
expect(uiContract).toContain("export type HexBoardGridProps");
|
|
363
|
+
expect(uiContract).toContain("type WorkspaceBoard");
|
|
364
|
+
expect(uiContract).toContain('export const Board: WorkspaceUI["Board"]');
|
|
365
|
+
expect(uiContract).toContain("baseUI.Board.HexView");
|
|
366
|
+
expect(uiContract).toContain("baseUI.Board.HexGrid");
|
|
367
|
+
expect(uiContract).not.toContain("export function useHexBoardView");
|
|
368
|
+
|
|
369
|
+
// Constrains the board prop to the manifest's hex-board ids and narrows
|
|
370
|
+
// TSpaceView.id to that board's space-id type.
|
|
284
371
|
expect(uiContract).toContain("export type HexBoardId");
|
|
285
372
|
expect(uiContract).toContain("keyof typeof hexStaticBoards");
|
|
286
373
|
expect(uiContract).toContain("Id extends HexBoardId");
|
|
287
374
|
expect(uiContract).toContain("BoardSpaceIdOf");
|
|
288
375
|
});
|
|
289
376
|
|
|
290
|
-
test("generated ui-contract.ts exposes
|
|
377
|
+
test("generated ui-contract.ts exposes Interaction.Field without standalone field wrappers", async () => {
|
|
291
378
|
const manifest = await loadBenchmarkManifest();
|
|
292
379
|
const authoritativeFiles = generateAuthoritativeFiles(manifest);
|
|
293
380
|
|
|
@@ -298,13 +385,19 @@ test("generated ui-contract.ts exposes typed interaction form wrappers", async (
|
|
|
298
385
|
);
|
|
299
386
|
}
|
|
300
387
|
|
|
301
|
-
expect(uiContract).toContain("InteractionForm as InteractionFormGeneric");
|
|
302
|
-
expect(uiContract).toContain("export type InteractionFieldRenderers");
|
|
303
|
-
expect(uiContract).toContain(
|
|
388
|
+
expect(uiContract).not.toContain("InteractionForm as InteractionFormGeneric");
|
|
389
|
+
expect(uiContract).not.toContain("export type InteractionFieldRenderers");
|
|
390
|
+
expect(uiContract).not.toContain("export type InteractionFieldProps");
|
|
391
|
+
expect(uiContract).not.toContain(
|
|
304
392
|
"export type InteractionFormProps<Key extends InteractionKey>",
|
|
305
393
|
);
|
|
306
|
-
expect(uiContract).toContain("export function InteractionForm");
|
|
307
|
-
expect(uiContract).toContain("export function InteractionField");
|
|
394
|
+
expect(uiContract).not.toContain("export function InteractionForm");
|
|
395
|
+
expect(uiContract).not.toContain("export function InteractionField");
|
|
396
|
+
expect(uiContract).toContain("readonly Interaction: Omit<");
|
|
397
|
+
expect(uiContract).toContain(
|
|
398
|
+
'DreamboardUI<typeof uiContract>["Interaction"]',
|
|
399
|
+
);
|
|
400
|
+
expect(uiContract).toContain("export const Interaction = UI.Interaction;");
|
|
308
401
|
});
|
|
309
402
|
|
|
310
403
|
test("generated ui-contract.ts exposes typed Radix-style primitives without GameShell wrappers", async () => {
|
|
@@ -318,11 +411,20 @@ test("generated ui-contract.ts exposes typed Radix-style primitives without Game
|
|
|
318
411
|
);
|
|
319
412
|
}
|
|
320
413
|
|
|
321
|
-
expect(uiContract).toContain("
|
|
414
|
+
expect(uiContract).toContain("const baseUI = createDreamboardUI(uiContract)");
|
|
415
|
+
expect(uiContract).toContain("export const UI: WorkspaceUI = {");
|
|
416
|
+
expect(uiContract).toContain("type TypedGame");
|
|
417
|
+
expect(uiContract).toContain("export const Game");
|
|
322
418
|
expect(uiContract).toContain("export const Interaction = UI.Interaction");
|
|
323
419
|
expect(uiContract).toContain("export const Prompt = UI.Prompt");
|
|
420
|
+
expect(uiContract).toContain("type UIPlayerRegistry");
|
|
421
|
+
expect(uiContract).toContain("players: {} as UIPlayerRegistry");
|
|
422
|
+
expect(uiContract).toContain("export const PlayerRoster");
|
|
423
|
+
expect(uiContract).toContain('export const Dice: WorkspaceUI["Dice"]');
|
|
324
424
|
expect(uiContract).toContain("export const Zone = UI.Zone");
|
|
325
|
-
expect(uiContract).toContain("
|
|
425
|
+
expect(uiContract).toContain("createResourceCounter");
|
|
426
|
+
expect(uiContract).toContain("export const ResourceCounter");
|
|
427
|
+
expect(uiContract).toContain('export const Board: WorkspaceUI["Board"]');
|
|
326
428
|
expect(uiContract).not.toContain("WorkspaceGameShell");
|
|
327
429
|
expect(uiContract).not.toContain("GameShell as GameShellGeneric");
|
|
328
430
|
expect(uiContract).not.toContain("defineMarketSurface");
|
|
@@ -330,18 +432,7 @@ test("generated ui-contract.ts exposes typed Radix-style primitives without Game
|
|
|
330
432
|
});
|
|
331
433
|
|
|
332
434
|
test("board-contract-lab manifest authoring typechecks", async () => {
|
|
333
|
-
await
|
|
334
|
-
WORKSPACE_NODE_MODULES,
|
|
335
|
-
path.join(benchmarkRoot, "node_modules"),
|
|
336
|
-
);
|
|
337
|
-
await ensureSymlink(
|
|
338
|
-
SDK_TYPES_PACKAGE_ROOT,
|
|
339
|
-
path.join(benchmarkRoot, "node_modules", "@dreamboard", "sdk-types"),
|
|
340
|
-
);
|
|
341
|
-
await ensureSymlink(
|
|
342
|
-
UI_SDK_NODE_MODULES,
|
|
343
|
-
path.join(benchmarkRoot, "ui", "node_modules"),
|
|
344
|
-
);
|
|
435
|
+
await prepareExampleTypecheckDependencies(benchmarkRoot);
|
|
345
436
|
|
|
346
437
|
const result = runNode20ExampleScript(benchmarkRoot, "typecheck:manifest");
|
|
347
438
|
|
|
@@ -354,9 +445,35 @@ test("generated app contracts typecheck under Node 20 without a larger heap", as
|
|
|
354
445
|
const examples = [thingsInRingsRoot, benchmarkRoot];
|
|
355
446
|
|
|
356
447
|
for (const exampleRoot of examples) {
|
|
448
|
+
await prepareExampleTypecheckDependencies(exampleRoot);
|
|
357
449
|
const result = runNode20ExampleScript(exampleRoot, "typecheck:app");
|
|
358
450
|
if (result.exitCode !== 0) {
|
|
359
451
|
throwTypecheckError(`${exampleRoot} app`, result);
|
|
360
452
|
}
|
|
361
453
|
}
|
|
362
454
|
}, 120_000);
|
|
455
|
+
|
|
456
|
+
async function prepareExampleTypecheckDependencies(exampleRoot: string) {
|
|
457
|
+
const nodeModulesPath = path.join(exampleRoot, "node_modules");
|
|
458
|
+
await ensureSymlink(WORKSPACE_NODE_MODULES, nodeModulesPath);
|
|
459
|
+
await ensureSymlink(
|
|
460
|
+
SDK_TYPES_PACKAGE_ROOT,
|
|
461
|
+
path.join(exampleRoot, "node_modules", "@dreamboard", "sdk-types"),
|
|
462
|
+
);
|
|
463
|
+
await ensureSymlink(
|
|
464
|
+
UI_SDK_NODE_MODULES,
|
|
465
|
+
path.join(exampleRoot, "ui", "node_modules"),
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
const nodeModulesStats = await lstat(nodeModulesPath);
|
|
469
|
+
if (!nodeModulesStats.isSymbolicLink()) {
|
|
470
|
+
await ensurePackageSymlink(
|
|
471
|
+
path.join(UI_SDK_NODE_MODULES, "@types", "react"),
|
|
472
|
+
path.join(nodeModulesPath, "@types", "react"),
|
|
473
|
+
);
|
|
474
|
+
await ensurePackageSymlink(
|
|
475
|
+
path.join(UI_SDK_NODE_MODULES, "@types", "react-dom"),
|
|
476
|
+
path.join(nodeModulesPath, "@types", "react-dom"),
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
@@ -724,7 +724,7 @@ test("generateManifestContractSource emits typed topology fields and helper lite
|
|
|
724
724
|
expect(source).not.toContain("cardName: z.string().optional()");
|
|
725
725
|
expect(source).not.toContain("description: z.string().optional()");
|
|
726
726
|
expect(source).toContain(
|
|
727
|
-
"const cardPropertiesSchemaByCardSetId: Record<string, z.
|
|
727
|
+
"const cardPropertiesSchemaByCardSetId: Record<string, z.ZodType<unknown>> = {",
|
|
728
728
|
);
|
|
729
729
|
expect(source).toContain(
|
|
730
730
|
"function createCardStateSchema<CardIdValue extends CardId>(",
|
package/src/manifest-contract.ts
CHANGED
|
@@ -3383,7 +3383,7 @@ function renderCardPropertiesSchemaByCardSetId(
|
|
|
3383
3383
|
` ${quote(cardSet.id)}: ${toPascalCase(cardSet.id)}CardPropertiesSchema,`,
|
|
3384
3384
|
];
|
|
3385
3385
|
});
|
|
3386
|
-
return `const cardPropertiesSchemaByCardSetId: Record<string, z.
|
|
3386
|
+
return `const cardPropertiesSchemaByCardSetId: Record<string, z.ZodType<unknown>> = {\n${entries.join("\n")}\n};`;
|
|
3387
3387
|
}
|
|
3388
3388
|
|
|
3389
3389
|
function renderObjectSchemaSection(
|
|
@@ -3666,7 +3666,7 @@ function renderCardStateSchemaById(analysis: ManifestAnalysis): string {
|
|
|
3666
3666
|
return `z.object(
|
|
3667
3667
|
Object.fromEntries(
|
|
3668
3668
|
literals.cardIds.map((cardId) => [cardId, createCardStateSchema(cardId)]),
|
|
3669
|
-
) as Record<CardId, z.
|
|
3669
|
+
) as Record<CardId, z.ZodType<unknown>>,
|
|
3670
3670
|
)`;
|
|
3671
3671
|
}
|
|
3672
3672
|
|
|
@@ -3773,8 +3773,17 @@ function renderGenericBoardStateSchema(
|
|
|
3773
3773
|
},
|
|
3774
3774
|
templateId: z.string().nullable().optional(),
|
|
3775
3775
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
3776
|
+
// T220: per-board state.spaces is loose-keyed by string. The
|
|
3777
|
+
// canonical narrow id (\`ids.spaceId\`) is a Zod enum of EVERY
|
|
3778
|
+
// space id across every board, which makes a strict
|
|
3779
|
+
// \`z.record(enum, …)\` reject any board whose spaces are a
|
|
3780
|
+
// proper subset of that enum. Loose keying matches the JSON wire
|
|
3781
|
+
// shape (\`additionalProperties\`); the inner \`id: ids.spaceId\`
|
|
3782
|
+
// narrows the value's spaceId at parse time. A future per-board
|
|
3783
|
+
// branded-id refactor (option B) can re-tighten this without a
|
|
3784
|
+
// wire change.
|
|
3776
3785
|
spaces: z.record(
|
|
3777
|
-
|
|
3786
|
+
z.string(),
|
|
3778
3787
|
z.object({
|
|
3779
3788
|
id: ids.spaceId,
|
|
3780
3789
|
name: z.string().nullable().optional(),
|
|
@@ -3835,8 +3844,9 @@ function renderHexBoardStateSchema(
|
|
|
3835
3844
|
},
|
|
3836
3845
|
templateId: z.string().nullable().optional(),
|
|
3837
3846
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
3847
|
+
// T220: see generic-board comment on the loose-keying choice.
|
|
3838
3848
|
spaces: z.record(
|
|
3839
|
-
|
|
3849
|
+
z.string(),
|
|
3840
3850
|
z.object({
|
|
3841
3851
|
id: ids.spaceId,
|
|
3842
3852
|
name: z.string().nullable().optional(),
|
|
@@ -3907,8 +3917,9 @@ function renderSquareBoardStateSchema(
|
|
|
3907
3917
|
},
|
|
3908
3918
|
templateId: z.string().nullable().optional(),
|
|
3909
3919
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
3920
|
+
// T220: see generic-board comment on the loose-keying choice.
|
|
3910
3921
|
spaces: z.record(
|
|
3911
|
-
|
|
3922
|
+
z.string(),
|
|
3912
3923
|
z.object({
|
|
3913
3924
|
id: ids.spaceId,
|
|
3914
3925
|
name: z.string().nullable().optional(),
|
|
@@ -5718,7 +5729,11 @@ const runtimeGenericBoardStateSchema = z.object({
|
|
|
5718
5729
|
playerId: ids.playerId.nullable().optional(),
|
|
5719
5730
|
templateId: z.string().nullable().optional(),
|
|
5720
5731
|
fields: unknownRecordSchema,
|
|
5721
|
-
|
|
5732
|
+
// T220: per-board state.spaces is loose-keyed by string. See the
|
|
5733
|
+
// codegen-template comment in renderGenericBoardStateSchema for
|
|
5734
|
+
// the rationale; the wire shape is unchanged (additionalProperties
|
|
5735
|
+
// JSON), and the inner id field narrows at parse time.
|
|
5736
|
+
spaces: z.record(z.string(), boardSpaceStateSchema),
|
|
5722
5737
|
relations: z.array(boardRelationStateSchema),
|
|
5723
5738
|
containers: z.record(ids.boardContainerId, boardContainerStateSchema),
|
|
5724
5739
|
});
|
|
@@ -5748,7 +5763,8 @@ const squareVertexStateSchema = z.object({
|
|
|
5748
5763
|
});
|
|
5749
5764
|
const runtimeHexBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
5750
5765
|
layout: z.literal("hex"),
|
|
5751
|
-
|
|
5766
|
+
// T220: loose-keyed by string — see comment above.
|
|
5767
|
+
spaces: z.record(z.string(), hexSpaceStateSchema),
|
|
5752
5768
|
relations: z.array(boardRelationStateSchema),
|
|
5753
5769
|
containers: z.object({}),
|
|
5754
5770
|
orientation: z.enum(["pointy-top", "flat-top"]),
|
|
@@ -5757,7 +5773,8 @@ const runtimeHexBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
|
5757
5773
|
});
|
|
5758
5774
|
const runtimeSquareBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
5759
5775
|
layout: z.literal("square"),
|
|
5760
|
-
|
|
5776
|
+
// T220: loose-keyed by string — see comment above.
|
|
5777
|
+
spaces: z.record(z.string(), squareSpaceStateSchema),
|
|
5761
5778
|
relations: z.array(boardRelationStateSchema),
|
|
5762
5779
|
containers: z.record(ids.boardContainerId, boardContainerStateSchema),
|
|
5763
5780
|
edges: z.array(hexEdgeStateSchema),
|
|
@@ -5973,11 +5990,11 @@ export const schemas = {
|
|
|
5973
5990
|
} as const;
|
|
5974
5991
|
|
|
5975
5992
|
export function createGameStateSchema<
|
|
5976
|
-
PhaseNameSchema extends z.
|
|
5977
|
-
PublicSchema extends z.
|
|
5978
|
-
PrivateSchema extends z.
|
|
5979
|
-
HiddenSchema extends z.
|
|
5980
|
-
PhasesSchema extends z.
|
|
5993
|
+
PhaseNameSchema extends z.ZodType<unknown>,
|
|
5994
|
+
PublicSchema extends z.ZodType<unknown>,
|
|
5995
|
+
PrivateSchema extends z.ZodType<unknown>,
|
|
5996
|
+
HiddenSchema extends z.ZodType<unknown>,
|
|
5997
|
+
PhasesSchema extends z.ZodType<unknown>,
|
|
5981
5998
|
>({
|
|
5982
5999
|
phaseNameSchema,
|
|
5983
6000
|
publicSchema,
|
|
@@ -6178,6 +6195,34 @@ function renderManifestRuntimeSource(legacySource: string): string {
|
|
|
6178
6195
|
`} from "@dreamboard/app-sdk/reducer";\n\nconst unknownRecordSchema`,
|
|
6179
6196
|
`} from "@dreamboard/app-sdk/reducer";\nimport { literals } from "./manifest-literals";\nimport type { PlayerId as PublicPlayerId, TableState as PublicTableState } from "./manifest-types";\n\nconst unknownRecordSchema`,
|
|
6180
6197
|
)
|
|
6198
|
+
.replaceAll(
|
|
6199
|
+
"literals.playerIds as unknown as readonly PlayerId[]",
|
|
6200
|
+
"literals.playerIds",
|
|
6201
|
+
)
|
|
6202
|
+
.replaceAll(
|
|
6203
|
+
"cardId: cardIdSchema as unknown as z.ZodType<CardId>,",
|
|
6204
|
+
"cardId: assumeManifestSchema<CardId>(cardIdSchema),",
|
|
6205
|
+
)
|
|
6206
|
+
.replaceAll(
|
|
6207
|
+
"deckId: deckIdSchema as unknown as z.ZodType<DeckId>,",
|
|
6208
|
+
"deckId: assumeManifestSchema<DeckId>(deckIdSchema),",
|
|
6209
|
+
)
|
|
6210
|
+
.replaceAll(
|
|
6211
|
+
"handId: handIdSchema as unknown as z.ZodType<HandId>,",
|
|
6212
|
+
"handId: assumeManifestSchema<HandId>(handIdSchema),",
|
|
6213
|
+
)
|
|
6214
|
+
.replace(
|
|
6215
|
+
/export const staticBoards = ([\s\S]*?) as const;\n\nconst baseInitialTable = /,
|
|
6216
|
+
"export const staticBoards = $1 as const satisfies StaticBoards<PublicTableState>;\n\nconst baseInitialTable = ",
|
|
6217
|
+
)
|
|
6218
|
+
.replace(
|
|
6219
|
+
/const baseInitialTable = ([\s\S]*?) as const as unknown as TableState;\nconst baseDeckCardsByZoneId:/,
|
|
6220
|
+
"const baseInitialTable = cloneManifestDefault<PublicTableState>($1);\nconst baseDeckCardsByZoneId:",
|
|
6221
|
+
)
|
|
6222
|
+
.replace(
|
|
6223
|
+
"staticBoards: staticBoards as unknown as StaticBoards<TableState>,",
|
|
6224
|
+
"staticBoards,",
|
|
6225
|
+
)
|
|
6181
6226
|
.replace(
|
|
6182
6227
|
`export const manifestContract: ReducerManifestContract<\n RuntimeTableRecord,`,
|
|
6183
6228
|
`export const manifestContract: ReducerManifestContract<\n PublicTableState,`,
|
|
@@ -6188,7 +6233,7 @@ function renderManifestRuntimeSource(legacySource: string): string {
|
|
|
6188
6233
|
)
|
|
6189
6234
|
.replace(
|
|
6190
6235
|
`const playerIdSchema = markManifestScopedSchema(\n z\n .string()\n .min(1)\n .transform((value) => asPlayerId(value)),\n);`,
|
|
6191
|
-
`const playerIdSchema = markManifestScopedSchema(\n
|
|
6236
|
+
`const playerIdSchema = assumeManifestSchema<PublicPlayerId>(\n markManifestScopedSchema(\n z\n .string()\n .min(1)\n .transform((value) => asPlayerId(value)),\n ),\n);`,
|
|
6192
6237
|
);
|
|
6193
6238
|
}
|
|
6194
6239
|
|