@dreamboard-games/sdk 0.5.0-alpha.2 → 0.5.0-alpha.21

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 (150) hide show
  1. package/README.md +462 -53
  2. package/dist/board-element-CqtxU5VZ.d.ts +13 -0
  3. package/dist/chunk-3RFGPBES.js +1792 -0
  4. package/dist/chunk-3RFGPBES.js.map +1 -0
  5. package/dist/chunk-CZRPUWCT.js +1602 -0
  6. package/dist/chunk-CZRPUWCT.js.map +1 -0
  7. package/dist/chunk-DMSXVMYY.js +7199 -0
  8. package/dist/chunk-DMSXVMYY.js.map +1 -0
  9. package/dist/chunk-U6R7FAH4.js +630 -0
  10. package/dist/chunk-U6R7FAH4.js.map +1 -0
  11. package/dist/chunk-YT3RPO5J.js +635 -0
  12. package/dist/chunk-YT3RPO5J.js.map +1 -0
  13. package/dist/diagnostics-ZAPEBlJP.d.ts +64 -0
  14. package/dist/extract-CwJWDrSD.d.ts +6850 -0
  15. package/dist/index.d.ts +5177 -1
  16. package/dist/index.js +1990 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/react.d.ts +158 -0
  19. package/dist/react.js +1119 -0
  20. package/dist/react.js.map +1 -0
  21. package/dist/reducer.d.ts +1028 -97
  22. package/dist/reducer.js +4892 -125
  23. package/dist/reducer.js.map +1 -1
  24. package/dist/shortcuts-B_RrufOM.d.ts +822 -0
  25. package/dist/testing.d.ts +529 -569
  26. package/dist/testing.js +2588 -934
  27. package/dist/testing.js.map +1 -1
  28. package/dist/types-BxXRINRF.d.ts +118 -0
  29. package/package.json +39 -144
  30. package/dist/HandView-Bi2lxzQP.d.ts +0 -79
  31. package/dist/ResourceCounter-BFxJknqp.d.ts +0 -98
  32. package/dist/ThemeProvider-CElaL2ik.d.ts +0 -99
  33. package/dist/attributes-DbvyMbXw.d.ts +0 -68
  34. package/dist/browser-interaction.d.ts +0 -910
  35. package/dist/browser-interaction.js +0 -119
  36. package/dist/browser-interaction.js.map +0 -1
  37. package/dist/chunk-32PFKDV7.js +0 -11705
  38. package/dist/chunk-32PFKDV7.js.map +0 -1
  39. package/dist/chunk-3BAD4VC2.js +0 -263
  40. package/dist/chunk-3BAD4VC2.js.map +0 -1
  41. package/dist/chunk-3SKDNDPG.js +0 -104
  42. package/dist/chunk-3SKDNDPG.js.map +0 -1
  43. package/dist/chunk-5YV2WHJ4.js +0 -25
  44. package/dist/chunk-5YV2WHJ4.js.map +0 -1
  45. package/dist/chunk-ANRB4XKA.js +0 -90
  46. package/dist/chunk-ANRB4XKA.js.map +0 -1
  47. package/dist/chunk-BI4G3PM2.js +0 -1864
  48. package/dist/chunk-BI4G3PM2.js.map +0 -1
  49. package/dist/chunk-EVCLTY4Q.js +0 -935
  50. package/dist/chunk-EVCLTY4Q.js.map +0 -1
  51. package/dist/chunk-GDPKTBUR.js +0 -564
  52. package/dist/chunk-GDPKTBUR.js.map +0 -1
  53. package/dist/chunk-H6VDGFL5.js +0 -2903
  54. package/dist/chunk-H6VDGFL5.js.map +0 -1
  55. package/dist/chunk-LR3ZTWQF.js +0 -5960
  56. package/dist/chunk-LR3ZTWQF.js.map +0 -1
  57. package/dist/chunk-PF7L4BMG.js +0 -117
  58. package/dist/chunk-PF7L4BMG.js.map +0 -1
  59. package/dist/chunk-PN5O6GG2.js +0 -32
  60. package/dist/chunk-PN5O6GG2.js.map +0 -1
  61. package/dist/chunk-PZ5AY32C.js +0 -10
  62. package/dist/chunk-PZ5AY32C.js.map +0 -1
  63. package/dist/chunk-S2JEDVWH.js +0 -7165
  64. package/dist/chunk-S2JEDVWH.js.map +0 -1
  65. package/dist/chunk-T3ZKNUZ7.js +0 -1
  66. package/dist/chunk-T3ZKNUZ7.js.map +0 -1
  67. package/dist/chunk-UGH54WZ2.js +0 -223
  68. package/dist/chunk-UGH54WZ2.js.map +0 -1
  69. package/dist/chunk-VCDWP5VL.js +0 -746
  70. package/dist/chunk-VCDWP5VL.js.map +0 -1
  71. package/dist/chunk-VDXOF4FW.js +0 -69
  72. package/dist/chunk-VDXOF4FW.js.map +0 -1
  73. package/dist/chunk-WHR5UW3F.js +0 -1988
  74. package/dist/chunk-WHR5UW3F.js.map +0 -1
  75. package/dist/chunk-Y75CFE77.js +0 -17
  76. package/dist/chunk-Y75CFE77.js.map +0 -1
  77. package/dist/chunk-Z7QCREWI.js +0 -3435
  78. package/dist/chunk-Z7QCREWI.js.map +0 -1
  79. package/dist/chunk-ZZGN2ATS.js +0 -1941
  80. package/dist/chunk-ZZGN2ATS.js.map +0 -1
  81. package/dist/components-gAbIz7hK.d.ts +0 -1284
  82. package/dist/definitions-BgmV_GhC.d.ts +0 -300
  83. package/dist/diagnostics-DIi3ina7.d.ts +0 -50
  84. package/dist/digest.d.ts +0 -8
  85. package/dist/game-CsZScpcn.d.ts +0 -763
  86. package/dist/hex-board-view-aKkblDp6.d.ts +0 -1228
  87. package/dist/index-CcT9Q7N7.d.ts +0 -193
  88. package/dist/index.d-DjzoK7zn.d.ts +0 -2101
  89. package/dist/package-set.d.ts +0 -13
  90. package/dist/package-set.js +0 -12
  91. package/dist/package-set.js.map +0 -1
  92. package/dist/player-state-Cqpyeql0.d.ts +0 -371
  93. package/dist/plugin-runtime-contract.d.ts +0 -17
  94. package/dist/plugin-runtime-contract.js +0 -92
  95. package/dist/plugin-runtime-contract.js.map +0 -1
  96. package/dist/primitive-props-BNHDkgd7.d.ts +0 -16
  97. package/dist/protocol-dYgafTYY.d.ts +0 -314
  98. package/dist/reducer/advanced.d.ts +0 -82
  99. package/dist/reducer/advanced.js +0 -51
  100. package/dist/reducer/advanced.js.map +0 -1
  101. package/dist/reducer-contract.d.ts +0 -11
  102. package/dist/reducer-contract.js +0 -16
  103. package/dist/reducer-contract.js.map +0 -1
  104. package/dist/reference-games/index.d.ts +0 -31
  105. package/dist/reference-games/index.js +0 -48
  106. package/dist/reference-games/index.js.map +0 -1
  107. package/dist/runtime/primitives.d.ts +0 -250
  108. package/dist/runtime/primitives.js +0 -189
  109. package/dist/runtime/primitives.js.map +0 -1
  110. package/dist/runtime/runtime-api.d.ts +0 -2
  111. package/dist/runtime/runtime-api.js +0 -1
  112. package/dist/runtime/runtime-api.js.map +0 -1
  113. package/dist/runtime/workspace-contract.d.ts +0 -392
  114. package/dist/runtime/workspace-contract.js +0 -28
  115. package/dist/runtime/workspace-contract.js.map +0 -1
  116. package/dist/runtime-RJ5orDJU.d.ts +0 -1699
  117. package/dist/runtime-api-Bz5pwNU_.d.ts +0 -296
  118. package/dist/runtime-json-CQ9QbLZ5.d.ts +0 -5
  119. package/dist/runtime.d.ts +0 -83
  120. package/dist/runtime.js +0 -242
  121. package/dist/runtime.js.map +0 -1
  122. package/dist/schema.d.ts +0 -379
  123. package/dist/stale-contract-artifact-error-XLaweZtF.d.ts +0 -18
  124. package/dist/testing-compiler.d.ts +0 -37
  125. package/dist/testing-compiler.js +0 -272
  126. package/dist/testing-compiler.js.map +0 -1
  127. package/dist/testing-runtime.d.ts +0 -119
  128. package/dist/testing-runtime.js +0 -212
  129. package/dist/testing-runtime.js.map +0 -1
  130. package/dist/types-DJj5MJkl.d.ts +0 -256
  131. package/dist/types-DR7DoB1x.d.ts +0 -28
  132. package/dist/types-JWCYHmu7.d.ts +0 -122
  133. package/dist/types.d.ts +0 -1958
  134. package/dist/types.js +0 -14
  135. package/dist/types.js.map +0 -1
  136. package/dist/ui/components.d.ts +0 -17
  137. package/dist/ui/components.js +0 -216
  138. package/dist/ui/components.js.map +0 -1
  139. package/dist/ui/defaults.d.ts +0 -19
  140. package/dist/ui/defaults.js +0 -104
  141. package/dist/ui/defaults.js.map +0 -1
  142. package/dist/ui/player-state.d.ts +0 -2
  143. package/dist/ui/player-state.js +0 -1
  144. package/dist/ui/player-state.js.map +0 -1
  145. package/dist/ui/plugin-styles.css +0 -2
  146. package/dist/ui-contract-GTUPkf8z.d.ts +0 -1168
  147. package/dist/ui.d.ts +0 -317
  148. package/dist/ui.js +0 -277
  149. package/dist/ui.js.map +0 -1
  150. package/dist/views-BpuWcOyN.d.ts +0 -1641
@@ -0,0 +1,635 @@
1
+ import {
2
+ GameOutcomeSchema,
3
+ InteractionDescriptorSchema,
4
+ ProjectedGameEventDetailSchema,
5
+ ProjectedGameEventSchema,
6
+ SeatProjectionBundleSchema,
7
+ SimultaneousPhaseProjectionSchema,
8
+ SystemActionEventSchema,
9
+ ViewCardSchema
10
+ } from "./chunk-U6R7FAH4.js";
11
+ import {
12
+ BoardProjectionSchema,
13
+ PlayerIdSchema,
14
+ ProjectedTileSchema,
15
+ RuntimeJsonSchema,
16
+ canonicalizePluginRuntimeJson,
17
+ digestPluginRuntimeJson,
18
+ immutableCopy
19
+ } from "./chunk-CZRPUWCT.js";
20
+
21
+ // src/shared/protocol/protocol.ts
22
+ var DREAMBOARD_PLUGIN_PROTOCOL = "dreamboard-plugin";
23
+ var DREAMBOARD_PLUGIN_PROTOCOL_VERSION = 10;
24
+
25
+ // src/shared/protocol/schema.ts
26
+ import * as z from "zod";
27
+ var GameEventDetailSchema = ProjectedGameEventDetailSchema;
28
+ var SystemActionEventSchema2 = SystemActionEventSchema;
29
+ var GameEventSchema = ProjectedGameEventSchema;
30
+ var SeatProjectionBundleSchema2 = SeatProjectionBundleSchema;
31
+ var PluginPlayerSummarySchema = z.object({
32
+ playerId: PlayerIdSchema,
33
+ displayName: z.string(),
34
+ color: z.string().optional()
35
+ }).strict();
36
+ var PluginSessionDescriptorSchema = z.object({
37
+ sessionId: z.string().min(1),
38
+ players: z.array(PluginPlayerSummarySchema),
39
+ assets: z.record(z.string(), z.instanceof(Blob)).optional()
40
+ }).strict();
41
+ var ZoneHandlesSnapshotSchema = z.object({
42
+ tiles: z.array(ProjectedTileSchema),
43
+ cardIds: z.array(z.string()),
44
+ cardViewsById: z.record(z.string(), ViewCardSchema),
45
+ cardBacksById: z.record(z.string(), z.string()),
46
+ playableByCardId: z.record(
47
+ z.string(),
48
+ z.array(InteractionDescriptorSchema)
49
+ )
50
+ }).strict();
51
+ var SimultaneousPhaseSnapshotSchema = SimultaneousPhaseProjectionSchema;
52
+ var GameplayBasisSchema = z.object({
53
+ sessionId: z.string().min(1),
54
+ version: z.number().int().nonnegative(),
55
+ actionSetVersion: z.string().min(1),
56
+ perspectivePlayerId: PlayerIdSchema
57
+ }).strict();
58
+ var GameOutcomeSchema2 = GameOutcomeSchema;
59
+ var ProjectedViewSchema = z.record(z.string(), RuntimeJsonSchema).superRefine((view, context) => {
60
+ if (!Object.hasOwn(view, "boards")) return;
61
+ const boards = BoardProjectionSchema.safeParse(view.boards);
62
+ if (!boards.success) {
63
+ for (const issue of boards.error.issues) {
64
+ context.addIssue({
65
+ code: "custom",
66
+ path: ["boards", ...issue.path],
67
+ message: issue.message
68
+ });
69
+ }
70
+ }
71
+ });
72
+ var SeatFrameSchema = z.object({
73
+ events: z.array(GameEventSchema).max(32),
74
+ view: ProjectedViewSchema.nullable(),
75
+ flow: z.object({
76
+ currentPhase: z.string().nullable(),
77
+ activePlayers: z.array(PlayerIdSchema),
78
+ simultaneousPhase: SimultaneousPhaseSnapshotSchema.nullable()
79
+ }).strict(),
80
+ availableInteractions: z.array(InteractionDescriptorSchema),
81
+ zones: z.record(
82
+ z.string(),
83
+ z.record(z.string(), ZoneHandlesSnapshotSchema)
84
+ )
85
+ }).strict();
86
+ var PluginGameplayFrameSchema = SeatFrameSchema.extend({
87
+ basis: GameplayBasisSchema
88
+ });
89
+ var InteractionResultSchema = z.discriminatedUnion("accepted", [
90
+ z.object({
91
+ type: z.literal("interaction.result"),
92
+ clientActionId: z.string().min(1),
93
+ accepted: z.literal(true)
94
+ }).strict(),
95
+ z.object({
96
+ type: z.literal("interaction.result"),
97
+ clientActionId: z.string().min(1),
98
+ accepted: z.literal(false),
99
+ errorCode: z.string().min(1),
100
+ message: z.string().optional()
101
+ }).strict()
102
+ ]);
103
+ var SubmitInteractionCommandSchema = z.object({
104
+ type: z.literal("interaction.submit"),
105
+ clientActionId: z.string().min(1),
106
+ basis: GameplayBasisSchema,
107
+ interactionId: z.string().min(1),
108
+ params: RuntimeJsonSchema
109
+ }).strict();
110
+ var CancelInteractionCommandSchema = SubmitInteractionCommandSchema.omit({ params: true }).extend({ type: z.literal("interaction.cancel") }).strict();
111
+ var HostToPluginPayloadSchema = z.discriminatedUnion("type", [
112
+ z.object({
113
+ type: z.literal("runtime.init"),
114
+ session: PluginSessionDescriptorSchema
115
+ }).strict(),
116
+ z.object({
117
+ type: z.literal("gameplay.frame"),
118
+ frame: PluginGameplayFrameSchema
119
+ }).strict(),
120
+ InteractionResultSchema
121
+ ]);
122
+ var PluginToHostPayloadSchema = z.discriminatedUnion("type", [
123
+ z.object({ type: z.literal("runtime.ready") }).strict(),
124
+ z.object({ type: z.literal("runtime.resume") }).strict(),
125
+ z.object({
126
+ type: z.literal("runtime.ack"),
127
+ sequence: z.number().int().nonnegative(),
128
+ clientReceivedAtMs: z.number().finite().optional(),
129
+ clientRenderedAtMs: z.number().finite().optional()
130
+ }).strict(),
131
+ SubmitInteractionCommandSchema,
132
+ CancelInteractionCommandSchema,
133
+ z.object({
134
+ type: z.literal("runtime.error"),
135
+ message: z.string(),
136
+ code: z.string().optional()
137
+ }).strict()
138
+ ]);
139
+ function createPluginProtocolEnvelopeSchema(payloadSchema) {
140
+ return z.object({
141
+ protocol: z.literal(DREAMBOARD_PLUGIN_PROTOCOL),
142
+ version: z.literal(DREAMBOARD_PLUGIN_PROTOCOL_VERSION),
143
+ channelId: z.string().min(1),
144
+ sequence: z.number().int().nonnegative(),
145
+ payload: payloadSchema
146
+ }).strict();
147
+ }
148
+ var HostToPluginEnvelopeSchema = createPluginProtocolEnvelopeSchema(
149
+ HostToPluginPayloadSchema
150
+ );
151
+ var PluginToHostEnvelopeSchema = createPluginProtocolEnvelopeSchema(
152
+ PluginToHostPayloadSchema
153
+ );
154
+ function parsePluginSessionDescriptor(value) {
155
+ return PluginSessionDescriptorSchema.parse(value);
156
+ }
157
+ function parsePluginGameplayFrame(value) {
158
+ return PluginGameplayFrameSchema.parse(value);
159
+ }
160
+ function parseHostToPluginEnvelope(value) {
161
+ return HostToPluginEnvelopeSchema.parse(value);
162
+ }
163
+ function parsePluginToHostEnvelope(value) {
164
+ return PluginToHostEnvelopeSchema.parse(value);
165
+ }
166
+
167
+ // src/headless/sources/static.ts
168
+ import { createStore } from "@tanstack/store";
169
+ import * as z2 from "zod";
170
+ var SourceSnapshotSchema = z2.object({
171
+ me: z2.string().min(1),
172
+ players: z2.array(PluginPlayerSummarySchema),
173
+ frame: SeatFrameSchema,
174
+ version: z2.number().int().nonnegative()
175
+ }).strict();
176
+ function staticSource(input) {
177
+ const snapshot = immutableCopy(SourceSnapshotSchema.parse(input));
178
+ if (!snapshot.players.some((player) => player.playerId === snapshot.me))
179
+ throw new Error("Gameplay seat is absent from session.");
180
+ const store = createStore(
181
+ Object.freeze({
182
+ snapshot,
183
+ connection: "ready",
184
+ request: null,
185
+ failure: null
186
+ })
187
+ );
188
+ return {
189
+ store: {
190
+ get: () => store.get(),
191
+ subscribe: (listener) => store.subscribe(listener)
192
+ },
193
+ dispose() {
194
+ store.setState(
195
+ (state) => Object.freeze({
196
+ snapshot: state.snapshot,
197
+ connection: "closed",
198
+ request: null,
199
+ failure: null
200
+ })
201
+ );
202
+ }
203
+ };
204
+ }
205
+
206
+ // src/shared/protocol/digest.ts
207
+ function computePluginActionSetVersion(input) {
208
+ return digestPluginRuntimeJson({
209
+ digestVersion: "plugin-action-set@6",
210
+ version: input.version,
211
+ availableInteractions: input.availableInteractions
212
+ });
213
+ }
214
+ function digestPluginGameplayFrame(frame) {
215
+ return digestPluginRuntimeJson({
216
+ digestVersion: "plugin-gameplay-frame@6",
217
+ frame
218
+ });
219
+ }
220
+ function digestPluginCommandRequest(command) {
221
+ return digestPluginRuntimeJson({
222
+ digestVersion: "plugin-command-request@6",
223
+ command
224
+ });
225
+ }
226
+
227
+ // src/shared/protocol/projection.ts
228
+ function materializePluginGameplayFrame(input) {
229
+ const dynamicProjection = SeatProjectionBundleSchema2.parse(
230
+ canonicalizePluginRuntimeJson(input.dynamicProjection)
231
+ );
232
+ if (dynamicProjection.referenceBasis.sessionId !== input.sessionId || dynamicProjection.referenceBasis.version !== input.version) {
233
+ throw new Error(
234
+ "Projection reference basis does not match the frame basis."
235
+ );
236
+ }
237
+ const registry = dynamicProjection.interactionsByRef ?? {};
238
+ const seat = dynamicProjection.seats[input.perspectivePlayerId] ?? null;
239
+ const availableInteractions = seat == null ? [] : hydrateInteractionRefs(
240
+ registry,
241
+ seat.availableInteractionRefs ?? [],
242
+ "availableInteractionRefs"
243
+ );
244
+ const zones = seat?.zones == null ? {} : hydrateZones(registry, seat.zones, "zones");
245
+ const frame = {
246
+ events: seat?.events ?? [],
247
+ basis: {
248
+ sessionId: input.sessionId,
249
+ version: input.version,
250
+ actionSetVersion: input.actionSetVersion,
251
+ perspectivePlayerId: input.perspectivePlayerId
252
+ },
253
+ view: materializeView(seat?.view, seat?.boards),
254
+ flow: {
255
+ currentPhase: input.currentPhase,
256
+ activePlayers: [...input.activePlayers],
257
+ simultaneousPhase: dynamicProjection.simultaneousPhase ?? null
258
+ },
259
+ availableInteractions,
260
+ zones
261
+ };
262
+ return PluginGameplayFrameSchema.parse(frame);
263
+ }
264
+ function materializeView(seatView, seatBoards) {
265
+ const parts = [
266
+ seatView,
267
+ seatBoards === void 0 ? void 0 : { boards: seatBoards }
268
+ ].filter((part) => part !== void 0 && part !== null);
269
+ if (parts.length === 0) return null;
270
+ return Object.assign({}, ...parts);
271
+ }
272
+ function hydrateZones(registry, value, path) {
273
+ return Object.fromEntries(
274
+ Object.entries(value).map(([zoneId, hosts]) => [
275
+ zoneId,
276
+ Object.fromEntries(
277
+ Object.entries(hosts).map(([hostId, zone]) => [
278
+ hostId,
279
+ {
280
+ tiles: zone.tiles,
281
+ cardIds: zone.cardIds,
282
+ cardViewsById: zone.cardViewsById,
283
+ cardBacksById: zone.cardBacksById,
284
+ playableByCardId: Object.fromEntries(
285
+ Object.entries(zone.playableByCardId).map(([cardId, refs]) => [
286
+ cardId,
287
+ hydrateInteractionRefs(
288
+ registry,
289
+ refs,
290
+ `${path}.${zoneId}.${hostId}.playableByCardId.${cardId}`
291
+ )
292
+ ])
293
+ )
294
+ }
295
+ ])
296
+ )
297
+ ])
298
+ );
299
+ }
300
+ function hydrateInteractionRefs(registry, value, path) {
301
+ return value.map((ref, index) => {
302
+ const descriptor = registry[ref];
303
+ if (!descriptor) {
304
+ throw new Error(
305
+ `Seat projection ${path}[${index}] references '${ref}', which is missing from interactionsByRef.`
306
+ );
307
+ }
308
+ return descriptor;
309
+ });
310
+ }
311
+
312
+ // src/headless/sources/lifecycle.ts
313
+ import { createStore as createStore2 } from "@tanstack/store";
314
+ function createSourceLifecycle(options) {
315
+ let context = options.context ? immutableCopy(options.context) : null;
316
+ const store = createStore2(
317
+ Object.freeze({
318
+ snapshot: null,
319
+ connection: "connecting",
320
+ request: null,
321
+ failure: null
322
+ })
323
+ );
324
+ let session = null;
325
+ let assetUrls = null;
326
+ let basis = null;
327
+ let pending = null;
328
+ let timer;
329
+ let recovered = false;
330
+ let closed = false;
331
+ const clearTimer = () => {
332
+ clearTimeout(timer);
333
+ timer = void 0;
334
+ };
335
+ const publish = (state) => {
336
+ if (state.request) Object.freeze(state.request);
337
+ store.setState(() => Object.freeze(state));
338
+ };
339
+ const recovering = () => {
340
+ if (closed) return;
341
+ publish({ ...store.get(), connection: "recovering", failure: null });
342
+ };
343
+ const close = (failure) => {
344
+ if (closed) return;
345
+ closed = true;
346
+ clearTimer();
347
+ for (const url of Object.values(assetUrls ?? {})) URL.revokeObjectURL(url);
348
+ pending?.reject(failure ?? new Error("Gameplay source disposed."));
349
+ pending = null;
350
+ options.close();
351
+ const snapshot = store.get().snapshot;
352
+ publish(
353
+ failure ? {
354
+ connection: "failed",
355
+ snapshot,
356
+ request: null,
357
+ failure: Object.freeze(failure)
358
+ } : { connection: "closed", snapshot, request: null, failure: null }
359
+ );
360
+ };
361
+ const fail = (error) => close(error);
362
+ const arm = () => {
363
+ clearTimer();
364
+ timer = setTimeout(() => {
365
+ if (recovered) {
366
+ fail(new Error("Gameplay source recovery timed out."));
367
+ return;
368
+ }
369
+ recovered = true;
370
+ recovering();
371
+ try {
372
+ options.recover();
373
+ if (pending && !pending.accepted) options.send(pending.command);
374
+ arm();
375
+ } catch (error) {
376
+ fail(asError(error));
377
+ }
378
+ }, options.timeoutMs ?? 1e4);
379
+ };
380
+ const finishBarrier = () => {
381
+ if (!pending?.accepted) return;
382
+ const frame = store.get().snapshot;
383
+ if (!frame || frame.version <= pending.command.basis.version) return;
384
+ clearTimer();
385
+ pending = null;
386
+ publish({
387
+ snapshot: frame,
388
+ request: null,
389
+ connection: "ready",
390
+ failure: null
391
+ });
392
+ };
393
+ const start = async (operation, interactionId, params) => {
394
+ const state = store.get();
395
+ if (closed || state.connection !== "ready" || !basis)
396
+ return Promise.reject(new Error("Gameplay source is not open."));
397
+ if (pending)
398
+ return Promise.reject(
399
+ new Error("A gameplay interaction is already pending.")
400
+ );
401
+ const command = immutableCopy(
402
+ PluginToHostPayloadSchema.parse({
403
+ type: operation === "cancel" ? "interaction.cancel" : "interaction.submit",
404
+ clientActionId: crypto.randomUUID(),
405
+ basis,
406
+ interactionId,
407
+ ...operation === "cancel" ? {} : { params }
408
+ })
409
+ );
410
+ recovered = false;
411
+ const promise = new Promise((resolve, reject) => {
412
+ pending = { command, resolve, reject, accepted: false };
413
+ });
414
+ publish({
415
+ ...state,
416
+ request: {
417
+ interactionId,
418
+ operation,
419
+ phase: "awaiting-result"
420
+ }
421
+ });
422
+ arm();
423
+ try {
424
+ options.send(command);
425
+ } catch (error) {
426
+ fail(asError(error));
427
+ }
428
+ return promise;
429
+ };
430
+ const source = {
431
+ store: {
432
+ get: () => store.get(),
433
+ subscribe: (listener) => store.subscribe(listener)
434
+ },
435
+ submit: (interactionId, params) => start("submit", interactionId, params),
436
+ cancel: (interactionId) => start("cancel", interactionId),
437
+ dispose: () => close(null)
438
+ };
439
+ return {
440
+ source,
441
+ retry() {
442
+ if (closed || !pending) return;
443
+ try {
444
+ if (pending.accepted) options.recover();
445
+ else options.send(pending.command);
446
+ } catch (error) {
447
+ fail(asError(error));
448
+ }
449
+ },
450
+ fail,
451
+ recovering,
452
+ session(value) {
453
+ if (closed) return;
454
+ const { assets, ...parsed } = PluginSessionDescriptorSchema.parse(value);
455
+ if ((context?.sessionId ?? session?.sessionId) && parsed.sessionId !== (context?.sessionId ?? session?.sessionId)) {
456
+ fail(new Error("Gameplay session changed."));
457
+ return;
458
+ }
459
+ if (context && !parsed.players.some((player) => player.playerId === context.playerId)) {
460
+ fail(new Error("Gameplay seat is absent from session."));
461
+ return;
462
+ }
463
+ session = immutableCopy(parsed);
464
+ assetUrls ??= Object.fromEntries(
465
+ Object.entries(assets ?? {}).map(([path, blob]) => [
466
+ path,
467
+ URL.createObjectURL(blob)
468
+ ])
469
+ );
470
+ },
471
+ frame(value) {
472
+ if (closed) return;
473
+ const parsed = PluginGameplayFrameSchema.parse(value);
474
+ if (!session) {
475
+ fail(new Error("Gameplay frame arrived before session metadata."));
476
+ return;
477
+ }
478
+ context ??= {
479
+ sessionId: session.sessionId,
480
+ playerId: parsed.basis.perspectivePlayerId
481
+ };
482
+ if (parsed.basis.sessionId !== context.sessionId) {
483
+ fail(new Error("Gameplay authority session changed."));
484
+ return;
485
+ }
486
+ const changedSeat = parsed.basis.perspectivePlayerId !== context.playerId;
487
+ if (changedSeat && !options.followHostSeat) {
488
+ fail(new Error("Gameplay perspective changed."));
489
+ return;
490
+ }
491
+ if (!session.players.some(
492
+ (player) => player.playerId === parsed.basis.perspectivePlayerId
493
+ )) {
494
+ fail(new Error("Gameplay seat is absent from session."));
495
+ return;
496
+ }
497
+ if (basis && parsed.basis.version < basis.version) return;
498
+ if (changedSeat) {
499
+ clearTimer();
500
+ pending?.reject(new Error("Gameplay perspective changed."));
501
+ pending = null;
502
+ recovered = false;
503
+ context = { ...context, playerId: parsed.basis.perspectivePlayerId };
504
+ }
505
+ const { basis: nextBasis, ...frame } = immutableCopy(
506
+ withCardImageUrls(parsed, assetUrls)
507
+ );
508
+ basis = nextBasis;
509
+ publish({
510
+ failure: null,
511
+ request: changedSeat ? null : store.get().request,
512
+ snapshot: Object.freeze({
513
+ me: context.playerId,
514
+ players: session.players,
515
+ frame: Object.freeze(frame),
516
+ version: basis.version
517
+ }),
518
+ connection: "ready"
519
+ });
520
+ finishBarrier();
521
+ },
522
+ result(value) {
523
+ if (closed) return;
524
+ const result = InteractionResultSchema.parse(value);
525
+ if (!pending || result.clientActionId !== pending.command.clientActionId || pending.accepted)
526
+ return;
527
+ pending.resolve(
528
+ immutableCopy(
529
+ result.accepted ? { accepted: true } : {
530
+ accepted: false,
531
+ errorCode: result.errorCode,
532
+ ...result.message === void 0 ? {} : { message: result.message }
533
+ }
534
+ )
535
+ );
536
+ if (!result.accepted) {
537
+ clearTimer();
538
+ pending = null;
539
+ publish({
540
+ snapshot: store.get().snapshot,
541
+ request: null,
542
+ connection: "ready",
543
+ failure: null
544
+ });
545
+ return;
546
+ }
547
+ pending.accepted = true;
548
+ recovered = false;
549
+ const state = store.get();
550
+ publish({
551
+ connection: state.connection === "recovering" ? "recovering" : "ready",
552
+ snapshot: state.snapshot,
553
+ failure: null,
554
+ request: { ...state.request, phase: "awaiting-frame" }
555
+ });
556
+ arm();
557
+ finishBarrier();
558
+ }
559
+ };
560
+ }
561
+ function asError(error) {
562
+ return error instanceof Error ? error : new Error(String(error));
563
+ }
564
+ function withCardImageUrls(frame, urls) {
565
+ if (urls === null || Object.keys(urls).length === 0) return frame;
566
+ return {
567
+ ...frame,
568
+ zones: Object.fromEntries(
569
+ Object.entries(frame.zones).map(([zoneId, hosts]) => [
570
+ zoneId,
571
+ Object.fromEntries(
572
+ Object.entries(hosts).map(([hostId, zone]) => [
573
+ hostId,
574
+ {
575
+ ...zone,
576
+ cardViewsById: Object.fromEntries(
577
+ Object.entries(zone.cardViewsById).map(([cardId, card]) => [
578
+ cardId,
579
+ {
580
+ ...card,
581
+ frontImage: card.frontImage === void 0 ? void 0 : urls[card.frontImage] ?? card.frontImage,
582
+ backImage: card.backImage === void 0 ? void 0 : urls[card.backImage] ?? card.backImage
583
+ }
584
+ ])
585
+ ),
586
+ cardBacksById: Object.fromEntries(
587
+ Object.entries(zone.cardBacksById).map(([cardId, path]) => [
588
+ cardId,
589
+ urls[path] ?? path
590
+ ])
591
+ )
592
+ }
593
+ ])
594
+ )
595
+ ])
596
+ )
597
+ };
598
+ }
599
+
600
+ export {
601
+ DREAMBOARD_PLUGIN_PROTOCOL,
602
+ DREAMBOARD_PLUGIN_PROTOCOL_VERSION,
603
+ GameEventDetailSchema,
604
+ SystemActionEventSchema2 as SystemActionEventSchema,
605
+ GameEventSchema,
606
+ SeatProjectionBundleSchema2 as SeatProjectionBundleSchema,
607
+ PluginPlayerSummarySchema,
608
+ PluginSessionDescriptorSchema,
609
+ ZoneHandlesSnapshotSchema,
610
+ SimultaneousPhaseSnapshotSchema,
611
+ GameplayBasisSchema,
612
+ GameOutcomeSchema2 as GameOutcomeSchema,
613
+ SeatFrameSchema,
614
+ PluginGameplayFrameSchema,
615
+ InteractionResultSchema,
616
+ SubmitInteractionCommandSchema,
617
+ CancelInteractionCommandSchema,
618
+ HostToPluginPayloadSchema,
619
+ PluginToHostPayloadSchema,
620
+ createPluginProtocolEnvelopeSchema,
621
+ HostToPluginEnvelopeSchema,
622
+ PluginToHostEnvelopeSchema,
623
+ parsePluginSessionDescriptor,
624
+ parsePluginGameplayFrame,
625
+ parseHostToPluginEnvelope,
626
+ parsePluginToHostEnvelope,
627
+ SourceSnapshotSchema,
628
+ staticSource,
629
+ createSourceLifecycle,
630
+ computePluginActionSetVersion,
631
+ digestPluginGameplayFrame,
632
+ digestPluginCommandRequest,
633
+ materializePluginGameplayFrame
634
+ };
635
+ //# sourceMappingURL=chunk-YT3RPO5J.js.map