@dreamboard-games/sdk 0.5.0-alpha.2 → 0.5.0-alpha.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.
Files changed (151) hide show
  1. package/README.md +186 -45
  2. package/dist/board-target-B0QG6OYx.d.ts +8 -0
  3. package/dist/chunk-3JXUL4VN.js +139 -0
  4. package/dist/chunk-3JXUL4VN.js.map +1 -0
  5. package/dist/{chunk-S2JEDVWH.js → chunk-C77SYIVT.js} +6102 -6505
  6. package/dist/chunk-C77SYIVT.js.map +1 -0
  7. package/dist/chunk-DMFVAZI2.js +16 -0
  8. package/dist/chunk-DMFVAZI2.js.map +1 -0
  9. package/dist/chunk-OOFMBCFF.js +1338 -0
  10. package/dist/chunk-OOFMBCFF.js.map +1 -0
  11. package/dist/chunk-UG2Q4NLG.js +590 -0
  12. package/dist/chunk-UG2Q4NLG.js.map +1 -0
  13. package/dist/chunk-XU6WJW6K.js +847 -0
  14. package/dist/chunk-XU6WJW6K.js.map +1 -0
  15. package/dist/diagnostics-B8d5aLad.d.ts +65 -0
  16. package/dist/extract-gVKcB8Og.d.ts +4736 -0
  17. package/dist/index.d.ts +3782 -1
  18. package/dist/index.js +1096 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/model-vdpLHrxh.d.ts +432 -0
  21. package/dist/react.d.ts +60 -0
  22. package/dist/react.js +208 -0
  23. package/dist/react.js.map +1 -0
  24. package/dist/reducer.d.ts +1244 -78
  25. package/dist/reducer.js +4204 -121
  26. package/dist/reducer.js.map +1 -1
  27. package/dist/testing.d.ts +520 -564
  28. package/dist/testing.js +2451 -915
  29. package/dist/testing.js.map +1 -1
  30. package/dist/types-Bj5ZLTUV.d.ts +114 -0
  31. package/package.json +40 -142
  32. package/dist/HandView-Bi2lxzQP.d.ts +0 -79
  33. package/dist/ResourceCounter-BFxJknqp.d.ts +0 -98
  34. package/dist/ThemeProvider-CElaL2ik.d.ts +0 -99
  35. package/dist/attributes-DbvyMbXw.d.ts +0 -68
  36. package/dist/browser-interaction.d.ts +0 -910
  37. package/dist/browser-interaction.js +0 -119
  38. package/dist/browser-interaction.js.map +0 -1
  39. package/dist/chunk-32PFKDV7.js +0 -11705
  40. package/dist/chunk-32PFKDV7.js.map +0 -1
  41. package/dist/chunk-3BAD4VC2.js +0 -263
  42. package/dist/chunk-3BAD4VC2.js.map +0 -1
  43. package/dist/chunk-3SKDNDPG.js +0 -104
  44. package/dist/chunk-3SKDNDPG.js.map +0 -1
  45. package/dist/chunk-5YV2WHJ4.js +0 -25
  46. package/dist/chunk-5YV2WHJ4.js.map +0 -1
  47. package/dist/chunk-ANRB4XKA.js +0 -90
  48. package/dist/chunk-ANRB4XKA.js.map +0 -1
  49. package/dist/chunk-BI4G3PM2.js +0 -1864
  50. package/dist/chunk-BI4G3PM2.js.map +0 -1
  51. package/dist/chunk-EVCLTY4Q.js +0 -935
  52. package/dist/chunk-EVCLTY4Q.js.map +0 -1
  53. package/dist/chunk-GDPKTBUR.js +0 -564
  54. package/dist/chunk-GDPKTBUR.js.map +0 -1
  55. package/dist/chunk-H6VDGFL5.js +0 -2903
  56. package/dist/chunk-H6VDGFL5.js.map +0 -1
  57. package/dist/chunk-LR3ZTWQF.js +0 -5960
  58. package/dist/chunk-LR3ZTWQF.js.map +0 -1
  59. package/dist/chunk-PF7L4BMG.js +0 -117
  60. package/dist/chunk-PF7L4BMG.js.map +0 -1
  61. package/dist/chunk-PN5O6GG2.js +0 -32
  62. package/dist/chunk-PN5O6GG2.js.map +0 -1
  63. package/dist/chunk-PZ5AY32C.js +0 -10
  64. package/dist/chunk-PZ5AY32C.js.map +0 -1
  65. package/dist/chunk-S2JEDVWH.js.map +0 -1
  66. package/dist/chunk-T3ZKNUZ7.js +0 -1
  67. package/dist/chunk-T3ZKNUZ7.js.map +0 -1
  68. package/dist/chunk-UGH54WZ2.js +0 -223
  69. package/dist/chunk-UGH54WZ2.js.map +0 -1
  70. package/dist/chunk-VCDWP5VL.js +0 -746
  71. package/dist/chunk-VCDWP5VL.js.map +0 -1
  72. package/dist/chunk-VDXOF4FW.js +0 -69
  73. package/dist/chunk-VDXOF4FW.js.map +0 -1
  74. package/dist/chunk-WHR5UW3F.js +0 -1988
  75. package/dist/chunk-WHR5UW3F.js.map +0 -1
  76. package/dist/chunk-Y75CFE77.js +0 -17
  77. package/dist/chunk-Y75CFE77.js.map +0 -1
  78. package/dist/chunk-Z7QCREWI.js +0 -3435
  79. package/dist/chunk-Z7QCREWI.js.map +0 -1
  80. package/dist/chunk-ZZGN2ATS.js +0 -1941
  81. package/dist/chunk-ZZGN2ATS.js.map +0 -1
  82. package/dist/components-gAbIz7hK.d.ts +0 -1284
  83. package/dist/definitions-BgmV_GhC.d.ts +0 -300
  84. package/dist/diagnostics-DIi3ina7.d.ts +0 -50
  85. package/dist/digest.d.ts +0 -8
  86. package/dist/game-CsZScpcn.d.ts +0 -763
  87. package/dist/hex-board-view-aKkblDp6.d.ts +0 -1228
  88. package/dist/index-CcT9Q7N7.d.ts +0 -193
  89. package/dist/index.d-DjzoK7zn.d.ts +0 -2101
  90. package/dist/package-set.d.ts +0 -13
  91. package/dist/package-set.js +0 -12
  92. package/dist/package-set.js.map +0 -1
  93. package/dist/player-state-Cqpyeql0.d.ts +0 -371
  94. package/dist/plugin-runtime-contract.d.ts +0 -17
  95. package/dist/plugin-runtime-contract.js +0 -92
  96. package/dist/plugin-runtime-contract.js.map +0 -1
  97. package/dist/primitive-props-BNHDkgd7.d.ts +0 -16
  98. package/dist/protocol-dYgafTYY.d.ts +0 -314
  99. package/dist/reducer/advanced.d.ts +0 -82
  100. package/dist/reducer/advanced.js +0 -51
  101. package/dist/reducer/advanced.js.map +0 -1
  102. package/dist/reducer-contract.d.ts +0 -11
  103. package/dist/reducer-contract.js +0 -16
  104. package/dist/reducer-contract.js.map +0 -1
  105. package/dist/reference-games/index.d.ts +0 -31
  106. package/dist/reference-games/index.js +0 -48
  107. package/dist/reference-games/index.js.map +0 -1
  108. package/dist/runtime/primitives.d.ts +0 -250
  109. package/dist/runtime/primitives.js +0 -189
  110. package/dist/runtime/primitives.js.map +0 -1
  111. package/dist/runtime/runtime-api.d.ts +0 -2
  112. package/dist/runtime/runtime-api.js +0 -1
  113. package/dist/runtime/runtime-api.js.map +0 -1
  114. package/dist/runtime/workspace-contract.d.ts +0 -392
  115. package/dist/runtime/workspace-contract.js +0 -28
  116. package/dist/runtime/workspace-contract.js.map +0 -1
  117. package/dist/runtime-RJ5orDJU.d.ts +0 -1699
  118. package/dist/runtime-api-Bz5pwNU_.d.ts +0 -296
  119. package/dist/runtime-json-CQ9QbLZ5.d.ts +0 -5
  120. package/dist/runtime.d.ts +0 -83
  121. package/dist/runtime.js +0 -242
  122. package/dist/runtime.js.map +0 -1
  123. package/dist/schema.d.ts +0 -379
  124. package/dist/stale-contract-artifact-error-XLaweZtF.d.ts +0 -18
  125. package/dist/testing-compiler.d.ts +0 -37
  126. package/dist/testing-compiler.js +0 -272
  127. package/dist/testing-compiler.js.map +0 -1
  128. package/dist/testing-runtime.d.ts +0 -119
  129. package/dist/testing-runtime.js +0 -212
  130. package/dist/testing-runtime.js.map +0 -1
  131. package/dist/types-DJj5MJkl.d.ts +0 -256
  132. package/dist/types-DR7DoB1x.d.ts +0 -28
  133. package/dist/types-JWCYHmu7.d.ts +0 -122
  134. package/dist/types.d.ts +0 -1958
  135. package/dist/types.js +0 -14
  136. package/dist/types.js.map +0 -1
  137. package/dist/ui/components.d.ts +0 -17
  138. package/dist/ui/components.js +0 -216
  139. package/dist/ui/components.js.map +0 -1
  140. package/dist/ui/defaults.d.ts +0 -19
  141. package/dist/ui/defaults.js +0 -104
  142. package/dist/ui/defaults.js.map +0 -1
  143. package/dist/ui/player-state.d.ts +0 -2
  144. package/dist/ui/player-state.js +0 -1
  145. package/dist/ui/player-state.js.map +0 -1
  146. package/dist/ui/plugin-styles.css +0 -2
  147. package/dist/ui-contract-GTUPkf8z.d.ts +0 -1168
  148. package/dist/ui.d.ts +0 -317
  149. package/dist/ui.js +0 -277
  150. package/dist/ui.js.map +0 -1
  151. package/dist/views-BpuWcOyN.d.ts +0 -1641
@@ -0,0 +1,590 @@
1
+ import {
2
+ immutableCopy
3
+ } from "./chunk-DMFVAZI2.js";
4
+ import {
5
+ BoardStaticProjectionSchema,
6
+ GameEventDetailSchema,
7
+ GameEventSchema,
8
+ GameOutcomeSchema,
9
+ InteractionDescriptorSchema,
10
+ RuntimeJsonSchema,
11
+ SeatProjectionBundleSchema,
12
+ SimultaneousPhaseProjectionSchema,
13
+ SystemActionEventSchema,
14
+ canonicalizePluginRuntimeJson,
15
+ digestPluginRuntimeJson
16
+ } from "./chunk-XU6WJW6K.js";
17
+
18
+ // src/shared/protocol/protocol.ts
19
+ var DREAMBOARD_PLUGIN_PROTOCOL = "dreamboard-plugin";
20
+ var DREAMBOARD_PLUGIN_PROTOCOL_VERSION = 6;
21
+
22
+ // src/shared/protocol/schema.ts
23
+ import { z } from "zod";
24
+ var BoardStaticProjectionSchema2 = BoardStaticProjectionSchema;
25
+ var GameEventDetailSchema2 = GameEventDetailSchema;
26
+ var SystemActionEventSchema2 = SystemActionEventSchema;
27
+ var GameEventSchema2 = GameEventSchema;
28
+ var SeatProjectionBundleSchema2 = SeatProjectionBundleSchema;
29
+ var PlayerIdSchema = z.string().min(1);
30
+ var PluginPlayerSummarySchema = z.object({
31
+ playerId: PlayerIdSchema,
32
+ displayName: z.string(),
33
+ color: z.string().optional()
34
+ }).strict();
35
+ var PluginSessionDescriptorSchema = z.object({
36
+ sessionId: z.string().min(1),
37
+ players: z.array(PluginPlayerSummarySchema),
38
+ assets: z.record(z.string(), z.instanceof(Blob)).optional()
39
+ }).strict();
40
+ var ZoneHandlesSnapshotSchema = z.object({
41
+ cardIds: z.array(z.string()),
42
+ cardViewsById: z.record(z.string(), z.string()),
43
+ playableByCardId: z.record(
44
+ z.string(),
45
+ z.array(InteractionDescriptorSchema)
46
+ )
47
+ }).strict();
48
+ var SimultaneousPhaseSnapshotSchema = SimultaneousPhaseProjectionSchema;
49
+ var GameplayBasisSchema = z.object({
50
+ version: z.number().int().nonnegative(),
51
+ actionSetVersion: z.string().min(1),
52
+ perspectivePlayerId: PlayerIdSchema
53
+ }).strict();
54
+ var GameOutcomeSchema2 = GameOutcomeSchema;
55
+ var SeatFrameSchema = z.object({
56
+ events: z.array(GameEventSchema2).max(32),
57
+ view: z.record(z.string(), RuntimeJsonSchema).nullable(),
58
+ flow: z.object({
59
+ currentPhase: z.string().nullable(),
60
+ activePlayers: z.array(PlayerIdSchema),
61
+ simultaneousPhase: SimultaneousPhaseSnapshotSchema.nullable()
62
+ }).strict(),
63
+ availableInteractions: z.array(InteractionDescriptorSchema),
64
+ zones: z.record(z.string(), ZoneHandlesSnapshotSchema)
65
+ }).strict();
66
+ var PluginGameplayFrameSchema = SeatFrameSchema.extend({
67
+ basis: GameplayBasisSchema
68
+ });
69
+ var InteractionResultSchema = z.discriminatedUnion("accepted", [
70
+ z.object({
71
+ type: z.literal("interaction.result"),
72
+ clientActionId: z.string().min(1),
73
+ accepted: z.literal(true)
74
+ }).strict(),
75
+ z.object({
76
+ type: z.literal("interaction.result"),
77
+ clientActionId: z.string().min(1),
78
+ accepted: z.literal(false),
79
+ errorCode: z.string().min(1),
80
+ message: z.string().optional()
81
+ }).strict()
82
+ ]);
83
+ var SubmitInteractionCommandSchema = z.object({
84
+ type: z.literal("interaction.submit"),
85
+ clientActionId: z.string().min(1),
86
+ basis: GameplayBasisSchema,
87
+ interactionId: z.string().min(1),
88
+ params: RuntimeJsonSchema
89
+ }).strict();
90
+ var CancelInteractionCommandSchema = SubmitInteractionCommandSchema.omit({ params: true }).extend({ type: z.literal("interaction.cancel") }).strict();
91
+ var HostToPluginPayloadSchema = z.discriminatedUnion("type", [
92
+ z.object({
93
+ type: z.literal("runtime.init"),
94
+ session: PluginSessionDescriptorSchema
95
+ }).strict(),
96
+ z.object({
97
+ type: z.literal("gameplay.frame"),
98
+ frame: PluginGameplayFrameSchema
99
+ }).strict(),
100
+ InteractionResultSchema
101
+ ]);
102
+ var PluginToHostPayloadSchema = z.discriminatedUnion("type", [
103
+ z.object({ type: z.literal("runtime.ready") }).strict(),
104
+ z.object({ type: z.literal("runtime.resume") }).strict(),
105
+ z.object({
106
+ type: z.literal("runtime.ack"),
107
+ sequence: z.number().int().nonnegative(),
108
+ clientReceivedAtMs: z.number().finite().optional(),
109
+ clientRenderedAtMs: z.number().finite().optional()
110
+ }).strict(),
111
+ SubmitInteractionCommandSchema,
112
+ CancelInteractionCommandSchema,
113
+ z.object({
114
+ type: z.literal("runtime.error"),
115
+ message: z.string(),
116
+ code: z.string().optional()
117
+ }).strict()
118
+ ]);
119
+ function createPluginProtocolEnvelopeSchema(payloadSchema) {
120
+ return z.object({
121
+ protocol: z.literal(DREAMBOARD_PLUGIN_PROTOCOL),
122
+ version: z.literal(DREAMBOARD_PLUGIN_PROTOCOL_VERSION),
123
+ channelId: z.string().min(1),
124
+ sequence: z.number().int().nonnegative(),
125
+ payload: payloadSchema
126
+ }).strict();
127
+ }
128
+ var HostToPluginEnvelopeSchema = createPluginProtocolEnvelopeSchema(
129
+ HostToPluginPayloadSchema
130
+ );
131
+ var PluginToHostEnvelopeSchema = createPluginProtocolEnvelopeSchema(
132
+ PluginToHostPayloadSchema
133
+ );
134
+ function parsePluginSessionDescriptor(value) {
135
+ return PluginSessionDescriptorSchema.parse(value);
136
+ }
137
+ function parsePluginGameplayFrame(value) {
138
+ return PluginGameplayFrameSchema.parse(value);
139
+ }
140
+ function parseHostToPluginEnvelope(value) {
141
+ return HostToPluginEnvelopeSchema.parse(value);
142
+ }
143
+ function parsePluginToHostEnvelope(value) {
144
+ return PluginToHostEnvelopeSchema.parse(value);
145
+ }
146
+
147
+ // src/headless/sources/static.ts
148
+ import { createStore } from "@tanstack/store";
149
+ import { z as z2 } from "zod";
150
+ var SourceSnapshotSchema = z2.object({
151
+ me: z2.string().min(1),
152
+ players: z2.array(PluginPlayerSummarySchema),
153
+ frame: SeatFrameSchema,
154
+ version: z2.number().int().nonnegative()
155
+ }).strict();
156
+ function staticSource(input) {
157
+ const snapshot = immutableCopy(SourceSnapshotSchema.parse(input));
158
+ if (!snapshot.players.some((player) => player.playerId === snapshot.me))
159
+ throw new Error("Gameplay seat is absent from session.");
160
+ const store = createStore(
161
+ Object.freeze({
162
+ snapshot,
163
+ connection: "ready",
164
+ request: null,
165
+ failure: null
166
+ })
167
+ );
168
+ return {
169
+ store: {
170
+ get: () => store.get(),
171
+ subscribe: (listener) => store.subscribe(listener)
172
+ },
173
+ dispose() {
174
+ store.setState(
175
+ (state) => Object.freeze({
176
+ snapshot: state.snapshot,
177
+ connection: "closed",
178
+ request: null,
179
+ failure: null
180
+ })
181
+ );
182
+ }
183
+ };
184
+ }
185
+
186
+ // src/shared/protocol/digest.ts
187
+ function computePluginActionSetVersion(input) {
188
+ return digestPluginRuntimeJson({
189
+ digestVersion: "plugin-action-set@5",
190
+ version: input.version,
191
+ availableInteractions: input.availableInteractions
192
+ });
193
+ }
194
+ function digestPluginGameplayFrame(frame) {
195
+ return digestPluginRuntimeJson({
196
+ digestVersion: "plugin-gameplay-frame@5",
197
+ frame
198
+ });
199
+ }
200
+ function digestPluginCommandRequest(command) {
201
+ return digestPluginRuntimeJson({
202
+ digestVersion: "plugin-command-request@5",
203
+ command
204
+ });
205
+ }
206
+
207
+ // src/shared/protocol/projection.ts
208
+ function materializePluginGameplayFrame(input) {
209
+ const dynamicProjection = SeatProjectionBundleSchema2.parse(
210
+ canonicalizePluginRuntimeJson(input.dynamicProjection)
211
+ );
212
+ const staticProjection = input.staticProjection == null ? null : BoardStaticProjectionSchema2.parse(
213
+ canonicalizePluginRuntimeJson(input.staticProjection)
214
+ );
215
+ const registry = dynamicProjection.interactionsByRef ?? {};
216
+ const seat = dynamicProjection.seats[input.perspectivePlayerId] ?? null;
217
+ const availableInteractions = seat == null ? [] : hydrateInteractionRefs(
218
+ registry,
219
+ seat.availableInteractionRefs ?? [],
220
+ "availableInteractionRefs"
221
+ );
222
+ const zones = seat?.zones == null ? {} : hydrateZones(registry, seat.zones, "zones");
223
+ const frame = {
224
+ events: dynamicProjection.events,
225
+ basis: {
226
+ version: input.version,
227
+ actionSetVersion: input.actionSetVersion,
228
+ perspectivePlayerId: input.perspectivePlayerId
229
+ },
230
+ view: materializeView(staticProjection, seat?.view),
231
+ flow: {
232
+ currentPhase: input.currentPhase,
233
+ activePlayers: [...input.activePlayers],
234
+ simultaneousPhase: dynamicProjection.simultaneousPhase ?? null
235
+ },
236
+ availableInteractions,
237
+ zones
238
+ };
239
+ return PluginGameplayFrameSchema.parse(frame);
240
+ }
241
+ function materializeView(staticProjection, seatView) {
242
+ const parts = [staticProjection?.view, seatView].filter(
243
+ (part) => part !== void 0 && part !== null
244
+ );
245
+ if (parts.length === 0) return null;
246
+ return Object.assign({}, ...parts);
247
+ }
248
+ function hydrateZones(registry, value, path) {
249
+ return Object.fromEntries(
250
+ Object.entries(value).map(([zoneId, zone]) => [
251
+ zoneId,
252
+ {
253
+ cardIds: zone.cardIds,
254
+ cardViewsById: zone.cardViewsById,
255
+ playableByCardId: Object.fromEntries(
256
+ Object.entries(zone.playableByCardId).map(([cardId, refs]) => [
257
+ cardId,
258
+ hydrateInteractionRefs(
259
+ registry,
260
+ refs,
261
+ `${path}.${zoneId}.playableByCardId.${cardId}`
262
+ )
263
+ ])
264
+ )
265
+ }
266
+ ])
267
+ );
268
+ }
269
+ function hydrateInteractionRefs(registry, value, path) {
270
+ return value.map((ref, index) => {
271
+ const descriptor = registry[ref];
272
+ if (!descriptor) {
273
+ throw new Error(
274
+ `Seat projection ${path}[${index}] references '${ref}', which is missing from interactionsByRef.`
275
+ );
276
+ }
277
+ return descriptor;
278
+ });
279
+ }
280
+
281
+ // src/headless/sources/lifecycle.ts
282
+ import { createStore as createStore2 } from "@tanstack/store";
283
+ import { z as z3 } from "zod";
284
+ var CardImageViewSchema = z3.looseObject({
285
+ frontImage: z3.string().optional(),
286
+ backImage: z3.string().optional()
287
+ });
288
+ function createSourceLifecycle(options) {
289
+ let context = options.context ? immutableCopy(options.context) : null;
290
+ const store = createStore2(
291
+ Object.freeze({
292
+ snapshot: null,
293
+ connection: "connecting",
294
+ request: null,
295
+ failure: null
296
+ })
297
+ );
298
+ let session = null;
299
+ let assetUrls = null;
300
+ let basis = null;
301
+ let pending = null;
302
+ let timer;
303
+ let recovered = false;
304
+ let closed = false;
305
+ const clearTimer = () => {
306
+ clearTimeout(timer);
307
+ timer = void 0;
308
+ };
309
+ const publish = (state) => {
310
+ if (state.request) Object.freeze(state.request);
311
+ store.setState(() => Object.freeze(state));
312
+ };
313
+ const recovering = () => {
314
+ if (closed) return;
315
+ publish({ ...store.get(), connection: "recovering", failure: null });
316
+ };
317
+ const close = (failure) => {
318
+ if (closed) return;
319
+ closed = true;
320
+ clearTimer();
321
+ for (const url of Object.values(assetUrls ?? {})) URL.revokeObjectURL(url);
322
+ pending?.reject(failure ?? new Error("Gameplay source disposed."));
323
+ pending = null;
324
+ options.close();
325
+ const snapshot = store.get().snapshot;
326
+ publish(
327
+ failure ? {
328
+ connection: "failed",
329
+ snapshot,
330
+ request: null,
331
+ failure: Object.freeze(failure)
332
+ } : { connection: "closed", snapshot, request: null, failure: null }
333
+ );
334
+ };
335
+ const fail = (error) => close(error);
336
+ const arm = () => {
337
+ clearTimer();
338
+ timer = setTimeout(() => {
339
+ if (recovered) {
340
+ fail(new Error("Gameplay source recovery timed out."));
341
+ return;
342
+ }
343
+ recovered = true;
344
+ recovering();
345
+ try {
346
+ options.recover();
347
+ if (pending && !pending.accepted) options.send(pending.command);
348
+ arm();
349
+ } catch (error) {
350
+ fail(asError(error));
351
+ }
352
+ }, options.timeoutMs ?? 1e4);
353
+ };
354
+ const finishBarrier = () => {
355
+ if (!pending?.accepted) return;
356
+ const frame = store.get().snapshot;
357
+ if (!frame || frame.version <= pending.command.basis.version) return;
358
+ clearTimer();
359
+ pending = null;
360
+ publish({
361
+ snapshot: frame,
362
+ request: null,
363
+ connection: "ready",
364
+ failure: null
365
+ });
366
+ };
367
+ const start = async (operation, interactionId, params) => {
368
+ const state = store.get();
369
+ if (closed || state.connection !== "ready" || !basis)
370
+ return Promise.reject(new Error("Gameplay source is not open."));
371
+ if (pending)
372
+ return Promise.reject(
373
+ new Error("A gameplay interaction is already pending.")
374
+ );
375
+ const command = immutableCopy(
376
+ PluginToHostPayloadSchema.parse({
377
+ type: operation === "cancel" ? "interaction.cancel" : "interaction.submit",
378
+ clientActionId: crypto.randomUUID(),
379
+ basis,
380
+ interactionId,
381
+ ...operation === "cancel" ? {} : { params }
382
+ })
383
+ );
384
+ recovered = false;
385
+ const promise = new Promise((resolve, reject) => {
386
+ pending = { command, resolve, reject, accepted: false };
387
+ });
388
+ publish({
389
+ ...state,
390
+ request: {
391
+ interactionId,
392
+ operation,
393
+ phase: "awaiting-result"
394
+ }
395
+ });
396
+ arm();
397
+ try {
398
+ options.send(command);
399
+ } catch (error) {
400
+ fail(asError(error));
401
+ }
402
+ return promise;
403
+ };
404
+ const source = {
405
+ store: {
406
+ get: () => store.get(),
407
+ subscribe: (listener) => store.subscribe(listener)
408
+ },
409
+ submit: (interactionId, params) => start("submit", interactionId, params),
410
+ cancel: (interactionId) => start("cancel", interactionId),
411
+ dispose: () => close(null)
412
+ };
413
+ return {
414
+ source,
415
+ retry() {
416
+ if (closed || !pending) return;
417
+ try {
418
+ if (pending.accepted) options.recover();
419
+ else options.send(pending.command);
420
+ } catch (error) {
421
+ fail(asError(error));
422
+ }
423
+ },
424
+ fail,
425
+ recovering,
426
+ session(value) {
427
+ if (closed) return;
428
+ const { assets, ...parsed } = PluginSessionDescriptorSchema.parse(value);
429
+ if ((context?.sessionId ?? session?.sessionId) && parsed.sessionId !== (context?.sessionId ?? session?.sessionId)) {
430
+ fail(new Error("Gameplay session changed."));
431
+ return;
432
+ }
433
+ if (context && !parsed.players.some((player) => player.playerId === context.playerId)) {
434
+ fail(new Error("Gameplay seat is absent from session."));
435
+ return;
436
+ }
437
+ session = immutableCopy(parsed);
438
+ assetUrls ??= Object.fromEntries(
439
+ Object.entries(assets ?? {}).map(([path, blob]) => [
440
+ path,
441
+ URL.createObjectURL(blob)
442
+ ])
443
+ );
444
+ },
445
+ frame(value) {
446
+ if (closed) return;
447
+ const parsed = PluginGameplayFrameSchema.parse(value);
448
+ if (!session) {
449
+ fail(new Error("Gameplay frame arrived before session metadata."));
450
+ return;
451
+ }
452
+ context ??= {
453
+ sessionId: session.sessionId,
454
+ playerId: parsed.basis.perspectivePlayerId
455
+ };
456
+ if (parsed.basis.perspectivePlayerId !== context.playerId) {
457
+ fail(new Error("Gameplay perspective changed."));
458
+ return;
459
+ }
460
+ if (!session.players.some((player) => player.playerId === context.playerId)) {
461
+ fail(new Error("Gameplay seat is absent from session."));
462
+ return;
463
+ }
464
+ if (basis && parsed.basis.version < basis.version) return;
465
+ const { basis: nextBasis, ...frame } = immutableCopy(
466
+ withCardImageUrls(parsed, assetUrls)
467
+ );
468
+ basis = nextBasis;
469
+ publish({
470
+ failure: null,
471
+ request: store.get().request,
472
+ snapshot: Object.freeze({
473
+ me: context.playerId,
474
+ players: session.players,
475
+ frame: Object.freeze(frame),
476
+ version: basis.version
477
+ }),
478
+ connection: "ready"
479
+ });
480
+ finishBarrier();
481
+ },
482
+ result(value) {
483
+ if (closed) return;
484
+ const result = InteractionResultSchema.parse(value);
485
+ if (!pending || result.clientActionId !== pending.command.clientActionId || pending.accepted)
486
+ return;
487
+ pending.resolve(
488
+ immutableCopy(
489
+ result.accepted ? { accepted: true } : {
490
+ accepted: false,
491
+ errorCode: result.errorCode,
492
+ ...result.message === void 0 ? {} : { message: result.message }
493
+ }
494
+ )
495
+ );
496
+ if (!result.accepted) {
497
+ clearTimer();
498
+ pending = null;
499
+ publish({
500
+ snapshot: store.get().snapshot,
501
+ request: null,
502
+ connection: "ready",
503
+ failure: null
504
+ });
505
+ return;
506
+ }
507
+ pending.accepted = true;
508
+ recovered = false;
509
+ const state = store.get();
510
+ publish({
511
+ connection: state.connection === "recovering" ? "recovering" : "ready",
512
+ snapshot: state.snapshot,
513
+ failure: null,
514
+ request: { ...state.request, phase: "awaiting-frame" }
515
+ });
516
+ arm();
517
+ finishBarrier();
518
+ }
519
+ };
520
+ }
521
+ function asError(error) {
522
+ return error instanceof Error ? error : new Error(String(error));
523
+ }
524
+ function withCardImageUrls(frame, urls) {
525
+ if (urls === null || Object.keys(urls).length === 0) return frame;
526
+ const resolve = (encoded) => {
527
+ const card = CardImageViewSchema.parse(JSON.parse(encoded));
528
+ for (const key of ["frontImage", "backImage"]) {
529
+ const path = card[key];
530
+ const url = path === void 0 ? void 0 : urls[path];
531
+ if (url !== void 0) card[key] = url;
532
+ }
533
+ return JSON.stringify(card);
534
+ };
535
+ return {
536
+ ...frame,
537
+ zones: Object.fromEntries(
538
+ Object.entries(frame.zones).map(([zoneId, zone]) => [
539
+ zoneId,
540
+ {
541
+ ...zone,
542
+ cardViewsById: Object.fromEntries(
543
+ Object.entries(zone.cardViewsById).map(([cardId, encoded]) => [
544
+ cardId,
545
+ resolve(encoded)
546
+ ])
547
+ )
548
+ }
549
+ ])
550
+ )
551
+ };
552
+ }
553
+
554
+ export {
555
+ DREAMBOARD_PLUGIN_PROTOCOL,
556
+ DREAMBOARD_PLUGIN_PROTOCOL_VERSION,
557
+ BoardStaticProjectionSchema2 as BoardStaticProjectionSchema,
558
+ GameEventDetailSchema2 as GameEventDetailSchema,
559
+ SystemActionEventSchema2 as SystemActionEventSchema,
560
+ GameEventSchema2 as GameEventSchema,
561
+ SeatProjectionBundleSchema2 as SeatProjectionBundleSchema,
562
+ PluginPlayerSummarySchema,
563
+ PluginSessionDescriptorSchema,
564
+ ZoneHandlesSnapshotSchema,
565
+ SimultaneousPhaseSnapshotSchema,
566
+ GameplayBasisSchema,
567
+ GameOutcomeSchema2 as GameOutcomeSchema,
568
+ SeatFrameSchema,
569
+ PluginGameplayFrameSchema,
570
+ InteractionResultSchema,
571
+ SubmitInteractionCommandSchema,
572
+ CancelInteractionCommandSchema,
573
+ HostToPluginPayloadSchema,
574
+ PluginToHostPayloadSchema,
575
+ createPluginProtocolEnvelopeSchema,
576
+ HostToPluginEnvelopeSchema,
577
+ PluginToHostEnvelopeSchema,
578
+ parsePluginSessionDescriptor,
579
+ parsePluginGameplayFrame,
580
+ parseHostToPluginEnvelope,
581
+ parsePluginToHostEnvelope,
582
+ SourceSnapshotSchema,
583
+ staticSource,
584
+ createSourceLifecycle,
585
+ computePluginActionSetVersion,
586
+ digestPluginGameplayFrame,
587
+ digestPluginCommandRequest,
588
+ materializePluginGameplayFrame
589
+ };
590
+ //# sourceMappingURL=chunk-UG2Q4NLG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/protocol/protocol.ts","../src/shared/protocol/schema.ts","../src/headless/sources/static.ts","../src/shared/protocol/digest.ts","../src/shared/protocol/projection.ts","../src/headless/sources/lifecycle.ts"],"sourcesContent":["import type {\n GameplayBasis,\n InteractionDescriptor,\n PluginGameplayFrame,\n PluginSessionDescriptor,\n} from \"./frame.js\";\nimport type { RuntimeJson } from \"../runtime-json.js\";\n\nexport const DREAMBOARD_PLUGIN_PROTOCOL = \"dreamboard-plugin\" as const;\nexport const DREAMBOARD_PLUGIN_PROTOCOL_VERSION = 6 as const;\n\nexport type InteractionResult =\n | {\n readonly type: \"interaction.result\";\n readonly clientActionId: string;\n readonly accepted: true;\n }\n | {\n readonly type: \"interaction.result\";\n readonly clientActionId: string;\n readonly accepted: false;\n readonly errorCode: string;\n readonly message?: string;\n };\n\nexport interface SubmitInteractionCommand {\n readonly type: \"interaction.submit\";\n readonly clientActionId: string;\n readonly basis: GameplayBasis;\n readonly interactionId: string;\n readonly params: RuntimeJson;\n}\n\nexport interface CancelInteractionCommand {\n readonly type: \"interaction.cancel\";\n readonly clientActionId: string;\n readonly basis: GameplayBasis;\n readonly interactionId: string;\n}\n\nexport type HostToPluginPayload =\n | {\n readonly type: \"runtime.init\";\n readonly session: PluginSessionDescriptor;\n }\n | {\n readonly type: \"gameplay.frame\";\n readonly frame: PluginGameplayFrame;\n }\n | InteractionResult;\n\nexport type PluginToHostPayload =\n | { readonly type: \"runtime.ready\" }\n | { readonly type: \"runtime.resume\" }\n | {\n readonly type: \"runtime.ack\";\n /** Echoes the host envelope sequence. It is delivery order only. */\n readonly sequence: number;\n readonly clientReceivedAtMs?: number;\n readonly clientRenderedAtMs?: number;\n }\n | SubmitInteractionCommand\n | CancelInteractionCommand\n | {\n readonly type: \"runtime.error\";\n readonly message: string;\n readonly code?: string;\n };\n\nexport interface PluginProtocolEnvelope<Payload> {\n readonly protocol: typeof DREAMBOARD_PLUGIN_PROTOCOL;\n readonly version: typeof DREAMBOARD_PLUGIN_PROTOCOL_VERSION;\n readonly channelId: string;\n /** Delivery order only. It is not a game revision. */\n readonly sequence: number;\n readonly payload: Payload;\n}\n\nexport type HostToPluginEnvelope = PluginProtocolEnvelope<HostToPluginPayload>;\nexport type PluginToHostEnvelope = PluginProtocolEnvelope<PluginToHostPayload>;\n\nexport type ActionSetVersionInput = {\n readonly version: number;\n readonly availableInteractions: readonly InteractionDescriptor[];\n};\n","import * as ReducerWireZod from \"../runtime-schema\";\nimport { z } from \"zod\";\nimport {\n DREAMBOARD_PLUGIN_PROTOCOL,\n DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n} from \"./protocol.js\";\nimport { RuntimeJsonSchema } from \"../runtime-json.js\";\nimport type {\n GameOutcome,\n GameplayBasis,\n PluginGameplayFrame,\n PluginSessionDescriptor,\n ZoneHandlesSnapshot,\n} from \"./frame.js\";\nimport type {\n HostToPluginPayload,\n InteractionResult,\n PluginProtocolEnvelope,\n PluginToHostPayload,\n} from \"./protocol.js\";\n\nexport const BoardStaticProjectionSchema =\n ReducerWireZod.BoardStaticProjectionSchema;\nexport const GameEventDetailSchema = ReducerWireZod.GameEventDetailSchema;\nexport const SystemActionEventSchema = ReducerWireZod.SystemActionEventSchema;\nexport const GameEventSchema = ReducerWireZod.GameEventSchema;\nexport const SeatProjectionBundleSchema =\n ReducerWireZod.SeatProjectionBundleSchema;\n\nexport const PlayerIdSchema = z.string().min(1);\n\nexport const PluginPlayerSummarySchema = z\n .object({\n playerId: PlayerIdSchema,\n displayName: z.string(),\n color: z.string().optional(),\n })\n .strict();\n\nexport const PluginSessionDescriptorSchema = z\n .object({\n sessionId: z.string().min(1),\n players: z.array(PluginPlayerSummarySchema),\n assets: z.record(z.string(), z.instanceof(Blob)).optional(),\n })\n .strict() satisfies z.ZodType<PluginSessionDescriptor>;\n\nexport {\n InteractionCommitPolicySchema,\n InputSelectionSchema,\n InputDomainSchema,\n InteractionChoiceOptionSchema,\n InteractionInputDescriptorSchema,\n InteractionAvailabilitySchema,\n InteractionDescriptorSchema,\n} from \"../interaction-schema.js\";\nimport { InteractionDescriptorSchema } from \"../interaction-schema.js\";\n\nexport const ZoneHandlesSnapshotSchema = z\n .object({\n cardIds: z.array(z.string()),\n cardViewsById: z.record(z.string(), z.string()),\n playableByCardId: z.record(\n z.string(),\n z.array(InteractionDescriptorSchema),\n ),\n })\n .strict() satisfies z.ZodType<ZoneHandlesSnapshot>;\n\nexport const SimultaneousPhaseSnapshotSchema =\n ReducerWireZod.SimultaneousPhaseProjectionSchema;\n\nexport const GameplayBasisSchema = z\n .object({\n version: z.number().int().nonnegative(),\n actionSetVersion: z.string().min(1),\n perspectivePlayerId: PlayerIdSchema,\n })\n .strict() satisfies z.ZodType<GameplayBasis>;\n\nexport const GameOutcomeSchema =\n ReducerWireZod.GameOutcomeSchema satisfies z.ZodType<GameOutcome>;\n\nexport const SeatFrameSchema = z\n .object({\n events: z.array(GameEventSchema).max(32),\n view: z.record(z.string(), RuntimeJsonSchema).nullable(),\n flow: z\n .object({\n currentPhase: z.string().nullable(),\n activePlayers: z.array(PlayerIdSchema),\n simultaneousPhase: SimultaneousPhaseSnapshotSchema.nullable(),\n })\n .strict(),\n availableInteractions: z.array(InteractionDescriptorSchema),\n zones: z.record(z.string(), ZoneHandlesSnapshotSchema),\n })\n .strict();\n\nexport const PluginGameplayFrameSchema = SeatFrameSchema.extend({\n basis: GameplayBasisSchema,\n}) satisfies z.ZodType<PluginGameplayFrame>;\n\nexport const InteractionResultSchema = z.discriminatedUnion(\"accepted\", [\n z\n .object({\n type: z.literal(\"interaction.result\"),\n clientActionId: z.string().min(1),\n accepted: z.literal(true),\n })\n .strict(),\n z\n .object({\n type: z.literal(\"interaction.result\"),\n clientActionId: z.string().min(1),\n accepted: z.literal(false),\n errorCode: z.string().min(1),\n message: z.string().optional(),\n })\n .strict(),\n]) satisfies z.ZodType<InteractionResult>;\n\nexport const SubmitInteractionCommandSchema = z\n .object({\n type: z.literal(\"interaction.submit\"),\n clientActionId: z.string().min(1),\n basis: GameplayBasisSchema,\n interactionId: z.string().min(1),\n params: RuntimeJsonSchema,\n })\n .strict();\n\nexport const CancelInteractionCommandSchema =\n SubmitInteractionCommandSchema.omit({ params: true })\n .extend({ type: z.literal(\"interaction.cancel\") })\n .strict();\n\nexport const HostToPluginPayloadSchema = z.discriminatedUnion(\"type\", [\n z\n .object({\n type: z.literal(\"runtime.init\"),\n session: PluginSessionDescriptorSchema,\n })\n .strict(),\n z\n .object({\n type: z.literal(\"gameplay.frame\"),\n frame: PluginGameplayFrameSchema,\n })\n .strict(),\n InteractionResultSchema,\n]) satisfies z.ZodType<HostToPluginPayload>;\n\nexport const PluginToHostPayloadSchema = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"runtime.ready\") }).strict(),\n z.object({ type: z.literal(\"runtime.resume\") }).strict(),\n z\n .object({\n type: z.literal(\"runtime.ack\"),\n sequence: z.number().int().nonnegative(),\n clientReceivedAtMs: z.number().finite().optional(),\n clientRenderedAtMs: z.number().finite().optional(),\n })\n .strict(),\n SubmitInteractionCommandSchema,\n CancelInteractionCommandSchema,\n z\n .object({\n type: z.literal(\"runtime.error\"),\n message: z.string(),\n code: z.string().optional(),\n })\n .strict(),\n]) satisfies z.ZodType<PluginToHostPayload>;\n\nexport function createPluginProtocolEnvelopeSchema<Payload>(\n payloadSchema: z.ZodType<Payload>,\n): z.ZodType<PluginProtocolEnvelope<Payload>> {\n return z\n .object({\n protocol: z.literal(DREAMBOARD_PLUGIN_PROTOCOL),\n version: z.literal(DREAMBOARD_PLUGIN_PROTOCOL_VERSION),\n channelId: z.string().min(1),\n sequence: z.number().int().nonnegative(),\n payload: payloadSchema,\n })\n .strict();\n}\n\nexport const HostToPluginEnvelopeSchema = createPluginProtocolEnvelopeSchema(\n HostToPluginPayloadSchema,\n);\n\nexport const PluginToHostEnvelopeSchema = createPluginProtocolEnvelopeSchema(\n PluginToHostPayloadSchema,\n);\n\nexport function parsePluginSessionDescriptor(\n value: unknown,\n): PluginSessionDescriptor {\n return PluginSessionDescriptorSchema.parse(value);\n}\n\nexport function parsePluginGameplayFrame(value: unknown): PluginGameplayFrame {\n return PluginGameplayFrameSchema.parse(value);\n}\n\nexport function parseHostToPluginEnvelope(\n value: unknown,\n): PluginProtocolEnvelope<HostToPluginPayload> {\n return HostToPluginEnvelopeSchema.parse(value);\n}\n\nexport function parsePluginToHostEnvelope(\n value: unknown,\n): PluginProtocolEnvelope<PluginToHostPayload> {\n return PluginToHostEnvelopeSchema.parse(value);\n}\n","import { createStore } from \"@tanstack/store\";\nimport { z } from \"zod\";\nimport {\n SeatFrameSchema,\n PluginPlayerSummarySchema,\n} from \"../../shared/protocol/schema.js\";\nimport { immutableCopy } from \"./immutable.js\";\nimport type { GameSource, SourceSnapshot, SourceState } from \"./types.js\";\n\nexport const SourceSnapshotSchema = z\n .object({\n me: z.string().min(1),\n players: z.array(PluginPlayerSummarySchema),\n frame: SeatFrameSchema,\n version: z.number().int().nonnegative(),\n })\n .strict();\n\n/** A read-only fixture source accepts the public seat snapshot, never wire basis. */\nexport function staticSource(input: SourceSnapshot): GameSource {\n const snapshot = immutableCopy(SourceSnapshotSchema.parse(input));\n if (!snapshot.players.some((player) => player.playerId === snapshot.me))\n throw new Error(\"Gameplay seat is absent from session.\");\n const store = createStore<SourceState>(\n Object.freeze({\n snapshot,\n connection: \"ready\",\n request: null,\n failure: null,\n }),\n );\n return {\n store: {\n get: () => store.get(),\n subscribe: (listener) => store.subscribe(listener),\n },\n dispose() {\n store.setState((state) =>\n Object.freeze({\n snapshot: state.snapshot,\n connection: \"closed\",\n request: null,\n failure: null,\n }),\n );\n },\n };\n}\n","import type { PluginGameplayFrame } from \"./frame.js\";\nimport {\n type ActionSetVersionInput,\n type SubmitInteractionCommand,\n type CancelInteractionCommand,\n} from \"./protocol.js\";\nimport {\n canonicalizePluginRuntimeJson,\n digestPluginRuntimeJson,\n encodeCanonicalPluginRuntimeJson,\n} from \"./json.js\";\n\nexport {\n canonicalizePluginRuntimeJson,\n digestPluginRuntimeJson,\n encodeCanonicalPluginRuntimeJson,\n};\n\nexport function computePluginActionSetVersion(\n input: ActionSetVersionInput,\n): string {\n return digestPluginRuntimeJson({\n digestVersion: \"plugin-action-set@5\",\n version: input.version,\n availableInteractions: input.availableInteractions,\n });\n}\n\nexport function digestPluginGameplayFrame(frame: PluginGameplayFrame): string {\n return digestPluginRuntimeJson({\n digestVersion: \"plugin-gameplay-frame@5\",\n frame,\n });\n}\n\nexport function digestPluginCommandRequest(\n command: SubmitInteractionCommand | CancelInteractionCommand,\n): string {\n return digestPluginRuntimeJson({\n digestVersion: \"plugin-command-request@5\",\n command,\n });\n}\n","import { canonicalizePluginRuntimeJson } from \"./json\";\nimport {\n BoardStaticProjectionSchema,\n PluginGameplayFrameSchema,\n SeatProjectionBundleSchema,\n} from \"./schema.js\";\nimport type {\n InteractionDescriptor,\n PlayerId,\n PluginGameplayFrame,\n ReducerBoardStaticProjection,\n ReducerSeatProjectionBundle,\n ZoneHandlesSnapshot,\n} from \"./frame.js\";\nimport type { RuntimeJson } from \"../runtime-json.js\";\n\nexport interface MaterializePluginGameplayFrameInput {\n readonly currentPhase: string | null;\n readonly activePlayers: readonly PlayerId[];\n readonly dynamicProjection: ReducerSeatProjectionBundle;\n readonly staticProjection?: ReducerBoardStaticProjection | null;\n readonly perspectivePlayerId: PlayerId;\n\n readonly version: number;\n readonly actionSetVersion: string;\n}\n\nexport function materializePluginGameplayFrame(\n input: MaterializePluginGameplayFrameInput,\n): PluginGameplayFrame {\n const dynamicProjection = SeatProjectionBundleSchema.parse(\n canonicalizePluginRuntimeJson(input.dynamicProjection),\n );\n const staticProjection =\n input.staticProjection == null\n ? null\n : BoardStaticProjectionSchema.parse(\n canonicalizePluginRuntimeJson(input.staticProjection),\n );\n\n const registry = dynamicProjection.interactionsByRef ?? {};\n const seat = dynamicProjection.seats[input.perspectivePlayerId] ?? null;\n\n const availableInteractions =\n seat == null\n ? []\n : hydrateInteractionRefs(\n registry,\n seat.availableInteractionRefs ?? [],\n \"availableInteractionRefs\",\n );\n const zones =\n seat?.zones == null ? {} : hydrateZones(registry, seat.zones, \"zones\");\n\n const frame = {\n events: dynamicProjection.events,\n basis: {\n version: input.version,\n actionSetVersion: input.actionSetVersion,\n perspectivePlayerId: input.perspectivePlayerId,\n },\n view: materializeView(staticProjection, seat?.view),\n flow: {\n currentPhase: input.currentPhase,\n activePlayers: [...input.activePlayers],\n simultaneousPhase: dynamicProjection.simultaneousPhase ?? null,\n },\n availableInteractions,\n zones,\n } satisfies PluginGameplayFrame;\n\n return PluginGameplayFrameSchema.parse(frame);\n}\n\nfunction materializeView(\n staticProjection: ReducerBoardStaticProjection | null,\n seatView: unknown,\n): RuntimeJson | null {\n const parts = [staticProjection?.view, seatView].filter(\n (part) => part !== undefined && part !== null,\n );\n if (parts.length === 0) return null;\n // Admitting schemas guarantee records and reject authored `boards` fields.\n return Object.assign({}, ...parts) as Record<string, RuntimeJson>;\n}\n\nfunction hydrateZones(\n registry: Readonly<Record<string, InteractionDescriptor>>,\n value: NonNullable<ReducerSeatProjectionBundle[\"seats\"][string][\"zones\"]>,\n path: string,\n): Record<string, ZoneHandlesSnapshot> {\n return Object.fromEntries(\n Object.entries(value).map(([zoneId, zone]) => [\n zoneId,\n {\n cardIds: zone.cardIds,\n cardViewsById: zone.cardViewsById,\n playableByCardId: Object.fromEntries(\n Object.entries(zone.playableByCardId).map(([cardId, refs]) => [\n cardId,\n hydrateInteractionRefs(\n registry,\n refs,\n `${path}.${zoneId}.playableByCardId.${cardId}`,\n ),\n ]),\n ),\n },\n ]),\n );\n}\n\nfunction hydrateInteractionRefs(\n registry: Readonly<Record<string, InteractionDescriptor>>,\n value: readonly string[],\n path: string,\n): InteractionDescriptor[] {\n return value.map((ref, index) => {\n const descriptor = registry[ref];\n if (!descriptor) {\n throw new Error(\n `Seat projection ${path}[${index}] references '${ref}', which is missing from interactionsByRef.`,\n );\n }\n return descriptor;\n });\n}\n","import { createStore } from \"@tanstack/store\";\nimport { z } from \"zod\";\nimport type { ViewCard } from \"../../shared/domain/cards.js\";\nimport {\n PluginGameplayFrameSchema,\n PluginSessionDescriptorSchema,\n InteractionResultSchema,\n PluginToHostPayloadSchema,\n} from \"../../shared/protocol/schema.js\";\nimport type {\n GameplayBasis,\n PluginGameplayFrame,\n PluginSessionDescriptor,\n} from \"../../shared/protocol/frame.js\";\nimport { immutableCopy } from \"./immutable.js\";\nimport type {\n CommandSource,\n SourceCommand,\n SourceContext,\n SourceState,\n SubmitResult,\n} from \"./types.js\";\n\ninterface Pending {\n readonly command: SourceCommand;\n readonly resolve: (result: SubmitResult) => void;\n readonly reject: (error: Error) => void;\n accepted: boolean;\n}\n\nconst CardImageViewSchema = z.looseObject({\n frontImage: z.string().optional(),\n backImage: z.string().optional(),\n}) satisfies z.ZodType<Pick<ViewCard, \"frontImage\" | \"backImage\">>;\n\n/** Adapter-private lifecycle. Transport callbacks must belong to this lifetime. */\nexport function createSourceLifecycle(options: {\n context?: SourceContext;\n send(command: SourceCommand): void;\n recover(): void;\n close(): void;\n timeoutMs?: number;\n}) {\n let context = options.context ? immutableCopy(options.context) : null;\n const store = createStore<SourceState>(\n Object.freeze({\n snapshot: null,\n connection: \"connecting\",\n request: null,\n failure: null,\n }),\n );\n let session: Omit<PluginSessionDescriptor, \"assets\"> | null = null;\n let assetUrls: Readonly<Record<string, string>> | null = null;\n let basis: GameplayBasis | null = null;\n let pending: Pending | null = null;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let recovered = false;\n let closed = false;\n const clearTimer = () => {\n clearTimeout(timer);\n timer = undefined;\n };\n const publish = (state: SourceState) => {\n if (state.request) Object.freeze(state.request);\n store.setState(() => Object.freeze(state));\n };\n const recovering = () => {\n if (closed) return;\n publish({ ...store.get(), connection: \"recovering\", failure: null });\n };\n const close = (failure: Error | null) => {\n if (closed) return;\n closed = true;\n clearTimer();\n for (const url of Object.values(assetUrls ?? {})) URL.revokeObjectURL(url);\n pending?.reject(failure ?? new Error(\"Gameplay source disposed.\"));\n pending = null;\n options.close();\n const snapshot = store.get().snapshot;\n publish(\n failure\n ? {\n connection: \"failed\",\n snapshot,\n request: null,\n failure: Object.freeze(failure),\n }\n : { connection: \"closed\", snapshot, request: null, failure: null },\n );\n };\n const fail = (error: Error) => close(error);\n const arm = () => {\n clearTimer();\n timer = setTimeout(() => {\n if (recovered) {\n fail(new Error(\"Gameplay source recovery timed out.\"));\n return;\n }\n recovered = true;\n recovering();\n try {\n options.recover();\n if (pending && !pending.accepted) options.send(pending.command);\n arm();\n } catch (error) {\n fail(asError(error));\n }\n }, options.timeoutMs ?? 10_000);\n };\n const finishBarrier = () => {\n if (!pending?.accepted) return;\n const frame = store.get().snapshot;\n if (!frame || frame.version <= pending.command.basis.version) return;\n clearTimer();\n pending = null;\n publish({\n snapshot: frame,\n request: null,\n connection: \"ready\",\n failure: null,\n });\n };\n const start = async (\n operation: \"submit\" | \"cancel\",\n interactionId: string,\n params?: unknown,\n ) => {\n const state = store.get();\n if (closed || state.connection !== \"ready\" || !basis)\n return Promise.reject(new Error(\"Gameplay source is not open.\"));\n if (pending)\n return Promise.reject(\n new Error(\"A gameplay interaction is already pending.\"),\n );\n const command = immutableCopy(\n PluginToHostPayloadSchema.parse({\n type:\n operation === \"cancel\" ? \"interaction.cancel\" : \"interaction.submit\",\n clientActionId: crypto.randomUUID(),\n basis,\n interactionId,\n ...(operation === \"cancel\" ? {} : { params }),\n }) as SourceCommand,\n );\n recovered = false;\n const promise = new Promise<SubmitResult>((resolve, reject) => {\n pending = { command, resolve, reject, accepted: false };\n });\n publish({\n ...state,\n request: {\n interactionId,\n operation,\n phase: \"awaiting-result\",\n },\n });\n arm();\n try {\n options.send(command);\n } catch (error) {\n fail(asError(error));\n }\n return promise;\n };\n const source: CommandSource = {\n store: {\n get: () => store.get(),\n subscribe: (listener) => store.subscribe(listener),\n },\n submit: (interactionId, params) => start(\"submit\", interactionId, params),\n cancel: (interactionId) => start(\"cancel\", interactionId),\n dispose: () => close(null),\n };\n return {\n source,\n retry() {\n if (closed || !pending) return;\n try {\n if (pending.accepted) options.recover();\n else options.send(pending.command);\n } catch (error) {\n fail(asError(error));\n }\n },\n fail,\n recovering,\n session(value: unknown) {\n if (closed) return;\n const { assets, ...parsed } = PluginSessionDescriptorSchema.parse(value);\n if (\n (context?.sessionId ?? session?.sessionId) &&\n parsed.sessionId !== (context?.sessionId ?? session?.sessionId)\n ) {\n fail(new Error(\"Gameplay session changed.\"));\n return;\n }\n if (\n context &&\n !parsed.players.some((player) => player.playerId === context!.playerId)\n ) {\n fail(new Error(\"Gameplay seat is absent from session.\"));\n return;\n }\n session = immutableCopy(parsed);\n // Hosts repeat initialization until ready; the first delivery wins.\n assetUrls ??= Object.fromEntries(\n Object.entries(assets ?? {}).map(([path, blob]) => [\n path,\n URL.createObjectURL(blob),\n ]),\n );\n },\n frame(value: unknown) {\n if (closed) return;\n const parsed = PluginGameplayFrameSchema.parse(value);\n if (!session) {\n fail(new Error(\"Gameplay frame arrived before session metadata.\"));\n return;\n }\n context ??= {\n sessionId: session.sessionId,\n playerId: parsed.basis.perspectivePlayerId,\n };\n if (parsed.basis.perspectivePlayerId !== context.playerId) {\n fail(new Error(\"Gameplay perspective changed.\"));\n return;\n }\n if (\n !session.players.some((player) => player.playerId === context!.playerId)\n ) {\n fail(new Error(\"Gameplay seat is absent from session.\"));\n return;\n }\n if (basis && parsed.basis.version < basis.version) return;\n const { basis: nextBasis, ...frame } = immutableCopy(\n withCardImageUrls(parsed, assetUrls),\n );\n basis = nextBasis;\n publish({\n failure: null,\n request: store.get().request,\n snapshot: Object.freeze({\n me: context.playerId,\n players: session.players,\n frame: Object.freeze(frame),\n version: basis.version,\n }),\n connection: \"ready\",\n });\n finishBarrier();\n },\n result(value: unknown) {\n if (closed) return;\n const result = InteractionResultSchema.parse(value);\n if (\n !pending ||\n result.clientActionId !== pending.command.clientActionId ||\n pending.accepted\n )\n return;\n pending.resolve(\n immutableCopy(\n result.accepted\n ? { accepted: true }\n : {\n accepted: false,\n errorCode: result.errorCode,\n ...(result.message === undefined\n ? {}\n : { message: result.message }),\n },\n ),\n );\n if (!result.accepted) {\n clearTimer();\n pending = null;\n publish({\n snapshot: store.get().snapshot!,\n request: null,\n connection: \"ready\",\n failure: null,\n });\n return;\n }\n pending.accepted = true;\n recovered = false;\n const state = store.get();\n // A pending command was submitted from ready, so its snapshot exists.\n publish({\n connection: state.connection === \"recovering\" ? \"recovering\" : \"ready\",\n snapshot: state.snapshot!,\n failure: null,\n request: { ...state.request!, phase: \"awaiting-frame\" },\n });\n arm();\n finishBarrier();\n },\n };\n}\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\n/** Replaces card image paths in encoded card views with delivered URLs. */\nfunction withCardImageUrls(\n frame: PluginGameplayFrame,\n urls: Readonly<Record<string, string>> | null,\n): PluginGameplayFrame {\n if (urls === null || Object.keys(urls).length === 0) return frame;\n const resolve = (encoded: string) => {\n const card = CardImageViewSchema.parse(JSON.parse(encoded) as unknown);\n for (const key of [\"frontImage\", \"backImage\"] as const) {\n const path = card[key];\n const url = path === undefined ? undefined : urls[path];\n if (url !== undefined) card[key] = url;\n }\n return JSON.stringify(card);\n };\n return {\n ...frame,\n zones: Object.fromEntries(\n Object.entries(frame.zones).map(([zoneId, zone]) => [\n zoneId,\n {\n ...zone,\n cardViewsById: Object.fromEntries(\n Object.entries(zone.cardViewsById).map(([cardId, encoded]) => [\n cardId,\n resolve(encoded),\n ]),\n ),\n },\n ]),\n ),\n };\n}\n"],"mappings":"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","names":["BoardStaticProjectionSchema","GameEventDetailSchema","SystemActionEventSchema","GameEventSchema","SeatProjectionBundleSchema","GameOutcomeSchema","z","z","SeatProjectionBundleSchema","BoardStaticProjectionSchema","createStore","z","z","createStore"]}