@dreamboard-games/sdk 0.4.0-alpha.1 → 0.4.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/REFERENCE.md +1318 -201
  2. package/dist/{ResourceCounter-BTXklCEZ.d.ts → ResourceCounter-BuiNstXs.d.ts} +5 -1
  3. package/dist/{ThemeProvider-DvMl17Ny.d.ts → ThemeProvider-B1sIoBlX.d.ts} +1 -1
  4. package/dist/{attributes-BrZtP9az.d.ts → attributes-DbvyMbXw.d.ts} +17 -2
  5. package/dist/authoring/index.d.ts +66 -0
  6. package/dist/authoring/index.js +560 -0
  7. package/dist/authoring/index.js.map +1 -0
  8. package/dist/browser-interaction.d.ts +205 -5
  9. package/dist/browser-interaction.js +14 -2
  10. package/dist/{chunk-7W6TQO3X.js → chunk-45FI6XII.js} +613 -366
  11. package/dist/chunk-45FI6XII.js.map +1 -0
  12. package/dist/{chunk-3K362ZKR.js → chunk-6JQFGSLD.js} +202 -38
  13. package/dist/chunk-6JQFGSLD.js.map +1 -0
  14. package/dist/{chunk-IUGKW2GS.js → chunk-BKD7XAWB.js} +6 -2
  15. package/dist/chunk-BKD7XAWB.js.map +1 -0
  16. package/dist/{chunk-XXBSIPJX.js → chunk-CP35NPPY.js} +131 -59
  17. package/dist/chunk-CP35NPPY.js.map +1 -0
  18. package/dist/chunk-DQ7GCD6C.js +12 -0
  19. package/dist/chunk-DQ7GCD6C.js.map +1 -0
  20. package/dist/{chunk-XJYUSD5F.js → chunk-FWVV2X74.js} +2 -2
  21. package/dist/chunk-K5ZRJTZZ.js +328 -0
  22. package/dist/chunk-K5ZRJTZZ.js.map +1 -0
  23. package/dist/{chunk-7LZZEI25.js → chunk-N6ZDIMRB.js} +1 -1
  24. package/dist/chunk-N6ZDIMRB.js.map +1 -0
  25. package/dist/chunk-O6M6PN4E.js +1225 -0
  26. package/dist/chunk-O6M6PN4E.js.map +1 -0
  27. package/dist/{chunk-AEUXCFGM.js → chunk-PF7L4BMG.js} +1 -8
  28. package/dist/{chunk-AEUXCFGM.js.map → chunk-PF7L4BMG.js.map} +1 -1
  29. package/dist/{chunk-CZMFAS3E.js → chunk-WOWFONLZ.js} +517 -1274
  30. package/dist/chunk-WOWFONLZ.js.map +1 -0
  31. package/dist/{chunk-MALRKLRR.js → chunk-WUIVY2KE.js} +301 -12
  32. package/dist/chunk-WUIVY2KE.js.map +1 -0
  33. package/dist/codegen.d.ts +11 -3
  34. package/dist/codegen.js +1 -1
  35. package/dist/{components-Dqr_LuZJ.d.ts → components-BbWPnZCF.d.ts} +37 -6
  36. package/dist/{hex-board-view-UCUjMALd.d.ts → hex-board-view-Kz9Q_zsv.d.ts} +1 -1
  37. package/dist/index-BLwlj7mO.d.ts +191 -0
  38. package/dist/index.js +2 -1
  39. package/dist/package-set.d.ts +2 -2
  40. package/dist/package-set.js +2 -1
  41. package/dist/player-state-Cqpyeql0.d.ts +371 -0
  42. package/dist/protocol-BP193lva.d.ts +267 -0
  43. package/dist/reducer/advanced.js +1 -1
  44. package/dist/reducer-contract.js +1 -1
  45. package/dist/reducer.js +2 -2
  46. package/dist/reducer.js.map +1 -1
  47. package/dist/runtime/primitives.d.ts +10 -10
  48. package/dist/runtime/primitives.js +9 -7
  49. package/dist/runtime/runtime-api.d.ts +2 -2
  50. package/dist/runtime/workspace-contract.d.ts +21 -167
  51. package/dist/runtime/workspace-contract.js +7 -6
  52. package/dist/runtime-api-BJharVaj.d.ts +198 -0
  53. package/dist/runtime-api-C6aWo9c0.d.ts +95 -0
  54. package/dist/runtime.d.ts +36 -32
  55. package/dist/runtime.js +87 -797
  56. package/dist/runtime.js.map +1 -1
  57. package/dist/testing.d.ts +254 -140
  58. package/dist/testing.js +964 -149
  59. package/dist/testing.js.map +1 -1
  60. package/dist/types-CYeN0wLK.d.ts +29 -0
  61. package/dist/{types-BqzHkNMA.d.ts → types-DJj5MJkl.d.ts} +32 -5
  62. package/dist/types.d.ts +13 -8
  63. package/dist/ui/components.d.ts +4 -5
  64. package/dist/ui/components.js +19 -1
  65. package/dist/ui/player-state.d.ts +2 -365
  66. package/dist/{ui-contract-W2-kxObe.d.ts → ui-contract-CY7cxsCC.d.ts} +16 -26
  67. package/dist/ui.d.ts +7 -8
  68. package/dist/ui.js +20 -2
  69. package/package.json +25 -19
  70. package/dist/chunk-3K362ZKR.js.map +0 -1
  71. package/dist/chunk-7LZZEI25.js.map +0 -1
  72. package/dist/chunk-7W6TQO3X.js.map +0 -1
  73. package/dist/chunk-CZMFAS3E.js.map +0 -1
  74. package/dist/chunk-IUGKW2GS.js.map +0 -1
  75. package/dist/chunk-MALRKLRR.js.map +0 -1
  76. package/dist/chunk-XXBSIPJX.js.map +0 -1
  77. package/dist/hex-color-MhOyuY-o.d.ts +0 -8
  78. package/dist/runtime-api-BXd70c2e.d.ts +0 -490
  79. /package/dist/{chunk-XJYUSD5F.js.map → chunk-FWVV2X74.js.map} +0 -0
@@ -28,6 +28,10 @@ declare function useRegisterMobileHand(hand: MobileHandRegistration): void;
28
28
  * the breakpoint with a CSS media query. Returns `false` outside `<UI.Root>`.
29
29
  */
30
30
  declare function useMobileHandTrayActive(): boolean;
31
+ declare function useOverlayInsets(): {
32
+ bottom: number;
33
+ };
34
+ declare function useRegisterBottomOverlayInset(id: string, height: number): void;
31
35
 
32
36
  type ResourceId = string;
33
37
  interface ResourceDisplayConfig<Resource extends string = ResourceId> {
@@ -99,4 +103,4 @@ declare const ResourceCounter: {
99
103
  Label: typeof ResourceCounterLabel;
100
104
  };
101
105
 
102
- export { type BoundResourceCounterRootProps as B, type HandRole as H, type MobileHandRegistration as M, ResourceCounter as R, MobileHandTrayProvider as a, type ResourceCounterComponents as b, ResourceCounterCount as c, ResourceCounterIcon as d, ResourceCounterItem as e, type ResourceCounterItemState as f, ResourceCounterLabel as g, type ResourceCounterPartProps as h, type ResourceCounterProps as i, ResourceCounterRoot as j, type ResourceCounterRootProps as k, type ResourceDisplayConfig as l, type ResourceIconProps as m, createResourceCounter as n, useRegisterMobileHand as o, useMobileHandTrayActive as u };
106
+ export { type BoundResourceCounterRootProps as B, type HandRole as H, type MobileHandRegistration as M, ResourceCounter as R, MobileHandTrayProvider as a, type ResourceCounterComponents as b, ResourceCounterCount as c, ResourceCounterIcon as d, ResourceCounterItem as e, type ResourceCounterItemState as f, ResourceCounterLabel as g, type ResourceCounterPartProps as h, type ResourceCounterProps as i, ResourceCounterRoot as j, type ResourceCounterRootProps as k, type ResourceDisplayConfig as l, type ResourceIconProps as m, createResourceCounter as n, useOverlayInsets as o, useRegisterBottomOverlayInset as p, useRegisterMobileHand as q, useMobileHandTrayActive as u };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { CSSProperties, ReactNode } from 'react';
3
- import { $ as Theme, a1 as ThemeOverride } from './hex-board-view-UCUjMALd.js';
3
+ import { $ as Theme, a1 as ThemeOverride } from './hex-board-view-Kz9Q_zsv.js';
4
4
 
5
5
  /**
6
6
  * The set of preset theme ids ships in `@dreamboard-games/sdk/ui`. Authors
@@ -1,4 +1,4 @@
1
- import { q as BrowserInteractionIntent, i as BrowserInteractionCandidateState, h as BrowserInteractionActuatorKind, G as BrowserInteractionSurfaceEffect, k as BrowserInteractionEffectPattern, s as BrowserInteractionPreparationTarget, v as BrowserInteractionReadiness, R as GameplayBrowserInteractionIntent, T as GameplaySemanticEffect, U as GameplaySemanticEffectPattern } from './types-BqzHkNMA.js';
1
+ import { q as BrowserInteractionIntent, i as BrowserInteractionCandidateState, h as BrowserInteractionActuatorKind, K as BrowserInteractionSurfaceEffect, k as BrowserInteractionEffectPattern, w as BrowserInteractionPreparationTarget, z as BrowserInteractionReadiness, V as GameplayBrowserInteractionIntent, X as GameplaySemanticEffect, Y as GameplaySemanticEffectPattern } from './types-DJj5MJkl.js';
2
2
 
3
3
  type BrowserInteractionAttributeMap = Record<string, string | boolean>;
4
4
  interface BrowserInteractionRootAttributesInput {
@@ -29,8 +29,19 @@ interface BrowserInteractionActuatorAttributesInput {
29
29
  readonly preparationPatterns?: readonly BrowserInteractionEffectPattern[];
30
30
  readonly prepares?: BrowserInteractionPreparationTarget;
31
31
  }
32
+ interface BrowserInteractionPointerTargetAttributesInput {
33
+ readonly surface: string;
34
+ readonly scopeId: string;
35
+ readonly interactionKey: string;
36
+ readonly interactionId: string;
37
+ readonly descriptorDigest?: string;
38
+ readonly targetId: string;
39
+ readonly enabled?: boolean;
40
+ readonly acceptedEffectPatterns: readonly BrowserInteractionEffectPattern[];
41
+ }
32
42
  declare function createBrowserInteractionRootAttributes(input: BrowserInteractionRootAttributesInput): BrowserInteractionAttributeMap;
33
43
  declare function createBrowserInteractionActuatorAttributes(input: BrowserInteractionActuatorAttributesInput): BrowserInteractionAttributeMap;
44
+ declare function createBrowserInteractionPointerTargetAttributes(input: BrowserInteractionPointerTargetAttributesInput): BrowserInteractionAttributeMap;
34
45
  type GameplayInteractionRootAttributesInput = Omit<BrowserInteractionRootAttributesInput, "surface">;
35
46
  type GameplayActuatorAttributesInput = Omit<BrowserInteractionActuatorAttributesInput, "surface" | "intent" | "semanticEffects" | "acceptedEffectPatterns" | "preparationPatterns"> & {
36
47
  readonly intent: GameplayBrowserInteractionIntent;
@@ -38,8 +49,12 @@ type GameplayActuatorAttributesInput = Omit<BrowserInteractionActuatorAttributes
38
49
  readonly acceptedEffectPatterns?: readonly GameplaySemanticEffectPattern[];
39
50
  readonly preparationPatterns?: readonly GameplaySemanticEffectPattern[];
40
51
  };
52
+ type GameplayPointerTargetAttributesInput = Omit<BrowserInteractionPointerTargetAttributesInput, "surface" | "acceptedEffectPatterns"> & {
53
+ readonly acceptedEffectPatterns: readonly GameplaySemanticEffectPattern[];
54
+ };
41
55
  declare function createGameplayInteractionRootAttributes(input: GameplayInteractionRootAttributesInput): BrowserInteractionAttributeMap;
42
56
  declare function createGameplayActuatorAttributes(input: GameplayActuatorAttributesInput): BrowserInteractionAttributeMap;
57
+ declare function createGameplayPointerTargetAttributes(input: GameplayPointerTargetAttributesInput): BrowserInteractionAttributeMap;
43
58
  declare function createBrowserInteractionActuatorKey(input: {
44
59
  readonly surface: string;
45
60
  readonly scopeId: string;
@@ -50,4 +65,4 @@ declare function createBrowserInteractionActuatorKey(input: {
50
65
  readonly actuatorKind: BrowserInteractionActuatorKind;
51
66
  }): string;
52
67
 
53
- export { type BrowserInteractionActuatorAttributesInput as B, type GameplayActuatorAttributesInput as G, type BrowserInteractionAttributeMap as a, type BrowserInteractionRootAttributesInput as b, type GameplayInteractionRootAttributesInput as c, createBrowserInteractionActuatorAttributes as d, createBrowserInteractionActuatorKey as e, createBrowserInteractionRootAttributes as f, createGameplayActuatorAttributes as g, createGameplayInteractionRootAttributes as h };
68
+ export { type BrowserInteractionActuatorAttributesInput as B, type GameplayActuatorAttributesInput as G, type BrowserInteractionAttributeMap as a, type BrowserInteractionPointerTargetAttributesInput as b, type BrowserInteractionRootAttributesInput as c, type GameplayInteractionRootAttributesInput as d, type GameplayPointerTargetAttributesInput as e, createBrowserInteractionActuatorAttributes as f, createBrowserInteractionActuatorKey as g, createBrowserInteractionPointerTargetAttributes as h, createBrowserInteractionRootAttributes as i, createGameplayActuatorAttributes as j, createGameplayInteractionRootAttributes as k, createGameplayPointerTargetAttributes as l };
@@ -0,0 +1,66 @@
1
+ import { JsonValue, GameTopologyManifest } from '../types.js';
2
+
3
+ type GeneratedAuthoringMetadataV1 = {
4
+ sdkVersion: string;
5
+ codegenVersion: string;
6
+ manifestSchemaVersion: number;
7
+ generatedArtifactSchemaVersion: number;
8
+ };
9
+ type AuthoringValidationResultV1 = {
10
+ valid: boolean;
11
+ errors: readonly string[];
12
+ warnings: readonly string[];
13
+ };
14
+ type GeneratedArtifactV1 = {
15
+ path: string;
16
+ ownership: "authoritative" | "seed" | "derived-test";
17
+ content: string;
18
+ contentSha256: string;
19
+ };
20
+ type GeneratedPathPatternV1 = {
21
+ prefix: string;
22
+ suffix: string;
23
+ };
24
+ type GenerateTestArtifactsInputV1 = {
25
+ manifest: GameTopologyManifest;
26
+ };
27
+ type AuthoringManifestConformanceCaseV1 = {
28
+ id: string;
29
+ manifest: JsonValue;
30
+ expected: {
31
+ valid: true;
32
+ transportValid: true;
33
+ materializedSha256: string;
34
+ } | {
35
+ valid: false;
36
+ transportValid: boolean;
37
+ diagnosticCodes: readonly string[];
38
+ };
39
+ };
40
+ type ProjectAuthoringAdapterV1 = {
41
+ protocolVersion: 1;
42
+ metadata: GeneratedAuthoringMetadataV1;
43
+ generatedPaths: readonly string[];
44
+ generatedPathPatterns: readonly GeneratedPathPatternV1[];
45
+ manifestConformanceCases: readonly AuthoringManifestConformanceCaseV1[];
46
+ validateManifest(manifest: unknown): AuthoringValidationResultV1;
47
+ materializeManifest(manifest: unknown): JsonValue;
48
+ generateWorkspaceArtifacts(manifest: unknown): readonly GeneratedArtifactV1[];
49
+ generateTestArtifacts(input: GenerateTestArtifactsInputV1): readonly GeneratedArtifactV1[];
50
+ };
51
+
52
+ declare function diagnosticCodesForValidationErrors(errors: readonly string[]): readonly string[];
53
+
54
+ declare function validateManifest(manifest: unknown): AuthoringValidationResultV1;
55
+ declare function materializeManifest(manifest: unknown): JsonValue;
56
+ 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"];
59
+ declare const GENERATED_WORKSPACE_PATH_PATTERNS: {
60
+ prefix: string;
61
+ suffix: string;
62
+ }[];
63
+ declare const MANIFEST_CONFORMANCE_CASES: readonly AuthoringManifestConformanceCaseV1[];
64
+ declare const projectAuthoringAdapter: ProjectAuthoringAdapterV1;
65
+
66
+ 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 };
@@ -0,0 +1,560 @@
1
+ import {
2
+ GENERATED_AUTHORING_METADATA
3
+ } from "../chunk-DQ7GCD6C.js";
4
+ import {
5
+ AUTHORITATIVE_GENERATED_FILES,
6
+ SEED_FILES,
7
+ SEED_FILE_PATTERNS,
8
+ generateAuthoritativeFiles,
9
+ generateSeedFiles,
10
+ materializeManifestTable,
11
+ validateManifestAuthoring
12
+ } from "../chunk-CP35NPPY.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,
546
+ generateWorkspaceArtifacts,
547
+ generateTestArtifacts
548
+ };
549
+ export {
550
+ GENERATED_WORKSPACE_PATHS,
551
+ GENERATED_WORKSPACE_PATH_PATTERNS,
552
+ MANIFEST_CONFORMANCE_CASES,
553
+ diagnosticCodesForValidationErrors,
554
+ generateTestArtifacts,
555
+ generateWorkspaceArtifacts,
556
+ materializeManifest,
557
+ projectAuthoringAdapter,
558
+ validateManifest
559
+ };
560
+ //# sourceMappingURL=index.js.map