@dreamboard-games/sdk 0.4.0-alpha.8 → 0.5.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +49 -11
  2. package/dist/authoring/index.d.ts +6 -14
  3. package/dist/authoring/index.js +11 -547
  4. package/dist/authoring/index.js.map +1 -1
  5. package/dist/authoring-compiler.d.ts +27 -0
  6. package/dist/authoring-compiler.js +11 -0
  7. package/dist/authoring-compiler.js.map +1 -0
  8. package/dist/authoring-materialize-cli.d.ts +1 -0
  9. package/dist/authoring-materialize-cli.js +45 -0
  10. package/dist/authoring-materialize-cli.js.map +1 -0
  11. package/dist/browser-interaction.d.ts +22 -22
  12. package/dist/{chunk-3BLN5POZ.js → chunk-2GQIALJL.js} +51 -15
  13. package/dist/chunk-2GQIALJL.js.map +1 -0
  14. package/dist/chunk-533O7C4L.js +7095 -0
  15. package/dist/chunk-533O7C4L.js.map +1 -0
  16. package/dist/{chunk-44N3T2A5.js → chunk-6LMESVGT.js} +9 -28
  17. package/dist/chunk-6LMESVGT.js.map +1 -0
  18. package/dist/{chunk-ZYONCTZ2.js → chunk-DQS2EG5E.js} +3 -3
  19. package/dist/{chunk-ZYONCTZ2.js.map → chunk-DQS2EG5E.js.map} +1 -1
  20. package/dist/chunk-EOEA3I64.js +1864 -0
  21. package/dist/chunk-EOEA3I64.js.map +1 -0
  22. package/dist/{chunk-B2YBS3SG.js → chunk-FL67RDID.js} +41 -13
  23. package/dist/chunk-FL67RDID.js.map +1 -0
  24. package/dist/{chunk-2TAKLJJD.js → chunk-HIH6Y4FA.js} +222 -1267
  25. package/dist/chunk-HIH6Y4FA.js.map +1 -0
  26. package/dist/chunk-HUK4234C.js +166 -0
  27. package/dist/chunk-HUK4234C.js.map +1 -0
  28. package/dist/chunk-KGV2EUNN.js +532 -0
  29. package/dist/chunk-KGV2EUNN.js.map +1 -0
  30. package/dist/{chunk-VTK4TIXC.js → chunk-KRJPRYEA.js} +49 -4
  31. package/dist/chunk-KRJPRYEA.js.map +1 -0
  32. package/dist/chunk-KWHOFBDM.js +9 -0
  33. package/dist/chunk-KWHOFBDM.js.map +1 -0
  34. package/dist/{chunk-UC2UXAC6.js → chunk-LMHCGCA6.js} +2 -2
  35. package/dist/{chunk-XV27IQHA.js → chunk-N33CGX2F.js} +15 -85
  36. package/dist/chunk-N33CGX2F.js.map +1 -0
  37. package/dist/chunk-TXELBVTG.js +32 -0
  38. package/dist/chunk-TXELBVTG.js.map +1 -0
  39. package/dist/{chunk-2TRZSZGD.js → chunk-VRRR6QZT.js} +9 -12
  40. package/dist/chunk-VRRR6QZT.js.map +1 -0
  41. package/dist/chunk-VWTKGIYF.js +90 -0
  42. package/dist/chunk-VWTKGIYF.js.map +1 -0
  43. package/dist/{chunk-IYX5OO2K.js → chunk-XFMSLL3P.js} +133 -61
  44. package/dist/chunk-XFMSLL3P.js.map +1 -0
  45. package/dist/{chunk-YGQTL63W.js → chunk-ZSTCUJKZ.js} +4 -4
  46. package/dist/chunk-ZSTCUJKZ.js.map +1 -0
  47. package/dist/codegen.js +1 -1
  48. package/dist/{components-BTwSIjXj.d.ts → components-CNAt5J1p.d.ts} +1 -1
  49. package/dist/definitions-bZSBaPjj.d.ts +300 -0
  50. package/dist/{diagnostics-1BWjRo6-.d.ts → diagnostics-DIi3ina7.d.ts} +2 -1
  51. package/dist/digest.d.ts +8 -0
  52. package/dist/{index-CFTjJIXd.d.ts → index-CR69MyWr.d.ts} +2 -2
  53. package/dist/{index.d-C0PKOVbh.d.ts → index.d-Bw8AOcgp.d.ts} +532 -225
  54. package/dist/index.js +2 -2
  55. package/dist/package-set.d.ts +2 -2
  56. package/dist/package-set.js +2 -2
  57. package/dist/plugin-runtime-contract.d.ts +17 -0
  58. package/dist/plugin-runtime-contract.js +94 -0
  59. package/dist/plugin-runtime-contract.js.map +1 -0
  60. package/dist/{protocol-nS2ojsGr.d.ts → protocol-CVaSqPgX.d.ts} +54 -47
  61. package/dist/reducer/advanced.d.ts +5 -4
  62. package/dist/reducer/advanced.js +14 -108
  63. package/dist/reducer/advanced.js.map +1 -1
  64. package/dist/reducer-contract.d.ts +1 -1
  65. package/dist/reducer-contract.js +6 -4
  66. package/dist/reducer.d.ts +20 -98
  67. package/dist/reducer.js +28 -6050
  68. package/dist/reducer.js.map +1 -1
  69. package/dist/reference-games/index.d.ts +6 -198
  70. package/dist/reference-games/index.js +18 -200
  71. package/dist/reference-games/index.js.map +1 -1
  72. package/dist/runtime/primitives.d.ts +3 -3
  73. package/dist/runtime/primitives.js +5 -5
  74. package/dist/runtime/runtime-api.d.ts +1 -1
  75. package/dist/runtime/workspace-contract.d.ts +343 -11
  76. package/dist/runtime/workspace-contract.js +12 -6
  77. package/dist/{runtime-Dkfm1x2r.d.ts → runtime-C7Z2acNU.d.ts} +67 -31
  78. package/dist/{runtime-api-C6aWo9c0.d.ts → runtime-api-CgPuEVeF.d.ts} +4 -13
  79. package/dist/runtime.d.ts +7 -7
  80. package/dist/runtime.js +15 -11
  81. package/dist/runtime.js.map +1 -1
  82. package/dist/schema.d.ts +405 -0
  83. package/dist/{stale-contract-artifact-error-C5AaZPJ8.d.ts → stale-contract-artifact-error-XLaweZtF.d.ts} +1 -1
  84. package/dist/testing-compiler.d.ts +37 -0
  85. package/dist/testing-compiler.js +272 -0
  86. package/dist/testing-compiler.js.map +1 -0
  87. package/dist/testing-runtime.d.ts +98 -21
  88. package/dist/testing-runtime.js +154 -95
  89. package/dist/testing-runtime.js.map +1 -1
  90. package/dist/testing.d.ts +197 -156
  91. package/dist/testing.js +660 -372
  92. package/dist/testing.js.map +1 -1
  93. package/dist/types-DN4O7kH_.d.ts +122 -0
  94. package/dist/{types-CTeN_QAk.d.ts → types-q1Guidm5.d.ts} +4 -5
  95. package/dist/types.d.ts +0 -1
  96. package/dist/ui/components.d.ts +3 -2
  97. package/dist/ui/components.js +1 -1
  98. package/dist/ui/plugin-styles.css +1 -1
  99. package/dist/{ui-contract-Ue6SywvO.d.ts → ui-contract-BC4JpysE.d.ts} +2 -6
  100. package/dist/ui.d.ts +4 -3
  101. package/dist/ui.js +2 -2
  102. package/dist/{views-Qx-EHBP8.d.ts → views-D2Cfzr3h.d.ts} +17 -5
  103. package/package.json +41 -22
  104. package/REFERENCE.md +0 -22884
  105. package/dist/chunk-2TAKLJJD.js.map +0 -1
  106. package/dist/chunk-2TRZSZGD.js.map +0 -1
  107. package/dist/chunk-3BLN5POZ.js.map +0 -1
  108. package/dist/chunk-3OZMHZK3.js +0 -40
  109. package/dist/chunk-3OZMHZK3.js.map +0 -1
  110. package/dist/chunk-44N3T2A5.js.map +0 -1
  111. package/dist/chunk-5CQIJHGF.js +0 -663
  112. package/dist/chunk-5CQIJHGF.js.map +0 -1
  113. package/dist/chunk-B2YBS3SG.js.map +0 -1
  114. package/dist/chunk-IYX5OO2K.js.map +0 -1
  115. package/dist/chunk-VTK4TIXC.js.map +0 -1
  116. package/dist/chunk-VTNEWMWJ.js +0 -12
  117. package/dist/chunk-VTNEWMWJ.js.map +0 -1
  118. package/dist/chunk-XV27IQHA.js.map +0 -1
  119. package/dist/chunk-YGQTL63W.js.map +0 -1
  120. package/dist/types-B_3pObUV.d.ts +0 -192
  121. /package/dist/{chunk-UC2UXAC6.js.map → chunk-LMHCGCA6.js.map} +0 -0
package/README.md CHANGED
@@ -1,19 +1,57 @@
1
1
  # @dreamboard-games/sdk
2
2
 
3
- The public Dreamboard SDK package. This repository publishes one consumer
4
- package, `@dreamboard-games/sdk`; public capabilities are exposed through the
5
- package export map rather than separate installable workspace packages.
3
+ The public TypeScript SDK for authoring, testing, and rendering Dreamboard
4
+ games. Install this package rather than any of the repository's unpublished
5
+ workspace inputs.
6
6
 
7
- Internal workspaces such as `sdk-types`, `workspace-codegen`, and
8
- `reducer-contract` are implementation inputs. Consumers should not install or
9
- import those package names directly.
7
+ ```sh
8
+ pnpm add @dreamboard-games/sdk
9
+ ```
10
10
 
11
- Typical imports:
11
+ The package's declarations and export map are the API authority. Supported
12
+ imports include the root module and explicit subpaths for authoring, runtime,
13
+ reducer contracts, testing, browser interaction, UI, and reference-game
14
+ metadata. Import only subpaths present in the installed package's `exports`
15
+ field.
12
16
 
13
17
  ```ts
14
- import {
15
- DREAMBOARD_SDK_PACKAGE_SET,
16
- DREAMBOARD_SDK_VERSION,
17
- } from "@dreamboard-games/sdk";
18
+ import { DREAMBOARD_SDK_VERSION } from "@dreamboard-games/sdk";
18
19
  import type { ReducerWire } from "@dreamboard-games/sdk/reducer-contract";
20
+ import {
21
+ REFERENCE_GAME_MANIFEST_SCHEMA_VERSION,
22
+ parseReferenceGameManifest,
23
+ type ReferenceGameManifest,
24
+ } from "@dreamboard-games/sdk/reference-games";
25
+
26
+ const manifest: ReferenceGameManifest = parseReferenceGameManifest(input);
27
+ console.log(REFERENCE_GAME_MANIFEST_SCHEMA_VERSION, manifest.id);
19
28
  ```
29
+
30
+ Reference-game manifests use schema V5. They describe the game workspace,
31
+ teaching purpose, mechanics, UI patterns, and substantive rights metadata.
32
+
33
+ Include the packaged stylesheet when using SDK UI components:
34
+
35
+ ```ts
36
+ import "@dreamboard-games/sdk/ui/plugin-styles.css";
37
+ ```
38
+
39
+ ## Reducer runner contract
40
+
41
+ `createReducerBundle(game)` returns exactly the contract version and four
42
+ operations: `boardStatic()`, `initialize(input)`, `dispatch({ state, input })`,
43
+ and `project({ state, playerIds })`. The runner contract is `0.5.0`; hosts must
44
+ require that exact version. Dispatch includes validation and effect execution. Initialization returns
45
+ `{ state, terminal?, events? }`, preserving outcomes and events from initial
46
+ phase entry and automatic continuations.
47
+
48
+ The authoritative state is explicit on every dispatch and projection. A host
49
+ may retain a warm worker and SDK caches, but replaying the same state and input
50
+ must produce the same gameplay result as a fresh worker. Projection timing is
51
+ diagnostic and is excluded from this equivalence.
52
+
53
+ Seat projections are independent of session versions. The gameplay service
54
+ owns the monotonically increasing version, perspective, and action-set identity.
55
+ The plugin frame basis contains `version`, `actionSetVersion`, and
56
+ `perspectivePlayerId`; it has no generation counter. Hosts merge the separately
57
+ cached board static projection when materializing plugin gameplay frames.
@@ -1,10 +1,7 @@
1
- import { JsonValue, GameTopologyManifest } from '../types.js';
1
+ import { JsonValue } from '../types.js';
2
2
 
3
- type GeneratedAuthoringMetadataV1 = {
3
+ type AuthoringMetadataV1 = {
4
4
  sdkVersion: string;
5
- codegenVersion: string;
6
- manifestSchemaVersion: number;
7
- generatedArtifactSchemaVersion: number;
8
5
  };
9
6
  type AuthoringValidationResultV1 = {
10
7
  valid: boolean;
@@ -13,7 +10,7 @@ type AuthoringValidationResultV1 = {
13
10
  };
14
11
  type GeneratedArtifactV1 = {
15
12
  path: string;
16
- ownership: "authoritative" | "seed" | "derived-test";
13
+ ownership: "authoritative" | "seed";
17
14
  content: string;
18
15
  contentSha256: string;
19
16
  };
@@ -21,9 +18,6 @@ type GeneratedPathPatternV1 = {
21
18
  prefix: string;
22
19
  suffix: string;
23
20
  };
24
- type GenerateTestArtifactsInputV1 = {
25
- manifest: GameTopologyManifest;
26
- };
27
21
  type AuthoringManifestConformanceCaseV1 = {
28
22
  id: string;
29
23
  manifest: JsonValue;
@@ -39,14 +33,13 @@ type AuthoringManifestConformanceCaseV1 = {
39
33
  };
40
34
  type ProjectAuthoringAdapterV1 = {
41
35
  protocolVersion: 1;
42
- metadata: GeneratedAuthoringMetadataV1;
36
+ metadata: AuthoringMetadataV1;
43
37
  generatedPaths: readonly string[];
44
38
  generatedPathPatterns: readonly GeneratedPathPatternV1[];
45
39
  manifestConformanceCases: readonly AuthoringManifestConformanceCaseV1[];
46
40
  validateManifest(manifest: unknown): AuthoringValidationResultV1;
47
41
  materializeManifest(manifest: unknown): JsonValue;
48
42
  generateWorkspaceArtifacts(manifest: unknown): readonly GeneratedArtifactV1[];
49
- generateTestArtifacts(input: GenerateTestArtifactsInputV1): readonly GeneratedArtifactV1[];
50
43
  };
51
44
 
52
45
  declare function diagnosticCodesForValidationErrors(errors: readonly string[]): readonly string[];
@@ -54,8 +47,7 @@ declare function diagnosticCodesForValidationErrors(errors: readonly string[]):
54
47
  declare function validateManifest(manifest: unknown): AuthoringValidationResultV1;
55
48
  declare function materializeManifest(manifest: unknown): JsonValue;
56
49
  declare function generateWorkspaceArtifacts(manifest: unknown): readonly GeneratedArtifactV1[];
57
- declare function generateTestArtifacts(input: GenerateTestArtifactsInputV1): readonly GeneratedArtifactV1[];
58
- declare const GENERATED_WORKSPACE_PATHS: readonly [...string[], "test/generated/base-state.json"];
50
+ declare const GENERATED_WORKSPACE_PATHS: readonly string[];
59
51
  type GeneratedWorkspacePathPattern = {
60
52
  readonly prefix: string;
61
53
  readonly suffix: string;
@@ -64,4 +56,4 @@ declare const GENERATED_WORKSPACE_PATH_PATTERNS: readonly GeneratedWorkspacePath
64
56
  declare const MANIFEST_CONFORMANCE_CASES: readonly AuthoringManifestConformanceCaseV1[];
65
57
  declare const projectAuthoringAdapter: ProjectAuthoringAdapterV1;
66
58
 
67
- export { type AuthoringManifestConformanceCaseV1, type AuthoringValidationResultV1, GENERATED_WORKSPACE_PATHS, GENERATED_WORKSPACE_PATH_PATTERNS, type GenerateTestArtifactsInputV1, type GeneratedArtifactV1, type GeneratedAuthoringMetadataV1, type GeneratedPathPatternV1, MANIFEST_CONFORMANCE_CASES, type ProjectAuthoringAdapterV1, diagnosticCodesForValidationErrors, generateTestArtifacts, generateWorkspaceArtifacts, materializeManifest, projectAuthoringAdapter, validateManifest };
59
+ export { type AuthoringManifestConformanceCaseV1, type AuthoringMetadataV1, type AuthoringValidationResultV1, GENERATED_WORKSPACE_PATHS, GENERATED_WORKSPACE_PATH_PATTERNS, type GeneratedArtifactV1, type GeneratedPathPatternV1, MANIFEST_CONFORMANCE_CASES, type ProjectAuthoringAdapterV1, diagnosticCodesForValidationErrors, generateWorkspaceArtifacts, materializeManifest, projectAuthoringAdapter, validateManifest };
@@ -1,557 +1,21 @@
1
1
  import {
2
- AUTHORITATIVE_GENERATED_FILES,
3
- SEED_FILES,
4
- SEED_FILE_PATTERNS,
5
- generateAuthoritativeFiles,
6
- generateSeedFiles,
7
- materializeManifestTable,
8
- validateManifestAuthoring
9
- } from "../chunk-2TAKLJJD.js";
10
- import {
11
- GENERATED_AUTHORING_METADATA
12
- } from "../chunk-VTNEWMWJ.js";
13
- import "../chunk-PZ5AY32C.js";
14
-
15
- // src/authoring/adapter.ts
16
- import { createHash } from "crypto";
17
-
18
- // src/authoring/manifest-conformance-cases.ts
19
- function baseManifest(cardSet, overrides = {}) {
20
- return {
21
- players: {
22
- minPlayers: 2,
23
- maxPlayers: 2,
24
- optimalPlayers: 2
25
- },
26
- cardSets: [cardSet],
27
- zones: [],
28
- boardTemplates: [],
29
- boards: [],
30
- pieceTypes: [],
31
- pieceSeeds: [],
32
- dieTypes: [],
33
- dieSeeds: [],
34
- resources: [],
35
- setupOptions: [],
36
- setupProfiles: [],
37
- ...overrides
38
- };
39
- }
40
- function manualCardSet(id, defaultHome, cards) {
41
- const cardSet = {
42
- id,
43
- name: id,
44
- type: "manual",
45
- cardSchema: { properties: {} },
46
- defaultHome,
47
- cards
48
- };
49
- return cardSet;
50
- }
51
- var sharedZone = {
52
- id: "shared-zone",
53
- name: "Shared Zone",
54
- scope: "shared",
55
- allowedCardSetIds: ["cards"]
56
- };
57
- var sharedBoard = {
58
- id: "square-board",
59
- name: "Square Board",
60
- layout: "square",
61
- scope: "shared",
62
- spaces: [
63
- { id: "a1", row: 0, col: 0 },
64
- { id: "a2", row: 0, col: 1 },
65
- { id: "b1", row: 1, col: 0 },
66
- { id: "b2", row: 1, col: 1 }
67
- ],
68
- relations: [],
69
- containers: [
70
- {
71
- id: "display-row",
72
- name: "Display Row",
73
- host: { type: "board" }
74
- }
75
- ],
76
- edges: [],
77
- vertices: []
78
- };
79
- var sharedTopology = {
80
- boards: [sharedBoard],
81
- pieceTypes: [
82
- {
83
- id: "holder",
84
- name: "Holder",
85
- slots: [{ id: "pocket" }]
86
- }
87
- ],
88
- pieceSeeds: [{ id: "holder-a", typeId: "holder" }]
89
- };
90
- var fixtures = [
91
- {
92
- id: "manual-default-detached",
93
- manifest: baseManifest(
94
- manualCardSet("cards", { type: "detached" }, [
95
- { type: "marker", name: "Marker", count: 1, properties: {} }
96
- ])
97
- ),
98
- expected: {
99
- valid: true,
100
- transportValid: true,
101
- materializedSha256: "ed6f7ce2ff4fbe697e49134f1d59157cf146e202db29a77be50e8326585f535c"
102
- }
103
- },
104
- {
105
- id: "manual-default-shared-zone",
106
- manifest: baseManifest(
107
- manualCardSet("cards", { type: "zone", zoneId: "shared-zone" }, [
108
- { type: "coin", name: "Coin", count: 2, properties: {} }
109
- ]),
110
- { zones: [sharedZone] }
111
- ),
112
- expected: {
113
- valid: true,
114
- transportValid: true,
115
- materializedSha256: "75028d28dbc415c81db5e2d780d55b04c4db36378a149bc02b0194d94a8cc2b9"
116
- }
117
- },
118
- {
119
- id: "preset-default-shared-zone",
120
- manifest: baseManifest(
121
- {
122
- id: "cards",
123
- name: "Preset Cards",
124
- type: "preset",
125
- presetId: "standard_52_deck",
126
- defaultHome: { type: "zone", zoneId: "shared-zone" }
127
- },
128
- { zones: [sharedZone] }
129
- ),
130
- expected: {
131
- valid: true,
132
- transportValid: true,
133
- materializedSha256: "b3471c577ed266667b16799f75aa9b7358100a94108aa46a31ad16a0291f67ca"
134
- }
135
- },
136
- {
137
- id: "manual-per-card-detached-override",
138
- manifest: baseManifest(
139
- manualCardSet("cards", { type: "zone", zoneId: "shared-zone" }, [
140
- {
141
- type: "removed",
142
- name: "Removed",
143
- count: 1,
144
- home: { type: "detached" },
145
- properties: {}
146
- }
147
- ]),
148
- { zones: [sharedZone] }
149
- ),
150
- expected: {
151
- valid: true,
152
- transportValid: true,
153
- materializedSha256: "fdcb2de78fc391e11aca1f266fd8bbb348a82faa0fbbac1d8eb1defd8697a0e9"
154
- }
155
- },
156
- {
157
- id: "manual-per-card-shared-zone-override",
158
- manifest: baseManifest(
159
- manualCardSet("cards", { type: "detached" }, [
160
- {
161
- type: "dealt",
162
- name: "Dealt",
163
- count: 1,
164
- home: { type: "zone", zoneId: "shared-zone" },
165
- properties: {}
166
- }
167
- ]),
168
- { zones: [sharedZone] }
169
- ),
170
- expected: {
171
- valid: true,
172
- transportValid: true,
173
- materializedSha256: "b6bee1db85f16e8a12a7136c7d524591f925427c8ec04d64b07905c5bc859d7a"
174
- }
175
- },
176
- {
177
- id: "manual-compatible-zones-no-inference",
178
- manifest: baseManifest(
179
- manualCardSet("cards", { type: "detached" }, [
180
- { type: "token", name: "Token", count: 1, properties: {} }
181
- ]),
182
- {
183
- zones: [
184
- sharedZone,
185
- {
186
- ...sharedZone,
187
- id: "second-compatible-zone",
188
- name: "Second Compatible Zone"
189
- }
190
- ]
191
- }
192
- ),
193
- expected: {
194
- valid: true,
195
- transportValid: true,
196
- materializedSha256: "2727728ba3743d2b1874b2bc573b48c88f962fdcbdcdf20c62bed551d6d955c4"
197
- }
198
- },
199
- {
200
- id: "manual-per-player-zone-rejected",
201
- manifest: baseManifest(
202
- manualCardSet("cards", { type: "zone", zoneId: "hand" }, [
203
- { type: "secret", name: "Secret", count: 1, properties: {} }
204
- ]),
205
- {
206
- zones: [
207
- {
208
- id: "hand",
209
- name: "Hand",
210
- scope: "perPlayer",
211
- allowedCardSetIds: ["cards"]
212
- }
213
- ]
214
- }
215
- ),
216
- expected: {
217
- valid: false,
218
- transportValid: true,
219
- diagnosticCodes: ["CARD_HOME_PER_PLAYER_ZONE_REJECTED"]
220
- }
221
- },
222
- {
223
- id: "manual-space-home",
224
- manifest: baseManifest(
225
- manualCardSet(
226
- "cards",
227
- { type: "space", boardId: "square-board", spaceId: "a1" },
228
- [{ type: "space-card", name: "Space", count: 1, properties: {} }]
229
- ),
230
- sharedTopology
231
- ),
232
- expected: {
233
- valid: true,
234
- transportValid: true,
235
- materializedSha256: "429abfb3276c67cdca59d3dc077fc73022a9716bccef2c43f6805ff5cce0f2c2"
236
- }
237
- },
238
- {
239
- id: "manual-container-home",
240
- manifest: baseManifest(
241
- manualCardSet(
242
- "cards",
243
- {
244
- type: "container",
245
- boardId: "square-board",
246
- containerId: "display-row"
247
- },
248
- [
249
- {
250
- type: "container-card",
251
- name: "Container",
252
- count: 1,
253
- properties: {}
254
- }
255
- ]
256
- ),
257
- sharedTopology
258
- ),
259
- expected: {
260
- valid: true,
261
- transportValid: true,
262
- materializedSha256: "eff372263227b316d064a519cf282a6cc1d2d8df4ac04673b7f47ac518d7a2a3"
263
- }
264
- },
265
- {
266
- id: "manual-slot-home",
267
- manifest: baseManifest(
268
- manualCardSet(
269
- "cards",
270
- {
271
- type: "slot",
272
- host: { kind: "piece", id: "holder-a" },
273
- slotId: "pocket"
274
- },
275
- [{ type: "slot-card", name: "Slot", count: 1, properties: {} }]
276
- ),
277
- sharedTopology
278
- ),
279
- expected: {
280
- valid: true,
281
- transportValid: true,
282
- materializedSha256: "af3111f8d861ae69b77f2f46ba3df9f2f698f3306c412efc91095544e8121ab6"
283
- }
284
- },
285
- {
286
- id: "manual-edge-home",
287
- manifest: baseManifest(
288
- manualCardSet(
289
- "cards",
290
- {
291
- type: "edge",
292
- boardId: "square-board",
293
- ref: { spaces: ["a1", "a2"] }
294
- },
295
- [{ type: "edge-card", name: "Edge", count: 1, properties: {} }]
296
- ),
297
- sharedTopology
298
- ),
299
- expected: {
300
- valid: true,
301
- transportValid: true,
302
- materializedSha256: "f8606ea25f52d9bf801aa4fee9f558b60d7f39bcd601d57bdfccdf1ddbf4c500"
303
- }
304
- },
305
- {
306
- id: "manual-vertex-home",
307
- manifest: baseManifest(
308
- manualCardSet(
309
- "cards",
310
- {
311
- type: "vertex",
312
- boardId: "square-board",
313
- ref: { spaces: ["a1", "a2", "b1", "b2"] }
314
- },
315
- [{ type: "vertex-card", name: "Vertex", count: 1, properties: {} }]
316
- ),
317
- sharedTopology
318
- ),
319
- expected: {
320
- valid: true,
321
- transportValid: true,
322
- materializedSha256: "e84a4920ea8b71052acd42accf11101380ab982e493ebe207113dd4d243034de"
323
- }
324
- },
325
- {
326
- id: "manual-invalid-target-id",
327
- manifest: baseManifest(
328
- manualCardSet("cards", { type: "zone", zoneId: "missing-zone" }, [
329
- { type: "lost", name: "Lost", count: 1, properties: {} }
330
- ])
331
- ),
332
- expected: {
333
- valid: false,
334
- transportValid: true,
335
- diagnosticCodes: ["AUTHORING_VALIDATION_ERROR"]
336
- }
337
- },
338
- {
339
- id: "manual-count-order",
340
- manifest: baseManifest(
341
- manualCardSet("cards", { type: "zone", zoneId: "shared-zone" }, [
342
- { type: "first", name: "First", count: 3, properties: {} },
343
- { type: "second", name: "Second", count: 2, properties: {} }
344
- ]),
345
- { zones: [sharedZone] }
346
- ),
347
- expected: {
348
- valid: true,
349
- transportValid: true,
350
- materializedSha256: "2e4ced71909d4c36053317311c9ceaf3bf3adba875bff3fe9596bbea47746423"
351
- }
352
- },
353
- {
354
- id: "manual-generated-scenario-base",
355
- manifest: baseManifest(
356
- manualCardSet("cards", { type: "zone", zoneId: "shared-zone" }, [
357
- { type: "alpha", name: "Alpha", count: 2, properties: {} },
358
- { type: "beta", name: "Beta", count: 1, properties: {} }
359
- ]),
360
- { zones: [sharedZone] }
361
- ),
362
- expected: {
363
- valid: true,
364
- transportValid: true,
365
- materializedSha256: "b1b65d708b503036a49434c64c6f4aab3bedd295681bd103b69c4b98fdd5e2bb"
366
- }
367
- },
368
- {
369
- id: "manual-default-required",
370
- manifest: {
371
- ...baseManifest(
372
- manualCardSet("cards", { type: "detached" }, [
373
- { type: "card", name: "Card", count: 1, properties: {} }
374
- ])
375
- ),
376
- cardSets: [
377
- {
378
- id: "cards",
379
- name: "Cards",
380
- type: "manual",
381
- cardSchema: { properties: {} },
382
- cards: [{ type: "card", name: "Card", count: 1, properties: {} }]
383
- }
384
- ]
385
- },
386
- expected: {
387
- valid: false,
388
- transportValid: false,
389
- diagnosticCodes: ["MANUAL_CARD_SET_DEFAULT_HOME_REQUIRED"]
390
- }
391
- }
392
- ];
393
- function deepFreeze(value) {
394
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
395
- for (const entry of Object.values(value)) {
396
- deepFreeze(entry);
397
- }
398
- Object.freeze(value);
399
- }
400
- return value;
401
- }
402
- function diagnosticCodesForValidationErrors(errors) {
403
- return [...new Set(errors.map(diagnosticCodeForValidationError))].sort();
404
- }
405
- function diagnosticCodeForValidationError(error) {
406
- if (error.includes(".defaultHome: Manual card sets must declare defaultHome")) {
407
- return "MANUAL_CARD_SET_DEFAULT_HOME_REQUIRED";
408
- }
409
- if (error.includes("cannot target per-player zone")) {
410
- return "CARD_HOME_PER_PLAYER_ZONE_REJECTED";
411
- }
412
- if (error.includes("cannot target per-player board")) {
413
- return "CARD_HOME_PER_PLAYER_BOARD_REJECTED";
414
- }
415
- return "AUTHORING_VALIDATION_ERROR";
416
- }
417
- function createManifestConformanceCases() {
418
- return deepFreeze(
419
- fixtures
420
- );
421
- }
422
-
423
- // src/authoring/adapter.ts
424
- var PLAYER_IDS = ["player-1", "player-2"];
425
- function stableJson(value) {
426
- if (value === void 0) {
427
- return "null";
428
- }
429
- if (value === null || typeof value !== "object") {
430
- return JSON.stringify(value);
431
- }
432
- if (Array.isArray(value)) {
433
- return `[${value.map((item) => stableJson(item)).join(",")}]`;
434
- }
435
- return `{${Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
436
- }
437
- function sha256(value) {
438
- return createHash("sha256").update(value).digest("hex");
439
- }
440
- function assertManifest(manifest) {
441
- if (!manifest || typeof manifest !== "object") {
442
- throw new Error("Expected a manifest object.");
443
- }
444
- return manifest;
445
- }
446
- function normalizeArtifact(path, content, ownership) {
447
- if (path.length === 0 || path.startsWith("/") || path.includes("\\") || path.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
448
- throw new Error(`Generated artifact path '${path}' is not normalized.`);
449
- }
450
- return {
451
- path,
452
- ownership,
453
- content,
454
- contentSha256: sha256(content)
455
- };
456
- }
457
- function normalizeArtifacts(entries, ownership) {
458
- return Object.entries(entries).map(([path, content]) => normalizeArtifact(path, content, ownership)).sort((left, right) => left.path.localeCompare(right.path));
459
- }
460
- function validateNoDuplicateArtifactPaths(artifacts) {
461
- const seen = /* @__PURE__ */ new Set();
462
- for (const artifact of artifacts) {
463
- if (seen.has(artifact.path)) {
464
- throw new Error(
465
- `Generated artifact path '${artifact.path}' was emitted twice.`
466
- );
467
- }
468
- seen.add(artifact.path);
469
- if (artifact.contentSha256 !== sha256(artifact.content)) {
470
- throw new Error(
471
- `Generated artifact '${artifact.path}' has a stale hash.`
472
- );
473
- }
474
- }
475
- }
476
- function validateManifest(manifest) {
477
- try {
478
- const gameManifest = assertManifest(manifest);
479
- const result = validateManifestAuthoring(gameManifest);
480
- const errors = [...result.errors];
481
- if (errors.length === 0) {
482
- try {
483
- materializeManifest(gameManifest);
484
- } catch (error) {
485
- errors.push(error instanceof Error ? error.message : String(error));
486
- }
487
- }
488
- return {
489
- valid: errors.length === 0,
490
- errors,
491
- warnings: result.warnings
492
- };
493
- } catch (error) {
494
- return {
495
- valid: false,
496
- errors: [error instanceof Error ? error.message : String(error)],
497
- warnings: []
498
- };
499
- }
500
- }
501
- function materializeManifest(manifest) {
502
- return materializeManifestTable({
503
- manifest: assertManifest(manifest),
504
- playerIds: PLAYER_IDS,
505
- shuffleItems: (values) => [...values]
506
- });
507
- }
508
- function generateWorkspaceArtifacts(manifest) {
509
- const gameManifest = assertManifest(manifest);
510
- const artifacts = [
511
- ...normalizeArtifacts(
512
- generateAuthoritativeFiles(gameManifest),
513
- "authoritative"
514
- ),
515
- ...normalizeArtifacts(generateSeedFiles(gameManifest), "seed")
516
- ].sort((left, right) => left.path.localeCompare(right.path));
517
- validateNoDuplicateArtifactPaths(artifacts);
518
- return artifacts;
519
- }
520
- function generateTestArtifacts(input) {
521
- const materialized = materializeManifest(input.manifest);
522
- return [
523
- normalizeArtifact(
524
- "test/generated/base-state.json",
525
- `${stableJson(materialized)}
526
- `,
527
- "derived-test"
528
- )
529
- ];
530
- }
531
- var GENERATED_WORKSPACE_PATHS = [
532
- ...AUTHORITATIVE_GENERATED_FILES,
533
- ...SEED_FILES,
534
- "test/generated/base-state.json"
535
- ];
536
- var GENERATED_WORKSPACE_PATH_PATTERNS = SEED_FILE_PATTERNS;
537
- var MANIFEST_CONFORMANCE_CASES = createManifestConformanceCases();
538
- var projectAuthoringAdapter = {
539
- protocolVersion: 1,
540
- metadata: GENERATED_AUTHORING_METADATA,
541
- generatedPaths: GENERATED_WORKSPACE_PATHS,
542
- generatedPathPatterns: GENERATED_WORKSPACE_PATH_PATTERNS,
543
- manifestConformanceCases: MANIFEST_CONFORMANCE_CASES,
544
- validateManifest,
545
- materializeManifest,
2
+ GENERATED_WORKSPACE_PATHS,
3
+ GENERATED_WORKSPACE_PATH_PATTERNS,
4
+ MANIFEST_CONFORMANCE_CASES,
5
+ diagnosticCodesForValidationErrors,
546
6
  generateWorkspaceArtifacts,
547
- generateTestArtifacts
548
- };
7
+ materializeManifest,
8
+ projectAuthoringAdapter,
9
+ validateManifest
10
+ } from "../chunk-KGV2EUNN.js";
11
+ import "../chunk-KWHOFBDM.js";
12
+ import "../chunk-HIH6Y4FA.js";
13
+ import "../chunk-PZ5AY32C.js";
549
14
  export {
550
15
  GENERATED_WORKSPACE_PATHS,
551
16
  GENERATED_WORKSPACE_PATH_PATTERNS,
552
17
  MANIFEST_CONFORMANCE_CASES,
553
18
  diagnosticCodesForValidationErrors,
554
- generateTestArtifacts,
555
19
  generateWorkspaceArtifacts,
556
20
  materializeManifest,
557
21
  projectAuthoringAdapter,