@dreamboard-games/sdk 0.5.0-alpha.11 → 0.5.0-alpha.12
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.
|
@@ -483,22 +483,32 @@ function createSourceLifecycle(options) {
|
|
|
483
483
|
fail(new Error("Gameplay authority session changed."));
|
|
484
484
|
return;
|
|
485
485
|
}
|
|
486
|
-
|
|
486
|
+
const changedSeat = parsed.basis.perspectivePlayerId !== context.playerId;
|
|
487
|
+
if (changedSeat && !options.followHostSeat) {
|
|
487
488
|
fail(new Error("Gameplay perspective changed."));
|
|
488
489
|
return;
|
|
489
490
|
}
|
|
490
|
-
if (!session.players.some(
|
|
491
|
+
if (!session.players.some(
|
|
492
|
+
(player) => player.playerId === parsed.basis.perspectivePlayerId
|
|
493
|
+
)) {
|
|
491
494
|
fail(new Error("Gameplay seat is absent from session."));
|
|
492
495
|
return;
|
|
493
496
|
}
|
|
494
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
|
+
}
|
|
495
505
|
const { basis: nextBasis, ...frame } = immutableCopy(
|
|
496
506
|
withCardImageUrls(parsed, assetUrls)
|
|
497
507
|
);
|
|
498
508
|
basis = nextBasis;
|
|
499
509
|
publish({
|
|
500
510
|
failure: null,
|
|
501
|
-
request: store.get().request,
|
|
511
|
+
request: changedSeat ? null : store.get().request,
|
|
502
512
|
snapshot: Object.freeze({
|
|
503
513
|
me: context.playerId,
|
|
504
514
|
players: session.players,
|
|
@@ -622,4 +632,4 @@ export {
|
|
|
622
632
|
digestPluginCommandRequest,
|
|
623
633
|
materializePluginGameplayFrame
|
|
624
634
|
};
|
|
625
|
-
//# sourceMappingURL=chunk-
|
|
635
|
+
//# sourceMappingURL=chunk-YUEMDRIH.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 = 10 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 { PlayerIdSchema } from \"../domain/player-identity.js\";\nimport { ViewCardSchema } from \"../domain/cards.js\";\nimport * as ReducerWireZod from \"../runtime-schema\";\nimport * as z from \"zod\";\nimport {\n DREAMBOARD_PLUGIN_PROTOCOL,\n DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n} from \"./protocol.js\";\nimport { RuntimeJsonSchema } from \"../runtime-json.js\";\nimport {\n BoardProjectionSchema,\n ProjectedTileSchema,\n} from \"../seat-topology-schema.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 GameEventDetailSchema =\n ReducerWireZod.ProjectedGameEventDetailSchema;\nexport const SystemActionEventSchema = ReducerWireZod.SystemActionEventSchema;\nexport const GameEventSchema = ReducerWireZod.ProjectedGameEventSchema;\nexport const SeatProjectionBundleSchema =\n ReducerWireZod.SeatProjectionBundleSchema;\n\nexport { PlayerIdSchema } from \"../domain/player-identity.js\";\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 tiles: z.array(ProjectedTileSchema),\n cardIds: z.array(z.string()),\n cardViewsById: z.record(z.string(), ViewCardSchema),\n cardBacksById: 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 sessionId: z.string().min(1),\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\nconst ProjectedViewSchema = z\n .record(z.string(), RuntimeJsonSchema)\n .superRefine((view, context) => {\n if (!Object.hasOwn(view, \"boards\")) return;\n const boards = BoardProjectionSchema.safeParse(view.boards);\n if (!boards.success) {\n for (const issue of boards.error.issues) {\n context.addIssue({\n code: \"custom\",\n path: [\"boards\", ...issue.path],\n message: issue.message,\n });\n }\n }\n });\n\nexport const SeatFrameSchema = z\n .object({\n events: z.array(GameEventSchema).max(32),\n view: ProjectedViewSchema.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(\n z.string(),\n z.record(z.string(), ZoneHandlesSnapshotSchema),\n ),\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 * as z from \"zod\";\nimport {\n SeatFrameSchema,\n PluginPlayerSummarySchema,\n} from \"../../shared/protocol/schema.js\";\nimport { immutableCopy } from \"../../shared/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@6\",\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@6\",\n frame,\n });\n}\n\nexport function digestPluginCommandRequest(\n command: SubmitInteractionCommand | CancelInteractionCommand,\n): string {\n return digestPluginRuntimeJson({\n digestVersion: \"plugin-command-request@6\",\n command,\n });\n}\n","import { canonicalizePluginRuntimeJson } from \"./json\";\nimport {\n PluginGameplayFrameSchema,\n SeatProjectionBundleSchema,\n} from \"./schema.js\";\nimport type {\n InteractionDescriptor,\n PlayerId,\n PluginGameplayFrame,\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 perspectivePlayerId: PlayerId;\n\n readonly sessionId: string;\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 if (\n dynamicProjection.referenceBasis.sessionId !== input.sessionId ||\n dynamicProjection.referenceBasis.version !== input.version\n ) {\n throw new Error(\n \"Projection reference basis does not match the frame basis.\",\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: seat?.events ?? [],\n basis: {\n sessionId: input.sessionId,\n version: input.version,\n actionSetVersion: input.actionSetVersion,\n perspectivePlayerId: input.perspectivePlayerId,\n },\n view: materializeView(seat?.view, seat?.boards),\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 seatView: unknown,\n seatBoards: ReducerSeatProjectionBundle[\"seats\"][string][\"boards\"],\n): RuntimeJson | null {\n const parts = [\n seatView,\n seatBoards === undefined ? undefined : { boards: seatBoards },\n ].filter((part) => part !== undefined && part !== null);\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, Record<string, ZoneHandlesSnapshot>> {\n return Object.fromEntries(\n Object.entries(value).map(([zoneId, hosts]) => [\n zoneId,\n Object.fromEntries(\n Object.entries(hosts).map(([hostId, zone]) => [\n hostId,\n {\n tiles: zone.tiles,\n cardIds: zone.cardIds,\n cardViewsById: zone.cardViewsById,\n cardBacksById: zone.cardBacksById,\n playableByCardId: Object.fromEntries(\n Object.entries(zone.playableByCardId).map(([cardId, refs]) => [\n cardId,\n hydrateInteractionRefs(\n registry,\n refs,\n `${path}.${zoneId}.${hostId}.playableByCardId.${cardId}`,\n ),\n ]),\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 {\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 \"../../shared/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\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 followHostSeat?: boolean;\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.sessionId !== context.sessionId) {\n fail(new Error(\"Gameplay authority session changed.\"));\n return;\n }\n const changedSeat = parsed.basis.perspectivePlayerId !== context.playerId;\n if (changedSeat && !options.followHostSeat) {\n fail(new Error(\"Gameplay perspective changed.\"));\n return;\n }\n if (\n !session.players.some(\n (player) => player.playerId === parsed.basis.perspectivePlayerId,\n )\n ) {\n fail(new Error(\"Gameplay seat is absent from session.\"));\n return;\n }\n if (basis && parsed.basis.version < basis.version) return;\n if (changedSeat) {\n clearTimer();\n pending?.reject(new Error(\"Gameplay perspective changed.\"));\n pending = null;\n recovered = false;\n context = { ...context, playerId: parsed.basis.perspectivePlayerId };\n }\n const { basis: nextBasis, ...frame } = immutableCopy(\n withCardImageUrls(parsed, assetUrls),\n );\n basis = nextBasis;\n publish({\n failure: null,\n request: changedSeat ? null : 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 card views and hidden card backs 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 return {\n ...frame,\n zones: Object.fromEntries(\n Object.entries(frame.zones).map(([zoneId, hosts]) => [\n zoneId,\n Object.fromEntries(\n Object.entries(hosts).map(([hostId, zone]) => [\n hostId,\n {\n ...zone,\n cardViewsById: Object.fromEntries(\n Object.entries(zone.cardViewsById).map(([cardId, card]) => [\n cardId,\n {\n ...card,\n frontImage:\n card.frontImage === undefined\n ? undefined\n : (urls[card.frontImage] ?? card.frontImage),\n backImage:\n card.backImage === undefined\n ? undefined\n : (urls[card.backImage] ?? card.backImage),\n },\n ]),\n ),\n cardBacksById: Object.fromEntries(\n Object.entries(zone.cardBacksById).map(([cardId, path]) => [\n cardId,\n urls[path] ?? path,\n ]),\n ),\n },\n ]),\n ),\n ]),\n ),\n };\n}\n"],"mappings":"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","names":["SystemActionEventSchema","SeatProjectionBundleSchema","GameOutcomeSchema","z","SeatProjectionBundleSchema","createStore","createStore"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -97,6 +97,8 @@ declare function staticSource(input: SourceSnapshot): GameSource;
|
|
|
97
97
|
/** Pins its parent window, origin and channel at the first valid initialization. */
|
|
98
98
|
declare function iframeSource(options?: {
|
|
99
99
|
timeoutMs?: number;
|
|
100
|
+
/** Trusted pass-and-play hosts may change seats without replacing the iframe. */
|
|
101
|
+
followHostSeat?: boolean;
|
|
100
102
|
}): CommandSource;
|
|
101
103
|
|
|
102
104
|
declare const GameplayCloseCode: {
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
parsePluginSessionDescriptor,
|
|
41
41
|
parsePluginToHostEnvelope,
|
|
42
42
|
staticSource
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-YUEMDRIH.js";
|
|
44
44
|
import {
|
|
45
45
|
InputDomainSchema,
|
|
46
46
|
InteractionAvailabilitySchema,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
} from "./chunk-ES74C2IN.js";
|
|
72
72
|
|
|
73
73
|
// src/package-set.ts
|
|
74
|
-
var DREAMBOARD_SDK_VERSION = true ? "0.5.0-alpha.
|
|
74
|
+
var DREAMBOARD_SDK_VERSION = true ? "0.5.0-alpha.12" : "0.0.0-development";
|
|
75
75
|
var DREAMBOARD_SDK_PACKAGES = {
|
|
76
76
|
"@dreamboard-games/sdk": DREAMBOARD_SDK_VERSION
|
|
77
77
|
};
|
|
@@ -103,6 +103,7 @@ function iframeSource(options = {}) {
|
|
|
103
103
|
};
|
|
104
104
|
const lifecycle = createSourceLifecycle({
|
|
105
105
|
timeoutMs: options.timeoutMs,
|
|
106
|
+
followHostSeat: options.followHostSeat,
|
|
106
107
|
send,
|
|
107
108
|
recover: () => send({ type: "runtime.resume" }),
|
|
108
109
|
close: () => target.removeEventListener("message", receive)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/package-set.ts","../src/headless/sources/iframe.ts","../src/shared/protocol/gameplay-wire.ts","../src/headless/sources/host-websocket.ts","../src/headless/features/hand.ts","../src/shared/tile-board-layout.ts","../src/shared/square-board-layout.ts","../src/headless/features/board.ts","../src/headless/features/drag.ts","../src/headless/features/pointer-session.ts","../src/headless/features/pan-zoom.ts","../src/headless/features/origins.ts","../src/headless/fan.ts"],"sourcesContent":["declare const __DREAMBOARD_SDK_VERSION__: string;\n\nexport const DREAMBOARD_SDK_VERSION =\n typeof __DREAMBOARD_SDK_VERSION__ === \"string\"\n ? __DREAMBOARD_SDK_VERSION__\n : \"0.0.0-development\";\n\nexport const DREAMBOARD_SDK_PACKAGES = {\n \"@dreamboard-games/sdk\": DREAMBOARD_SDK_VERSION,\n} as const;\n\nexport type DreamboardSdkPackageName = keyof typeof DREAMBOARD_SDK_PACKAGES;\n\nexport type DreamboardSdkPackageSet = {\n version: 1;\n sdkVersion: string;\n packages: Record<DreamboardSdkPackageName, string>;\n};\n\nexport const DREAMBOARD_SDK_PACKAGE_SET: DreamboardSdkPackageSet = {\n version: 1,\n sdkVersion: DREAMBOARD_SDK_VERSION,\n packages: DREAMBOARD_SDK_PACKAGES,\n};\n","import {\n DREAMBOARD_PLUGIN_PROTOCOL,\n DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n} from \"../../shared/protocol/protocol.js\";\nimport { HostToPluginEnvelopeSchema } from \"../../shared/protocol/schema.js\";\nimport type { PluginToHostPayload } from \"../../shared/protocol/protocol.js\";\nimport { createSourceLifecycle } from \"./lifecycle.js\";\nimport type { CommandSource } from \"./types.js\";\n\n/** Pins its parent window, origin and channel at the first valid initialization. */\nexport function iframeSource(\n options: {\n timeoutMs?: number;\n } = {},\n): CommandSource {\n const target = window;\n const parent = target.parent;\n let channel: { id: string; origin: string } | null = null;\n let sequence = 0;\n let receivedSequence = -1;\n const send = (payload: PluginToHostPayload) => {\n if (!channel) throw new Error(\"Iframe source is not initialized.\");\n parent.postMessage(\n {\n protocol: DREAMBOARD_PLUGIN_PROTOCOL,\n version: DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n channelId: channel.id,\n sequence: ++sequence,\n payload,\n },\n channel.origin,\n );\n };\n const lifecycle = createSourceLifecycle({\n timeoutMs: options.timeoutMs,\n send,\n recover: () => send({ type: \"runtime.resume\" }),\n close: () => target.removeEventListener(\"message\", receive),\n });\n const isOpen = () => {\n const { connection } = lifecycle.source.store.get();\n return connection !== \"closed\" && connection !== \"failed\";\n };\n function receive(event: MessageEvent) {\n if (event.source !== parent) return;\n const parsed = HostToPluginEnvelopeSchema.safeParse(event.data);\n if (!parsed.success) {\n const data: unknown = event.data;\n if (\n channel &&\n event.origin === channel.origin &&\n typeof data === \"object\" &&\n data !== null &&\n \"channelId\" in data &&\n data.channelId === channel.id\n ) {\n try {\n send({\n type: \"runtime.error\",\n code: \"host-runtime-protocol-mismatch\",\n message: \"Iframe source received an invalid host envelope.\",\n });\n } finally {\n lifecycle.fail(new Error(\"Invalid iframe host envelope.\"));\n }\n }\n return;\n }\n const envelope = parsed.data;\n if (!channel) {\n if (envelope.payload.type !== \"runtime.init\") return;\n channel = { id: envelope.channelId, origin: event.origin };\n }\n if (\n channel.id !== envelope.channelId ||\n channel.origin !== event.origin ||\n envelope.sequence <= receivedSequence\n )\n return;\n receivedSequence = envelope.sequence;\n const payload = envelope.payload;\n if (payload.type === \"runtime.init\") {\n lifecycle.session(payload.session);\n if (isOpen()) send({ type: \"runtime.ready\" });\n } else if (payload.type === \"gameplay.frame\")\n lifecycle.frame(payload.frame);\n else lifecycle.result(payload);\n if (isOpen()) send({ type: \"runtime.ack\", sequence: envelope.sequence });\n }\n target.addEventListener(\"message\", receive);\n return lifecycle.source;\n}\n","import * as z from \"zod\";\nimport {\n InteractionResultSchema,\n PluginGameplayFrameSchema,\n SubmitInteractionCommandSchema,\n CancelInteractionCommandSchema,\n} from \"./schema.js\";\nexport const GameplayCloseCode = {\n GoingAway: 1001,\n CredentialExpired: 4000,\n CredentialInvalid: 4001,\n RefreshContextMismatch: 4002,\n PermissionDenied: 4100,\n ProtocolViolation: 4200,\n FrameBeforeAuth: 4201,\n SlowConsumer: 4300,\n TooManyRequests: 4301,\n} as const;\n\nexport const GameplayCredentialSchema = z.discriminatedUnion(\"kind\", [\n z\n .object({ kind: z.literal(\"user\"), token: z.string().min(1).max(16384) })\n .strict(),\n z\n .object({ kind: z.literal(\"demo\"), secret: z.string().min(1).max(1024) })\n .strict(),\n]);\nexport const AuthConnectFrameSchema = z\n .object({\n type: z.literal(\"auth.connect\"),\n credential: GameplayCredentialSchema,\n sessionId: z.string().uuid(),\n playerId: z.string().min(1).max(128),\n })\n .strict();\nexport const AuthRefreshFrameSchema = z\n .object({\n type: z.literal(\"auth.refresh\"),\n credential: GameplayCredentialSchema,\n })\n .strict();\n\nexport const SessionResumeFrameSchema = z.object({\n type: z.literal(\"session.resume\"),\n lastSeenLogCursor: z.number().int().nonnegative().nullable(),\n unacknowledgedClientActionIds: z.array(z.string().min(1)).max(32),\n});\n\nexport const AuthAcceptedFrameSchema = z.object({\n type: z.literal(\"auth.accepted\"),\n expiresAt: z.string().datetime(),\n});\n\nexport const GameplayBackpressureReasonSchema = z.enum([\n \"queue_full\",\n \"capacity_full\",\n]);\n\nexport const GameplayBackpressureOperationSchema = z.enum([\n \"session.resume\",\n \"interaction.submit\",\n \"interaction.cancel\",\n]);\nexport const GameplayBackpressureFrameSchema = z.object({\n type: z.literal(\"gameplay.backpressure\"),\n reason: GameplayBackpressureReasonSchema,\n retryAfterMs: z.number().int().positive(),\n message: z.string().min(1),\n operation: GameplayBackpressureOperationSchema,\n clientActionId: z.string().min(1).optional(),\n});\nexport const SessionSnapshotFrameSchema = z.object({\n type: z.literal(\"session.snapshot\"),\n frame: PluginGameplayFrameSchema,\n});\nexport const ClientGameplayFrameSchema = z.discriminatedUnion(\"type\", [\n AuthConnectFrameSchema,\n AuthRefreshFrameSchema,\n SessionResumeFrameSchema,\n SubmitInteractionCommandSchema,\n CancelInteractionCommandSchema,\n]);\nexport const ServerGameplayFrameSchema = z.discriminatedUnion(\"type\", [\n AuthAcceptedFrameSchema,\n GameplayBackpressureFrameSchema,\n SessionSnapshotFrameSchema,\n InteractionResultSchema,\n]);\nexport type GameplayCredential = z.infer<typeof GameplayCredentialSchema>;\nexport type ClientGameplayFrame = z.infer<typeof ClientGameplayFrameSchema>;\nexport type ServerGameplayFrame = z.infer<typeof ServerGameplayFrameSchema>;\n","import type { PluginSessionDescriptor } from \"../../shared/protocol/frame.js\";\nimport {\n ClientGameplayFrameSchema,\n ServerGameplayFrameSchema,\n GameplayCloseCode,\n type ClientGameplayFrame,\n type GameplayCredential,\n} from \"../../shared/protocol/gameplay-wire.js\";\nimport { createSourceLifecycle } from \"./lifecycle.js\";\nimport type { CommandSource, SourceCommand } from \"./types.js\";\n\nexport function hostSource(options: {\n url: string;\n session: PluginSessionDescriptor;\n playerId: string;\n getCredential(): Promise<GameplayCredential>;\n timeoutMs?: number;\n}): CommandSource {\n const { url, playerId, getCredential } = options;\n const sessionId = options.session.sessionId;\n let socket: WebSocket | null = null;\n let generation = 0;\n let disposed = false;\n let authenticated = false;\n let queued: SourceCommand | null = null;\n let reconnects = 0;\n let refreshTimer: ReturnType<typeof setTimeout> | undefined;\n let snapshotTimer: ReturnType<typeof setTimeout> | undefined;\n let openTimer: ReturnType<typeof setTimeout> | undefined;\n let cleanup = () => {};\n const timeoutMs = options.timeoutMs ?? 10_000;\n const send = (frame: ClientGameplayFrame) => {\n if (!socket || socket.readyState !== WebSocket.OPEN)\n throw new Error(\"Gameplay socket is not open.\");\n socket.send(JSON.stringify(ClientGameplayFrameSchema.parse(frame)));\n };\n const resume = () =>\n send({\n type: \"session.resume\",\n lastSeenLogCursor: null,\n unacknowledgedClientActionIds: queued ? [queued.clientActionId] : [],\n });\n const lifecycle = createSourceLifecycle({\n context: {\n sessionId,\n playerId,\n },\n timeoutMs,\n send(command) {\n if (!authenticated) {\n queued = command;\n return;\n }\n send(command);\n },\n recover() {\n if (authenticated) resume();\n else if (!openTimer) void connect();\n },\n close() {\n disposed = true;\n generation++;\n clearTimeout(refreshTimer);\n clearTimeout(openTimer);\n clearTimeout(snapshotTimer);\n cleanup();\n socket?.close();\n socket = null;\n queued = null;\n },\n });\n lifecycle.session(options.session);\n async function connect() {\n if (disposed) return;\n const current = ++generation;\n authenticated = false;\n clearTimeout(refreshTimer);\n clearTimeout(openTimer);\n clearTimeout(snapshotTimer);\n cleanup();\n socket?.close();\n socket = null;\n openTimer = setTimeout(\n () =>\n lifecycle.fail(new Error(\"Gameplay socket authentication timed out.\")),\n timeoutMs,\n );\n try {\n const credential = await getCredential();\n if (disposed || current !== generation) return;\n const next = new WebSocket(url);\n socket = next;\n const active = () => !disposed && current === generation;\n const onOpen = () => {\n if (!active()) return;\n try {\n send({\n type: \"auth.connect\",\n credential,\n sessionId,\n playerId,\n });\n } catch (error) {\n lifecycle.fail(asError(error));\n }\n };\n const onMessage = (event: MessageEvent) => {\n if (!active()) return;\n try {\n const value: unknown = JSON.parse(String(event.data));\n if (typeof value !== \"object\" || value === null || !(\"type\" in value))\n throw new Error(\"Invalid gameplay frame.\");\n if (\n ![\n \"auth.accepted\",\n \"session.snapshot\",\n \"interaction.result\",\n \"gameplay.backpressure\",\n ].includes(String(value.type))\n )\n return;\n const frame = ServerGameplayFrameSchema.parse(value);\n if (frame.type === \"auth.accepted\") {\n clearTimeout(openTimer);\n openTimer = undefined;\n const first = !authenticated;\n authenticated = true;\n if (first) {\n snapshotTimer = setTimeout(\n () => lifecycle.fail(new Error(\"Gameplay snapshot timed out.\")),\n timeoutMs,\n );\n resume();\n if (queued) {\n send(queued);\n queued = null;\n }\n }\n clearTimeout(refreshTimer);\n if (credential.kind === \"user\") {\n const ttl = Date.parse(frame.expiresAt) - Date.now();\n if (ttl <= 0)\n throw new Error(\"Gameplay credential is already expired.\");\n refreshTimer = setTimeout(\n () => {\n openTimer = setTimeout(\n () =>\n lifecycle.fail(\n new Error(\"Gameplay credential refresh timed out.\"),\n ),\n timeoutMs,\n );\n void getCredential()\n .then((updated) => {\n if (active())\n send({ type: \"auth.refresh\", credential: updated });\n })\n .catch((error) => {\n if (active()) lifecycle.fail(asError(error));\n });\n },\n Math.max(0, ttl - Math.min(60_000, ttl * 0.2)),\n );\n }\n } else if (!authenticated)\n throw new Error(\"Gameplay frame arrived before authentication.\");\n else if (frame.type === \"session.snapshot\") {\n clearTimeout(snapshotTimer);\n snapshotTimer = undefined;\n reconnects = 0;\n lifecycle.frame(frame.frame);\n } else if (frame.type === \"interaction.result\")\n lifecycle.result(frame);\n else lifecycle.fail(new Error(frame.message));\n } catch (error) {\n lifecycle.fail(asError(error));\n }\n };\n const onClose = (event: CloseEvent) => {\n if (!active()) return;\n authenticated = false;\n lifecycle.recovering();\n if (\n new Set<number>([\n GameplayCloseCode.CredentialInvalid,\n GameplayCloseCode.RefreshContextMismatch,\n GameplayCloseCode.PermissionDenied,\n GameplayCloseCode.ProtocolViolation,\n GameplayCloseCode.FrameBeforeAuth,\n ]).has(event.code) ||\n reconnects++ > 0\n ) {\n lifecycle.fail(new Error(`Gameplay socket closed (${event.code}).`));\n return;\n }\n void connect();\n lifecycle.retry();\n };\n const onError = () => {\n if (active()) next.close();\n };\n next.addEventListener(\"open\", onOpen);\n next.addEventListener(\"message\", onMessage);\n next.addEventListener(\"close\", onClose);\n next.addEventListener(\"error\", onError);\n cleanup = () => {\n next.removeEventListener(\"open\", onOpen);\n next.removeEventListener(\"message\", onMessage);\n next.removeEventListener(\"close\", onClose);\n next.removeEventListener(\"error\", onError);\n };\n } catch (error) {\n if (!disposed && current === generation) lifecycle.fail(asError(error));\n }\n }\n void connect();\n return lifecycle.source;\n}\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n","import type { Card, CoreInstance, SeatCardId, Zone } from \"../model.js\";\n\nexport interface HandOptions<G> {\n /** Compare projected card data only; hidden cards never expose private fields. */\n readonly sort?: (\n left: Card<G, Record<never, never>>,\n right: Card<G, Record<never, never>>,\n ) => number;\n}\n\n// Generic G defers the card visibility union, so ids widen to string here.\nconst seatCardId = <G>(card: { readonly id: string }) =>\n card.id as SeatCardId<G>;\n\n/** Optional hand helpers reuse the zone order and the core selection router. */\nexport function handFeature<G>(\n _game: CoreInstance<G>,\n options: HandOptions<G> = {},\n) {\n return {\n zone: {\n getSortedCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards({ sort: options.sort }).map(seatCardId<G>);\n },\n getSelectedCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards()\n .filter((card) => card.getIsSelected())\n .map(seatCardId<G>);\n },\n getSelectableCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards()\n .filter((card) => card.getCanSelect())\n .map(seatCardId<G>);\n },\n },\n };\n}\n","import { immutableCopy } from \"./immutable.js\";\nimport { createHexTopology } from \"./hex-board.js\";\nimport { getPublicTileFootprint } from \"./tile-appearance.js\";\nimport {\n SeatBoardTopologySchema,\n type SeatBoardTopology,\n} from \"./seat-topology-schema.js\";\nimport type { SeatSpaceRef, SeatTileRef } from \"./domain/seat-reference.js\";\n\nexport type TileLayoutPoint = { readonly x: number; readonly y: number };\ntype PlacedTile = Exclude<\n SeatBoardTopology,\n { layout: \"generic\" }\n>[\"tiles\"][number];\n/** Rendering geometry is separate from inventory and spatial target handles. */\nexport type TileLayoutGeometry<Data extends PlacedTile = PlacedTile> = {\n readonly ref: SeatTileRef;\n readonly data: Data;\n readonly spaceIds: readonly SeatSpaceRef[];\n readonly outlines: readonly (readonly TileLayoutPoint[])[];\n readonly center: TileLayoutPoint;\n readonly anchor: TileLayoutPoint;\n readonly rotationDegrees: number;\n};\ntype Corner = { readonly key: string; readonly point: TileLayoutPoint };\ntype Side = { readonly from: Corner; readonly to: Corner };\ntype Cell = {\n readonly center: TileLayoutPoint;\n readonly corners: readonly Corner[];\n};\nfunction assertFinite(values: readonly number[]): void {\n if (!values.every(Number.isFinite))\n throw new Error(\"Derived tile layout geometry must be finite.\");\n}\nconst frozenPoint = (point: TileLayoutPoint) => {\n assertFinite([point.x, point.y]);\n return Object.freeze({ ...point });\n};\n\n/** Cancel internal sides using exact lattice identities, then walk every oriented boundary. */\nfunction outlines(\n cells: readonly Cell[],\n): readonly (readonly TileLayoutPoint[])[] {\n const sides = new Map<string, Side>();\n for (const cell of cells) {\n for (const [index, from] of cell.corners.entries()) {\n const to = cell.corners[(index + 1) % cell.corners.length];\n const key = [from.key, to.key].sort().join(\"|\");\n if (sides.has(key)) sides.delete(key);\n else sides.set(key, { from, to });\n }\n }\n const outgoing = new Map<string, Side[]>();\n for (const side of sides.values()) {\n const next = outgoing.get(side.from.key) ?? [];\n next.push(side);\n outgoing.set(side.from.key, next);\n }\n const loops: (readonly TileLayoutPoint[])[] = [];\n while (sides.size) {\n const first = sides.values().next().value!;\n const start = first.from.key;\n let side = first;\n const loop: TileLayoutPoint[] = [];\n while (true) {\n loop.push(frozenPoint(side.from.point));\n sides.delete([side.from.key, side.to.key].sort().join(\"|\"));\n const remaining = outgoing.get(side.from.key)!;\n remaining.splice(remaining.indexOf(side), 1);\n if (side.to.key === start) break;\n const candidates = [...(outgoing.get(side.to.key) ?? [])];\n if (!candidates.length)\n throw new Error(\"Tile footprint boundary is not closed.\");\n // At corner-touching islands, preserve the clockwise contour instead of joining islands.\n const angle = Math.atan2(\n side.to.point.y - side.from.point.y,\n side.to.point.x - side.from.point.x,\n );\n const turn = (next: typeof side) => {\n const delta =\n Math.atan2(\n next.to.point.y - next.from.point.y,\n next.to.point.x - next.from.point.x,\n ) - angle;\n return Math.atan2(Math.sin(delta), Math.cos(delta));\n };\n candidates.sort(\n (a, b) =>\n turn(b) - turn(a) ||\n (a.to.key < b.to.key ? -1 : a.to.key > b.to.key ? 1 : 0),\n );\n side = candidates[0];\n }\n loops.push(Object.freeze(loop));\n }\n return Object.freeze(loops);\n}\n\nfunction hexCells(\n boardId: string,\n orientation: \"pointy\" | \"flat\",\n coordinates: readonly { q: number; r: number }[],\n size: number,\n origin: TileLayoutPoint,\n): Cell[] {\n const topology = createHexTopology({\n id: boardId,\n orientation,\n spaces: coordinates.map((coordinate, index) => ({\n ...coordinate,\n id: String(index),\n })),\n });\n const layout = topology.getLayout({ hexSize: size, origin });\n const vertices = new Map(\n layout.vertices.map((vertex) => [vertex.id, vertex.center]),\n );\n return layout.spaces.map((space) => ({\n center: space.center,\n corners: topology\n .verticesOf(space.id)\n .map((key) => ({ key, point: vertices.get(key)! }))\n .sort(\n (a, b) =>\n Math.atan2(a.point.y - space.center.y, a.point.x - space.center.x) -\n Math.atan2(b.point.y - space.center.y, b.point.x - space.center.x),\n ),\n }));\n}\nfunction squareCells(\n coordinates: readonly { col: number; row: number }[],\n size: number,\n origin: TileLayoutPoint,\n): Cell[] {\n return coordinates.map(({ col, row }) => ({\n center: {\n x: origin.x + (col + 0.5) * size,\n y: origin.y + (row + 0.5) * size,\n },\n corners: [\n [col, row],\n [col + 1, row],\n [col + 1, row + 1],\n [col, row + 1],\n ].map(([x, y]) => ({\n key: `${x},${y}`,\n point: { x: origin.x + x * size, y: origin.y + y * size },\n })),\n }));\n}\n\nfunction build(\n board: SeatBoardTopology,\n size: number,\n origin: TileLayoutPoint,\n) {\n if (board.layout === \"generic\")\n throw new Error(\"Generic boards have no tile layout.\");\n const visibleByTile = new Map<\n SeatTileRef,\n { cells: Cell[]; ids: SeatSpaceRef[] }\n >();\n const group = (\n spaces: readonly { tileRef: SeatTileRef; id: SeatSpaceRef }[],\n cells: readonly Cell[],\n ) => {\n spaces.forEach((space, index) => {\n const grouped = visibleByTile.get(space.tileRef) ?? {\n cells: [],\n ids: [],\n };\n grouped.cells.push(cells[index]);\n grouped.ids.push(space.id);\n visibleByTile.set(space.tileRef, grouped);\n });\n };\n if (board.layout === \"hex\") {\n const spaces = Object.values(board.spaces);\n group(spaces, hexCells(board.id, board.orientation, spaces, size, origin));\n } else {\n const spaces = Object.values(board.spaces);\n group(spaces, squareCells(spaces, size, origin));\n }\n const tiles = board.tiles.map((tile): TileLayoutGeometry => {\n const visible = visibleByTile.get(tile.ref);\n const footprint =\n tile.disclosure === \"concealed\"\n ? getPublicTileFootprint(tile.appearance, tile.placement)\n : null;\n let cells: Cell[];\n let anchor: TileLayoutPoint;\n if (board.layout === \"hex\" && tile.placement.layout === \"hex\") {\n const placement = tile.placement;\n cells =\n tile.disclosure === \"visible\"\n ? (visible?.cells ?? [])\n : footprint?.layout === \"hex\"\n ? hexCells(\n board.id,\n board.orientation,\n footprint.cells,\n size,\n origin,\n )\n : [];\n anchor = hexCells(\n board.id,\n board.orientation,\n [{ q: placement.q, r: placement.r }],\n size,\n origin,\n )[0].center;\n } else if (\n board.layout === \"square\" &&\n tile.placement.layout === \"square\"\n ) {\n const placement = tile.placement;\n cells =\n tile.disclosure === \"visible\"\n ? (visible?.cells ?? [])\n : footprint?.layout === \"square\"\n ? squareCells(footprint.cells, size, origin)\n : [];\n anchor = squareCells(\n [{ col: placement.col, row: placement.row }],\n size,\n origin,\n )[0].center;\n } else throw new Error(\"Tile placement layout does not match board.\");\n if (!cells.length)\n throw new Error(\"A projected tile requires a nonempty footprint.\");\n const center = {\n x: cells.reduce((sum, cell) => sum + cell.center.x, 0) / cells.length,\n y: cells.reduce((sum, cell) => sum + cell.center.y, 0) / cells.length,\n };\n return Object.freeze({\n ref: tile.ref,\n data: tile,\n spaceIds: Object.freeze(visible?.ids ?? []),\n outlines: outlines(cells),\n center: frozenPoint(center),\n anchor: frozenPoint(anchor),\n rotationDegrees:\n tile.placement.rotation * (board.layout === \"hex\" ? 60 : 90),\n });\n });\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const tile of tiles)\n for (const loop of tile.outlines)\n for (const point of loop) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n const viewBox = {\n x: tiles.length ? minX : 0,\n y: tiles.length ? minY : 0,\n width: tiles.length ? maxX - minX : 0,\n height: tiles.length ? maxY - minY : 0,\n };\n assertFinite([viewBox.x, viewBox.y, viewBox.width, viewBox.height]);\n return Object.freeze({\n tiles: Object.freeze(tiles),\n viewBox: Object.freeze(viewBox),\n });\n}\nconst cache = new WeakMap<\n SeatBoardTopology,\n { key: string; value: ReturnType<typeof build> }\n>();\n/** Admit projected topology and layout options before caching derived rendering geometry. */\nexport function createTileBoardLayout(\n board: SeatBoardTopology,\n size: number,\n suppliedOrigin: TileLayoutPoint = { x: 0, y: 0 },\n) {\n if (!Number.isFinite(size) || size <= 0)\n throw new Error(\"Tile cell size must be positive and finite.\");\n if (![suppliedOrigin.x, suppliedOrigin.y].every(Number.isFinite))\n throw new Error(\"Tile layout origin must be finite.\");\n const key = JSON.stringify([size, suppliedOrigin.x, suppliedOrigin.y]);\n const cached = cache.get(board);\n if (cached?.key === key) return cached.value;\n const value = build(\n immutableCopy(SeatBoardTopologySchema.parse(board)),\n size,\n {\n ...suppliedOrigin,\n },\n );\n cache.set(board, { key, value });\n return value;\n}\n","import type { SquareBoardTopology } from \"./board-topology.js\";\nimport { parseBoardElementId } from \"./domain/board-element.js\";\n\ntype Point = { readonly x: number; readonly y: number };\n\n/** Render admitted square topology without inferring boundary incidence from cells. */\nexport function createSquareBoardLayout(\n board: {\n readonly id: string;\n readonly spaces: Readonly<\n Record<\n string,\n { readonly id: string; readonly col: number; readonly row: number }\n >\n >;\n readonly vertices: SquareBoardTopology[\"vertices\"];\n readonly edges: SquareBoardTopology[\"edges\"];\n },\n size: number,\n origin: Point,\n) {\n if (!Number.isFinite(size) || size <= 0)\n throw new Error(\"Square cell size must be positive and finite.\");\n if (![origin.x, origin.y].every(Number.isFinite))\n throw new Error(\"Layout origin must be finite.\");\n const spaces = Object.values(board.spaces).map((space) => {\n const x = origin.x + space.col * size;\n const y = origin.y + space.row * size;\n return {\n id: space.id,\n center: { x: x + size / 2, y: y + size / 2 },\n corners: [\n { x, y },\n { x: x + size, y },\n { x: x + size, y: y + size },\n { x, y: y + size },\n ],\n };\n });\n const vertices = board.vertices.map((vertex) => {\n const identity = parseBoardElementId(vertex.id);\n if (\n !identity ||\n identity.kind !== \"vertex\" ||\n identity.layout !== \"square\" ||\n identity.boardId !== board.id\n )\n throw new Error(\n `Square vertex '${vertex.id}' does not belong to board '${board.id}'.`,\n );\n const [col, row] = identity.latticeId.split(\",\").map(Number);\n return {\n id: vertex.id,\n center: { x: origin.x + col * size, y: origin.y + row * size },\n };\n });\n const vertexPoints = new Map(\n vertices.map((vertex) => [vertex.id, vertex.center]),\n );\n const edges = board.edges.map((edge) => {\n const from = vertexPoints.get(edge.vertexIds[0]);\n const to = vertexPoints.get(edge.vertexIds[1]);\n if (!from || !to)\n throw new Error(`Square edge '${edge.id}' references a missing vertex.`);\n return { id: edge.id, from, to };\n });\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const space of spaces) {\n for (const point of space.corners) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n }\n const x = spaces.length ? minX : 0;\n const y = spaces.length ? minY : 0;\n return {\n viewBox: {\n x,\n y,\n width: spaces.length ? maxX - x : 0,\n height: spaces.length ? maxY - y : 0,\n },\n spaces,\n edges,\n vertices,\n pointToSpace(point: Point): string | undefined {\n const col = Math.floor((point.x - origin.x) / size);\n const row = Math.floor((point.y - origin.y) / size);\n return Object.values(board.spaces).find(\n (space) => space.col === col && space.row === row,\n )?.id;\n },\n };\n}\n","import {\n createTileBoardLayout,\n type TileLayoutGeometry,\n} from \"../../shared/tile-board-layout.js\";\nimport type { SeatBoardTopology } from \"../../shared/seat-topology-schema.js\";\ntype ProjectedBoardSpace = SeatBoardTopology[\"spaces\"][string];\nimport { createSquareBoardLayout } from \"../../shared/square-board-layout.js\";\nimport {\n runtimeFeatures,\n type RuntimeBoard,\n type RuntimeFeatureContext,\n type RuntimeFeatureSnapshot,\n type RuntimeCollection,\n} from \"../runtime-features.js\";\nimport type { RuntimeTargetOptions } from \"../targets.js\";\nimport type {\n BoardBase,\n BoardDataOf,\n IdOf,\n BoardCollection,\n BoardSpaceCollection,\n BoardSpace,\n CoreInstance,\n FeatureContext,\n TargetOptions,\n ActionProps,\n} from \"../model.js\";\nimport type { BoardEdge, BoardVertex } from \"../../shared/board-topology.js\";\nimport { requireLookup } from \"../../shared/lookup.js\";\nimport { AmbiguousTargetError } from \"../instance.js\";\nimport {\n createHexTopology,\n createHexTopologyCache,\n} from \"../../shared/hex-board.js\";\nimport type { Point } from \"./pointer-session.js\";\nimport type { ViewportTransform } from \"./pan-zoom.js\";\n\ninterface RuntimeSpace {\n readonly id: string;\n readonly data: ProjectedBoardSpace;\n readonly board: RuntimeBoard;\n getIsEligible(): boolean;\n getIsSelectable(): boolean;\n getIsSelected(): boolean;\n getSelectHandler(options?: RuntimeTargetOptions): () => void;\n getTargetProps(options?: RuntimeTargetOptions): ActionProps;\n}\ninterface RuntimeLayoutTarget {\n readonly id: string;\n getIsEligible(): boolean;\n getIsSelectable(): boolean;\n getIsSelected(): boolean;\n getSelectHandler(options?: RuntimeTargetOptions): () => void;\n getTargetProps(options?: RuntimeTargetOptions): ActionProps;\n}\ninterface RuntimeLayout {\n readonly viewBox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n getSpaces(): readonly (RuntimeSpace & {\n readonly center: Point;\n points(): readonly Point[];\n readonly transform: string;\n })[];\n getEdges(): readonly (RuntimeLayoutTarget & {\n readonly data: BoardEdge | undefined;\n readonly center: Point;\n readonly line: readonly [Point, Point];\n })[];\n getVertices(): readonly (RuntimeLayoutTarget & {\n readonly data: BoardVertex | undefined;\n readonly center: Point;\n })[];\n getTiles(): readonly TileLayoutGeometry[];\n pointToSpace(x: number, y: number): string | undefined;\n}\ntype TargetKind = \"space\" | \"edge\" | \"vertex\";\nexport interface BoardLayoutOptions {\n /** Hex radius, or square cell width and height. */\n readonly hexSize: number;\n readonly origin?: Point;\n readonly viewport?: ViewportTransform;\n}\ninterface Geometry {\n readonly viewBox: { x: number; y: number; width: number; height: number };\n readonly spaces: readonly {\n id: string;\n center: Point;\n corners: readonly Point[];\n }[];\n readonly edges: readonly { id: string; from: Point; to: Point }[];\n readonly vertices: readonly { id: string; center: Point }[];\n pointToSpace(point: Point): string | undefined;\n}\n\n/** Semantic board spaces and captured selection, with optional spatial geometry. */\nfunction createRuntimeBoardFeature(context: RuntimeFeatureContext) {\n const game = context.game;\n const captures = new WeakMap<\n object,\n {\n model: RuntimeFeatureSnapshot;\n source: ReturnType<typeof game.getOptions>[\"source\"];\n geometry?: ReturnType<typeof createHexTopology>;\n }\n >();\n const cachedHexTopology = createHexTopologyCache();\n let cached:\n | {\n view: unknown;\n boards: ReturnType<RuntimeFeatureContext[\"getBoards\"]>;\n interactions: RuntimeFeatureSnapshot[\"interactions\"];\n source: ReturnType<typeof game.getOptions>[\"source\"];\n collection: RuntimeCollection<RuntimeBoard>;\n }\n | undefined;\n function collection(): RuntimeCollection<RuntimeBoard> {\n const model = game.getSnapshot();\n const source = game.getOptions().source;\n const projectedBoards = context.getBoards();\n if (\n cached &&\n cached.view === model.view &&\n cached.boards === projectedBoards &&\n cached.interactions === model.interactions &&\n cached.source === source\n )\n return cached.collection;\n const boards = Object.values(projectedBoards).map((data) => {\n const board = context.createBoard(data);\n const geometry =\n data.layout === \"hex\"\n ? cachedHexTopology({\n id: data.id,\n orientation: data.orientation,\n spaces: Object.values(data.spaces),\n })\n : undefined;\n captures.set(board, { model, source, geometry });\n return board;\n });\n const byId = new Map(boards.map((board) => [board.id, board]));\n const result: RuntimeCollection<RuntimeBoard> = Object.freeze({\n get: (id: string) => requireLookup(byId.get(id), \"Board\", id),\n find: (id: string) => byId.get(id),\n getAll: () => Object.freeze(boards),\n });\n cached = {\n view: model.view,\n boards: projectedBoards,\n interactions: model.interactions,\n source,\n collection: result,\n };\n return result;\n }\n function targetsFor(owner: RuntimeBoard) {\n const board = owner.data;\n const captured = captures.get(owner)!;\n function matchingTargets(\n model: RuntimeFeatureSnapshot,\n kind: TargetKind,\n id: string,\n ) {\n return model.interactions.list().flatMap((interaction) =>\n interaction\n .getInputs()\n .filter((input) => {\n const domain = input.getDomain();\n return (\n domain.type === \"boardTarget\" &&\n domain.targetKind === kind &&\n (domain.valueKind === \"board-space\"\n ? board.scope === \"perPlayer\" &&\n domain.boardBaseId === board.baseId\n : domain.boardId === board.id)\n );\n })\n .map((input) => {\n const domain = input.getDomain();\n return {\n interaction,\n input,\n value:\n domain.type === \"boardTarget\" &&\n domain.valueKind === \"board-space\"\n ? Object.freeze({\n boardId: board.id,\n spaceId: id,\n })\n : id,\n };\n }),\n );\n }\n function target(kind: TargetKind, id: string) {\n const matches = matchingTargets(captured.model, kind, id);\n const eligible = matches.some(({ input, value }) =>\n input.getIsEligible(value),\n );\n const selected = matches.some(({ input, value }) =>\n input.getIsSelected(value),\n );\n const selectable = matches.some(\n ({ input, value }) => !input.getTargetProps(value).disabled,\n );\n function select(options?: RuntimeTargetOptions) {\n if (\n game.getOptions().source !== captured.source ||\n game.snapshot?.me !== captured.model.snapshot?.me\n )\n return;\n const matching = matchingTargets(game.getSnapshot(), kind, id).filter(\n ({ interaction, input, value }) =>\n (!options?.interaction ||\n options.interaction === interaction.key) &&\n (!options?.input || options.input === input.key) &&\n !input.getTargetProps(value).disabled,\n );\n if (!matching.length) return;\n if (matching.length > 1) throw new AmbiguousTargetError(id);\n const domain = matching[0].input.getDomain();\n if (domain.type !== \"boardTarget\") return;\n const value = matching[0].value;\n const target =\n domain.valueKind === \"board-space\" && typeof value !== \"string\"\n ? { kind: \"space\" as const, valueKind: domain.valueKind, value }\n : {\n kind,\n valueKind: \"board-id\" as const,\n value: id,\n boardId: board.id,\n };\n context.routeTarget(target, {\n interaction: matching[0].interaction.key,\n input: matching[0].input.key,\n });\n }\n return {\n id,\n getIsEligible: () => eligible,\n getIsSelectable: () => selectable,\n getIsSelected: () => selected,\n getSelectHandler: (options?: RuntimeTargetOptions) => () =>\n select(options),\n getTargetProps(options?: RuntimeTargetOptions) {\n const candidates = matches.filter(\n ({ interaction, input, value }) =>\n (!options?.interaction ||\n interaction.key === options.interaction) &&\n (!options?.input || options.input === input.key) &&\n !input.getTargetProps(value).disabled,\n );\n const only = candidates.length === 1 ? candidates[0] : undefined;\n return {\n type: \"button\" as const,\n disabled: candidates.length === 0,\n \"data-action\": \"select\",\n \"data-value\":\n only && typeof only.value !== \"string\"\n ? JSON.stringify(only.value)\n : id,\n \"data-board\": board.id,\n \"data-interaction\": options?.interaction ?? only?.interaction.key,\n \"data-input\": only?.input.key,\n \"data-eligible\": eligible,\n \"data-selected\": selected,\n \"data-disabled\": candidates.length === 0,\n onClick: () => select(options),\n };\n },\n };\n }\n return target;\n }\n const spaceCollections = new WeakMap<\n object,\n RuntimeCollection<RuntimeSpace>\n >();\n function spacesFor(owner: RuntimeBoard): RuntimeCollection<RuntimeSpace> {\n const cached = spaceCollections.get(owner);\n if (cached) return cached;\n const target = targetsFor(owner);\n const data = owner.data;\n const values = Object.freeze(\n Object.values(data.spaces).map((space) =>\n Object.freeze({\n ...target(\"space\", space.id),\n data: space,\n board: owner,\n }),\n ),\n );\n const byId = new Map(values.map((space) => [space.id, space]));\n const spaces = Object.freeze({\n get: (id: string) =>\n requireLookup(byId.get(id), `Space on board ${owner.id}`, id),\n find: (id: string) => byId.get(id),\n getAll: () => values,\n });\n spaceCollections.set(owner, spaces);\n return spaces;\n }\n return {\n root: {\n get boards() {\n return collection();\n },\n },\n board: {\n get spaces(): RuntimeCollection<RuntimeSpace> {\n return spacesFor(this);\n },\n getLayout(\n this: RuntimeBoard,\n options: BoardLayoutOptions,\n ): RuntimeLayout {\n const board = this.data;\n if (board.layout === \"generic\")\n throw new Error(\n `Board '${board.id}' has no spatial geometry; use board.spaces for semantic selection.`,\n );\n const {\n hexSize,\n origin: suppliedOrigin = { x: 0, y: 0 },\n viewport: suppliedViewport = { x: 0, y: 0, scale: 1 },\n } = options;\n const origin = { ...suppliedOrigin };\n const viewport = { ...suppliedViewport };\n if (!Number.isFinite(hexSize) || hexSize <= 0)\n throw new Error(\"hexSize must be positive and finite.\");\n if (\n ![origin.x, origin.y, viewport.x, viewport.y, viewport.scale].every(\n Number.isFinite,\n ) ||\n viewport.scale <= 0\n )\n throw new Error(\n \"Layout transform must be finite with positive scale.\",\n );\n const captured = captures.get(this)!;\n const geometry: Geometry =\n board.layout === \"hex\"\n ? captured.geometry!.getLayout({ hexSize, origin })\n : createSquareBoardLayout(board, hexSize, origin);\n const point = (value: Point): Point => {\n const transformed = {\n x: value.x * viewport.scale + viewport.x,\n y: value.y * viewport.scale + viewport.y,\n };\n if (![transformed.x, transformed.y].every(Number.isFinite))\n throw new Error(\"Derived layout transform must be finite.\");\n return Object.freeze(transformed);\n };\n const tileGeometry = createTileBoardLayout(board, hexSize, origin);\n const tiles = Object.freeze(\n tileGeometry.tiles.map((tile) =>\n Object.freeze({\n ...tile,\n center: point(tile.center),\n anchor: point(tile.anchor),\n outlines: Object.freeze(\n tile.outlines.map((loop) => Object.freeze(loop.map(point))),\n ),\n }),\n ),\n );\n const target = targetsFor(this);\n const semanticSpaces = spacesFor(this);\n const spaces = Object.freeze(\n geometry.spaces.map((space) => {\n const corners = Object.freeze(space.corners.map(point));\n const center = point(space.center);\n return Object.freeze({\n ...semanticSpaces.get(space.id),\n center,\n points: () => corners,\n transform: `translate(${center.x} ${center.y})`,\n });\n }),\n );\n const edges = Object.freeze(\n geometry.edges.map((edge) =>\n Object.freeze({\n ...target(\"edge\", edge.id),\n data: board.edges.find((data) => data.id === edge.id),\n center: point({\n x: (edge.from.x + edge.to.x) / 2,\n y: (edge.from.y + edge.to.y) / 2,\n }),\n line: Object.freeze([point(edge.from), point(edge.to)] as const),\n }),\n ),\n );\n const vertices = Object.freeze(\n geometry.vertices.map((vertex) =>\n Object.freeze({\n ...target(\"vertex\", vertex.id),\n data: board.vertices.find((data) => data.id === vertex.id),\n center: point(vertex.center),\n }),\n ),\n );\n return Object.freeze({\n viewBox: tileGeometry.viewBox,\n getTiles: () => tiles,\n getSpaces: () => spaces,\n getEdges: () => edges,\n getVertices: () => vertices,\n pointToSpace(x: number, y: number) {\n return geometry.pointToSpace({\n x: (x - viewport.x) / viewport.scale,\n y: (y - viewport.y) / viewport.scale,\n });\n },\n });\n },\n } satisfies ThisType<RuntimeBoard>,\n };\n}\n\ntype LayoutTarget<G, Value> = Omit<\n Value,\n \"getSelectHandler\" | \"getTargetProps\"\n> & {\n getSelectHandler(options?: TargetOptions<G>): () => void;\n getTargetProps(options?: TargetOptions<G>): ActionProps;\n};\ntype LayoutElementData<G, Kind extends \"edges\" | \"vertices\"> =\n BoardDataOf<G, IdOf<G, \"boardId\">> extends infer Topology\n ? Topology extends Record<Kind, readonly (infer Element)[]>\n ? Element\n : never\n : never;\ntype LayoutElement<G, Kind extends \"edges\" | \"vertices\", Value> = LayoutTarget<\n G,\n Omit<Value, \"data\" | \"id\">\n> & {\n readonly id: LayoutElementData<G, Kind> extends { readonly id: infer Id }\n ? Id\n : never;\n readonly data: LayoutElementData<G, Kind> | undefined;\n};\n/** Seat tile presentation retains its visible/concealed data union without another discriminator. */\nexport type BoardLayoutTile<G> =\n BoardDataOf<G, IdOf<G, \"boardId\">> extends infer Board\n ? Board extends { readonly tiles: readonly (infer Tile)[] }\n ? Omit<TileLayoutGeometry, \"data\"> & { readonly data: Tile }\n : never\n : never;\n\ntype BoardLayout<G> = Omit<\n RuntimeLayout,\n \"getSpaces\" | \"getEdges\" | \"getVertices\" | \"getTiles\"\n> & {\n getTiles(): readonly BoardLayoutTile<G>[];\n getSpaces(): readonly (BoardSpace<G> & {\n readonly center: Point;\n points(): readonly Point[];\n readonly transform: string;\n })[];\n getEdges(): readonly LayoutElement<\n G,\n \"edges\",\n ReturnType<RuntimeLayout[\"getEdges\"]>[number]\n >[];\n getVertices(): readonly LayoutElement<\n G,\n \"vertices\",\n ReturnType<RuntimeLayout[\"getVertices\"]>[number]\n >[];\n};\nexport interface BoardFeature<G> {\n readonly root: { readonly boards: BoardCollection<G> };\n readonly board: {\n readonly spaces: BoardSpaceCollection<G>;\n getLayout(this: BoardBase<G>, options: BoardLayoutOptions): BoardLayout<G>;\n };\n}\n/** Bind one runtime implementation to the same game/source contract as the instance. */\nexport function boardFeature<G>(\n _game: CoreInstance<G>,\n context: FeatureContext<G>,\n): BoardFeature<G> {\n // Game-binding boundary: source identities and installed hooks belong to G.\n // Proven by headless-features/inline-boards type tests and board behavior tests.\n // eslint-disable-next-line no-restricted-syntax -- Instance composition binds these runtime source identities and feature hooks to the same game G.\n return createRuntimeBoardFeature(\n context[runtimeFeatures],\n ) as unknown as BoardFeature<G>;\n}\n","import {\n runtimeFeatures,\n type RuntimeFeatureContext,\n} from \"../runtime-features.js\";\nimport type { RuntimeDropTarget, RuntimeTargetOptions } from \"../targets.js\";\nimport type { DropTarget, TargetOptions } from \"../targets.js\";\nexport type { DropTarget } from \"../targets.js\";\nimport { isSameDropTarget } from \"../drop-targets.js\";\nimport type { CoreInstance, FeatureContext, SeatCardId } from \"../model.js\";\nexport interface DragState<G> {\n readonly cardId: SeatCardId<G>;\n readonly target: DropTarget<G> | null;\n}\n\nexport interface DragController<G> {\n readonly active: DragState<G> | null;\n getCanDrag(cardId: SeatCardId<G>, options?: TargetOptions<G>): boolean;\n begin(cardId: SeatCardId<G>, options?: TargetOptions<G>): boolean;\n getDropTargets(): readonly DropTarget<G>[];\n setDropTarget(target: DropTarget<G> | null): void;\n drop(): void;\n cancel(): void;\n}\n\ninterface RuntimeDragState {\n readonly cardId: string;\n readonly target: RuntimeDropTarget | null;\n}\ninterface RuntimeDragController {\n readonly active: RuntimeDragState | null;\n getCanDrag(cardId: string, options?: RuntimeTargetOptions): boolean;\n begin(cardId: string, options?: RuntimeTargetOptions): boolean;\n getDropTargets(): readonly RuntimeDropTarget[];\n setDropTarget(target: RuntimeDropTarget | null): void;\n drop(): void;\n cancel(): void;\n}\nfunction createRuntimeDragFeature(context: RuntimeFeatureContext) {\n const game = context.game;\n let active: RuntimeDragState | null = null;\n let selection: RuntimeTargetOptions | undefined;\n let source = game.getOptions().source;\n let seat = game.snapshot?.me;\n let disposed = false;\n let version = game.snapshot?.version;\n let lastInteractions = game.interactions;\n let lastCards = game.cards;\n let branch = snapshot();\n function update(next: RuntimeDragState | null) {\n if (disposed) return;\n active = next === null ? null : Object.freeze(next);\n branch = snapshot();\n context.invalidate();\n }\n function targets(\n cardId = active?.cardId,\n selected = selection,\n ): readonly RuntimeDropTarget[] {\n if (!cardId || game.connection !== \"ready\") return [];\n const options = selected;\n const resolved = (game.cards.find(cardId)?.getInteractions() ?? []).flatMap(\n (candidate) => {\n if (\n !candidate.getIsAvailable() ||\n (options?.interaction && candidate.key !== options.interaction)\n )\n return [];\n const inputs = candidate.getInputs();\n const cardInputs = inputs.filter(\n (input) =>\n input.getDomain().type === \"cardTarget\" &&\n (!options?.input || input.key === options.input) &&\n input.getIsEligible(cardId),\n );\n // Without a board input, the card lands on an area that runs the interaction.\n if (!inputs.some((input) => input.getDomain().type === \"boardTarget\"))\n return cardInputs.map((cardInput): RuntimeDropTarget =>\n Object.freeze({\n kind: \"interaction\",\n interactionKey: candidate.key,\n cardInputKey: cardInput.key,\n }),\n );\n return cardInputs.flatMap((cardInput) =>\n inputs.flatMap((input): RuntimeDropTarget[] => {\n const domain = input.getDomain();\n if (domain.type !== \"boardTarget\") return [];\n const route = {\n interactionKey: candidate.key,\n cardInputKey: cardInput.key,\n inputKey: input.key,\n };\n if (domain.valueKind === \"board-space\")\n return domain.eligibleTargets\n .filter((value) => !input.getTargetProps(value).disabled)\n .map((value) =>\n Object.freeze({\n kind: \"space\",\n valueKind: domain.valueKind,\n value,\n ...route,\n }),\n );\n return domain.eligibleTargets\n .filter((value) => !input.getTargetProps(value).disabled)\n .map((value) =>\n Object.freeze({\n kind: domain.targetKind,\n valueKind: domain.valueKind,\n value,\n boardId: domain.boardId,\n ...route,\n }),\n );\n }),\n );\n },\n );\n return resolved;\n }\n function cancel() {\n if (active) update(null);\n }\n function snapshot(): RuntimeDragController {\n const captured = active;\n const dropTargets = Object.freeze(targets());\n return Object.freeze<RuntimeDragController>({\n active: captured,\n getCanDrag: (cardId, options) =>\n !disposed && targets(cardId, options).length > 0,\n begin(cardId, options) {\n if (disposed || !targets(cardId, options).length) return false;\n selection = options;\n update({ cardId, target: null });\n return true;\n },\n getDropTargets: () => dropTargets,\n setDropTarget(target: RuntimeDropTarget | null) {\n if (!active || disposed) return;\n if (\n target &&\n !targets().some((candidate) => isSameDropTarget(candidate, target))\n ) {\n update({ ...active, target: null });\n return;\n }\n update({ ...active, target });\n },\n drop() {\n const finished = active;\n const eligible =\n finished?.target &&\n targets().some((target) =>\n isSameDropTarget(target, finished.target!),\n );\n cancel();\n if (!disposed && finished?.target && eligible)\n context.routeCardDrop(finished.cardId, finished.target);\n },\n cancel,\n });\n }\n const unsubscribe = game.subscribe(() => {\n const nextSource = game.getOptions().source;\n const nextSeat = game.snapshot?.me;\n const nextVersion = game.snapshot?.version;\n if (\n nextSource !== source ||\n nextSeat !== seat ||\n nextVersion !== version ||\n game.connection !== \"ready\"\n ) {\n source = nextSource;\n seat = nextSeat;\n version = nextVersion;\n cancel();\n }\n });\n return {\n root: {\n get drag() {\n if (\n lastInteractions !== game.interactions ||\n lastCards !== game.cards\n ) {\n lastInteractions = game.interactions;\n lastCards = game.cards;\n branch = snapshot();\n }\n return branch;\n },\n },\n dispose() {\n unsubscribe();\n cancel();\n disposed = true;\n },\n };\n}\n\n/**\n * Semantic card/drop routing. A card lands on a board destination when its\n * interaction has a board input, otherwise on an area that runs the\n * interaction. Gestures, hit-testing and feedback belong to /react.\n */\nexport function dragFeature<G>(\n _game: CoreInstance<G>,\n context: FeatureContext<G>,\n): { readonly root: { readonly drag: DragController<G> }; dispose(): void } {\n // Game-binding boundary: routes come from this instance's admitted descriptors.\n // The runtime implementation revalidates both inputs atomically on drop.\n return createRuntimeDragFeature(context[runtimeFeatures]) as {\n readonly root: { readonly drag: DragController<G> };\n dispose(): void;\n };\n}\n","/** Native pointer surface; importing a feature never requires browser globals. */\nexport interface PointerSurface {\n setPointerCapture(pointerId: number): void;\n hasPointerCapture(pointerId: number): boolean;\n releasePointerCapture(pointerId: number): void;\n}\n\nexport interface PointerInput {\n readonly pointerId: number;\n readonly button: number;\n readonly clientX: number;\n readonly clientY: number;\n readonly currentTarget: PointerSurface;\n preventDefault(): void;\n}\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\nexport interface PointerMove {\n readonly origin: Point;\n readonly point: Point;\n readonly delta: Point;\n}\n\n/** One captured gesture. Pointer cancellation and disposal never commit a drop. */\nexport function createPointerSession(callbacks: {\n move(value: PointerMove): void;\n end(value: PointerMove): void;\n cancel(): void;\n}) {\n let disposed = false;\n let active:\n | { id: number; surface: PointerSurface; origin: Point; point: Point }\n | undefined;\n\n function value(): PointerMove {\n const { origin, point } = active!;\n return {\n origin,\n point,\n delta: { x: point.x - origin.x, y: point.y - origin.y },\n };\n }\n\n function release() {\n const previous = active;\n active = undefined;\n if (previous?.surface.hasPointerCapture(previous.id)) {\n previous.surface.releasePointerCapture(previous.id);\n }\n }\n\n function cancel() {\n if (!active) return;\n release();\n callbacks.cancel();\n }\n\n return {\n start(event: PointerInput): boolean {\n if (disposed || active || event.button !== 0) return false;\n event.currentTarget.setPointerCapture(event.pointerId);\n const point = { x: event.clientX, y: event.clientY };\n active = {\n id: event.pointerId,\n surface: event.currentTarget,\n origin: point,\n point,\n };\n event.preventDefault();\n return true;\n },\n move(event: PointerInput) {\n if (event.pointerId !== active?.id) return;\n active.point = { x: event.clientX, y: event.clientY };\n event.preventDefault();\n callbacks.move(value());\n },\n end(event: PointerInput) {\n if (event.pointerId !== active?.id) return;\n active.point = { x: event.clientX, y: event.clientY };\n const result = value();\n release();\n callbacks.end(result);\n },\n cancel(event?: Pick<PointerInput, \"pointerId\">) {\n if (event && event.pointerId !== active?.id) return;\n cancel();\n },\n dispose() {\n disposed = true;\n cancel();\n },\n };\n}\n","import type { CoreInstance, FeatureContext } from \"../model.js\";\nimport {\n createPointerSession,\n type PointerInput,\n type PointerSurface,\n} from \"./pointer-session.js\";\n\nexport interface ViewportTransform {\n readonly x: number;\n readonly y: number;\n readonly scale: number;\n}\nexport interface ViewportSurface extends PointerSurface {\n getBoundingClientRect(): {\n readonly left: number;\n readonly top: number;\n readonly height: number;\n };\n}\nexport interface WheelInput {\n readonly clientX: number;\n readonly clientY: number;\n readonly deltaY: number;\n readonly deltaMode: number;\n readonly currentTarget: ViewportSurface;\n preventDefault(): void;\n}\nexport interface PanZoomOptions {\n readonly initial?: ViewportTransform;\n readonly minScale?: number;\n readonly maxScale?: number;\n}\n\n/** Native pointer panning and wheel zoom around the cursor. No document listeners. */\nexport function panZoomFeature<G>(\n game: CoreInstance<G>,\n context: FeatureContext<G>,\n options: PanZoomOptions = {},\n) {\n const minScale = options.minScale ?? 0.25;\n const maxScale = options.maxScale ?? 4;\n if (\n !Number.isFinite(minScale) ||\n !Number.isFinite(maxScale) ||\n minScale <= 0 ||\n maxScale < minScale\n ) {\n throw new Error(\n \"Viewport scale limits must be positive, finite, and ordered.\",\n );\n }\n const initial = options.initial ?? { x: 0, y: 0, scale: 1 };\n let disposed = false;\n let source = game.getOptions().source;\n let seat = game.snapshot?.me;\n let dragOrigin = initial;\n let transform = admit(initial);\n let branch = snapshot();\n\n function admit(value: ViewportTransform): ViewportTransform {\n if (\n ![value.x, value.y, value.scale].every(Number.isFinite) ||\n value.scale <= 0\n ) {\n throw new Error(\n \"Viewport transform must have finite coordinates and positive scale.\",\n );\n }\n return Object.freeze({\n x: value.x,\n y: value.y,\n scale: Math.min(maxScale, Math.max(minScale, value.scale)),\n });\n }\n function update(value: ViewportTransform) {\n if (disposed) return;\n const next = admit(value);\n if (\n next.x === transform.x &&\n next.y === transform.y &&\n next.scale === transform.scale\n )\n return;\n transform = next;\n branch = snapshot();\n context.invalidate();\n }\n const pointer = createPointerSession({\n move: ({ delta }) =>\n update({\n ...dragOrigin,\n x: dragOrigin.x + delta.x,\n y: dragOrigin.y + delta.y,\n }),\n end: ({ delta }) =>\n update({\n ...dragOrigin,\n x: dragOrigin.x + delta.x,\n y: dragOrigin.y + delta.y,\n }),\n cancel() {},\n });\n function props() {\n return {\n style: { touchAction: \"none\" as const },\n onPointerDown(event: PointerInput) {\n if (pointer.start(event)) dragOrigin = transform;\n },\n onPointerMove: pointer.move,\n onPointerUp: pointer.end,\n onPointerCancel: pointer.cancel,\n onLostPointerCapture: pointer.cancel,\n onWheel(event: WheelInput) {\n if (disposed) return;\n event.preventDefault();\n const rect = event.currentTarget.getBoundingClientRect();\n const unit =\n event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? rect.height : 1;\n const scale = Math.min(\n maxScale,\n Math.max(\n minScale,\n transform.scale * Math.exp(-event.deltaY * unit * 0.002),\n ),\n );\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n const ratio = scale / transform.scale;\n update({\n x: x - (x - transform.x) * ratio,\n y: y - (y - transform.y) * ratio,\n scale,\n });\n },\n };\n }\n function snapshot() {\n const captured = transform;\n return Object.freeze({\n transform: captured,\n getTransform: () => captured,\n getProps: props,\n setTransform: update,\n reset: () => {\n pointer.cancel();\n update(initial);\n },\n });\n }\n const unsubscribe = game.subscribe(() => {\n const nextSource = game.getOptions().source;\n const nextSeat = game.snapshot?.me;\n if (nextSource !== source || nextSeat !== seat) {\n source = nextSource;\n seat = nextSeat;\n pointer.cancel();\n update(initial);\n }\n });\n return {\n root: {\n get viewport() {\n return branch;\n },\n },\n dispose() {\n disposed = true;\n unsubscribe();\n pointer.dispose();\n },\n };\n}\n","import { isHiddenCardId as isHidden } from \"../../shared/domain/cards.js\";\nimport type { CoreInstance, IdOf, SeatCardId, ZoneHostId } from \"../model.js\";\nimport type { SourceSnapshot } from \"../sources/types.js\";\n\n/**\n * Where a card that arrived in its zone with the current frame was on the\n * previous one: another zone, or the private zones of the player who moved.\n * `hidden` says whether the seat saw only the card's back there.\n */\nexport type CardOrigin<G> =\n | {\n readonly zone: IdOf<G, \"zoneId\">;\n readonly hostId: ZoneHostId<G>;\n readonly hidden: boolean;\n }\n | { readonly player: IdOf<G, \"playerId\">; readonly hidden: true };\n\ntype RuntimeOrigin =\n | {\n readonly zone: string;\n readonly hostId?: string;\n readonly hidden: boolean;\n }\n | { readonly player: string; readonly hidden: true };\ntype NestedZones = SourceSnapshot[\"frame\"][\"zones\"];\ntype Zones = Record<\n string,\n import(\"../../shared/protocol/frame\").ZoneHandlesSnapshot\n>;\nconst flatten = (zones: NestedZones): Zones =>\n Object.fromEntries(\n Object.entries(zones).flatMap(([zoneId, hosts]) =>\n Object.entries(hosts).map(([hostId, zone]) => [\n JSON.stringify([zoneId, hostId]),\n zone,\n ]),\n ),\n );\n\nconst hiddenCount = (zones: Zones, zone: string) =>\n zones[zone]?.cardIds.filter(isHidden).length ?? 0;\n\nfunction singleOrigin(\n departures: readonly {\n readonly zone: string;\n readonly hostId?: string;\n readonly hidden: boolean;\n }[],\n count: number,\n) {\n const origin = departures[0];\n return origin &&\n departures.length >= count &&\n departures.every(\n (card) => card.zone === origin.zone && card.hidden === origin.hidden,\n )\n ? Object.freeze(origin)\n : null;\n}\n\n/**\n * Visible ids are card identities, so a visible card is followed between\n * zones. Hidden ids are positions, so only their net counts are compared.\n * An inferred origin requires one compatible source with enough departures;\n * existing hidden cards make the arriving positions ambiguous. Unexplained\n * arrivals can come from the sole mover's private zones, which the seat's\n * frame does not list. Ambiguous origins are omitted.\n */\nexport function findCardOrigins(\n previousNested: NestedZones,\n nextNested: NestedZones,\n mover: string | null,\n): ReadonlyMap<string, RuntimeOrigin> {\n const previous = flatten(previousNested);\n const next = flatten(nextNested);\n const shownBefore = new Map<string, string>();\n for (const [zone, { cardIds }] of Object.entries(previous))\n for (const cardId of cardIds)\n if (!isHidden(cardId)) shownBefore.set(cardId, zone);\n const shownNow = new Set(\n Object.values(next).flatMap(({ cardIds }) =>\n cardIds.filter((cardId) => !isHidden(cardId)),\n ),\n );\n let left = Object.entries(previous).flatMap(([zone, { cardIds }]) => [\n ...cardIds\n .filter((cardId) => !isHidden(cardId) && !shownNow.has(cardId))\n .map(() => ({ zone, hidden: false })),\n ...Array.from(\n {\n length: Math.max(\n 0,\n hiddenCount(previous, zone) - hiddenCount(next, zone),\n ),\n },\n () => ({ zone, hidden: true }),\n ),\n ]);\n const origins = new Map<string, RuntimeOrigin>();\n const shownArrivals: string[] = [];\n const hiddenArrivals: (string | null)[] = [];\n for (const [zone, { cardIds }] of Object.entries(next)) {\n for (const cardId of cardIds) {\n if (isHidden(cardId)) continue;\n const from = shownBefore.get(cardId);\n if (from === undefined) shownArrivals.push(cardId);\n else if (from !== zone)\n origins.set(cardId, Object.freeze({ zone: from, hidden: false }));\n }\n const hidden = cardIds.filter(isHidden);\n const before = hiddenCount(previous, zone);\n // Count ambiguous arrivals too, so another destination cannot claim their source.\n hiddenArrivals.push(\n ...Array.from(\n { length: Math.max(0, hidden.length - before) },\n (_, index) => (before === 0 ? hidden[index] : null),\n ),\n );\n }\n // Concealing a visible card can replace a hidden departure without changing\n // the hidden count. Net counts cannot resolve those simultaneous movements.\n if (\n left.some(\n (card) =>\n !card.hidden &&\n hiddenCount(previous, card.zone) > 0 &&\n hiddenCount(next, card.zone) > 0,\n )\n )\n return decodedOrigins(origins);\n const hiddenLeft = left.filter((card) => card.hidden);\n if (shownArrivals.length) {\n const origin = singleOrigin(hiddenLeft, shownArrivals.length);\n if (origin) {\n for (const cardId of shownArrivals) origins.set(cardId, origin);\n left = [\n ...left.filter((card) => !card.hidden),\n ...hiddenLeft.slice(shownArrivals.length),\n ];\n } else if (hiddenLeft.length) {\n // Which departures the shown cards consumed is also ambiguous.\n return decodedOrigins(origins);\n } else if (mover !== null) {\n const origin = Object.freeze({ player: mover, hidden: true as const });\n for (const cardId of shownArrivals) origins.set(cardId, origin);\n }\n }\n const hiddenOrigin =\n singleOrigin(left, hiddenArrivals.length) ??\n (left.length === 0 && mover !== null\n ? Object.freeze({ player: mover, hidden: true as const })\n : null);\n if (hiddenOrigin) {\n for (const cardId of hiddenArrivals)\n if (cardId !== null) origins.set(cardId, hiddenOrigin);\n }\n return decodedOrigins(origins);\n}\n\n/** The sole active player, when it is another seat. */\nfunction moverOf(snapshot: SourceSnapshot) {\n const active = snapshot.frame.flow.activePlayers;\n return active.length === 1 && active[0] !== snapshot.me ? active[0] : null;\n}\n\n/**\n * Adds `card.getOrigin()`: where a card that arrived in its zone with the\n * current frame came from, or null. Origins last until the next frame and\n * reset when the seat or source changes. Hidden origins are inferred from\n * net counts; ambiguous sources and arriving positions return null.\n */\nexport function originsFeature<G>(game: CoreInstance<G>) {\n type Origins = ReadonlyMap<SeatCardId<G>, CardOrigin<G>>;\n let frame = game.snapshot;\n let source = game.getOptions().source;\n let origins: Origins = new Map();\n function sync() {\n const next = game.snapshot;\n const nextSource = game.getOptions().source;\n if (\n next?.version === frame?.version &&\n next?.me === frame?.me &&\n nextSource === source\n )\n return;\n // Game-binding boundary: card, zone and player ids come from this instance's frames.\n origins =\n frame &&\n next &&\n next.me === frame.me &&\n nextSource === source &&\n next.version === frame.version + 1\n ? (findCardOrigins(\n frame.frame.zones,\n next.frame.zones,\n moverOf(frame),\n ) as Origins)\n : new Map();\n frame = next;\n source = nextSource;\n }\n // Also read lazily, so a reader notified before this listener sees the new frame's origins.\n const unsubscribe = game.subscribe(sync);\n return {\n card: {\n getOrigin(this: { readonly id: SeatCardId<G> }): CardOrigin<G> | null {\n sync();\n return origins.get(this.id) ?? null;\n },\n },\n dispose: unsubscribe,\n };\n}\n\nfunction decodedOrigins(\n origins: ReadonlyMap<string, RuntimeOrigin>,\n): ReadonlyMap<string, RuntimeOrigin> {\n return new Map<string, RuntimeOrigin>(\n [...origins].map(([id, origin]) => {\n if (!(\"zone\" in origin)) return [id, origin];\n const [zone, hostId] = JSON.parse(origin.zone) as [string, string];\n return [id, Object.freeze({ ...origin, zone, hostId })];\n }),\n );\n}\n","const RADIANS = Math.PI / 180;\n\nexport interface FanOptions {\n readonly count: number;\n /** The width available to the fan, in pixels. */\n readonly width: number;\n readonly cardWidth: number;\n readonly cardHeight: number;\n /** Distance between neighbouring cards along the arc when there is room. Default: 60% of the card width. */\n readonly step?: number;\n /** The smallest visible slice of a covered card. Default: 25% of the card width. */\n readonly minStep?: number;\n /** Degrees between neighbouring cards. Default 5; 0 lays a straight row. */\n readonly angle?: number;\n /** The most degrees between the two end cards. Default 30. */\n readonly maxSpread?: number;\n}\n\n/** A card's CSS `translate` from the fan's top-left corner, and its `rotate` about its own centre. */\nexport interface FanCard {\n readonly x: number;\n readonly y: number;\n /** Degrees clockwise. */\n readonly rotate: number;\n}\n\nexport interface FanLayout {\n readonly cards: readonly FanCard[];\n /** The fan's bounding box. It is wider than the available width only when the cards are at `minStep`. */\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Lays cards on a circular arc. The spread grows with the card count up to\n * `maxSpread`; the step shrinks continuously to fit the width, down to\n * `minStep`, past which the fan overflows and the hand should scroll.\n */\nexport function fanLayout({\n count,\n width,\n cardWidth,\n cardHeight,\n step = cardWidth * 0.6,\n minStep = cardWidth * 0.25,\n angle = 5,\n maxSpread = 30,\n}: FanOptions): FanLayout {\n if (count < 1) return { cards: [], width: 0, height: 0 };\n const gaps = count - 1;\n const delta = gaps ? Math.min(angle, maxSpread / gaps) * RADIANS : 0;\n const edge = (gaps * delta) / 2;\n // The horizontal distance between the end cards' centres is `spacing * span`.\n const span = delta ? (2 * Math.sin(edge)) / delta : gaps;\n // The end cards' outer halves, tilted by the edge angle.\n const ends = cardWidth * Math.cos(edge) + cardHeight * Math.sin(edge);\n const spacing = span\n ? Math.max(minStep, Math.min(step, (width - ends) / span))\n : 0;\n const radius = delta ? spacing / delta : 0;\n const centres = Array.from({ length: count }, (_, index) => {\n if (!delta) return { theta: 0, x: (index - gaps / 2) * spacing, y: 0 };\n const theta = (index - gaps / 2) * delta;\n return {\n theta,\n x: radius * Math.sin(theta),\n y: radius * (1 - Math.cos(theta)),\n };\n });\n const halfHeight = (theta: number) =>\n (cardHeight / 2) * Math.cos(theta) +\n (cardWidth / 2) * Math.abs(Math.sin(theta));\n const top = Math.min(\n ...centres.map((card) => card.y - halfHeight(card.theta)),\n );\n const bottom = Math.max(\n ...centres.map((card) => card.y + halfHeight(card.theta)),\n );\n const fanWidth = spacing * span + ends;\n return {\n cards: centres.map((card) => ({\n x: card.x + (fanWidth - cardWidth) / 2,\n y: card.y - top - cardHeight / 2,\n rotate: card.theta / RADIANS,\n })),\n width: fanWidth,\n height: bottom - top,\n };\n}\n\n/** Moves a fanned card outward along its own tilt, as for a selected card. */\nexport function liftFanCard(card: FanCard, distance: number): FanCard {\n const theta = card.rotate * RADIANS;\n return {\n x: card.x + distance * Math.sin(theta),\n y: card.y - distance * Math.cos(theta),\n rotate: card.rotate,\n };\n}\n"],"mappings":"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","names":["x","y","value","target","cached","origin"]}
|
|
1
|
+
{"version":3,"sources":["../src/package-set.ts","../src/headless/sources/iframe.ts","../src/shared/protocol/gameplay-wire.ts","../src/headless/sources/host-websocket.ts","../src/headless/features/hand.ts","../src/shared/tile-board-layout.ts","../src/shared/square-board-layout.ts","../src/headless/features/board.ts","../src/headless/features/drag.ts","../src/headless/features/pointer-session.ts","../src/headless/features/pan-zoom.ts","../src/headless/features/origins.ts","../src/headless/fan.ts"],"sourcesContent":["declare const __DREAMBOARD_SDK_VERSION__: string;\n\nexport const DREAMBOARD_SDK_VERSION =\n typeof __DREAMBOARD_SDK_VERSION__ === \"string\"\n ? __DREAMBOARD_SDK_VERSION__\n : \"0.0.0-development\";\n\nexport const DREAMBOARD_SDK_PACKAGES = {\n \"@dreamboard-games/sdk\": DREAMBOARD_SDK_VERSION,\n} as const;\n\nexport type DreamboardSdkPackageName = keyof typeof DREAMBOARD_SDK_PACKAGES;\n\nexport type DreamboardSdkPackageSet = {\n version: 1;\n sdkVersion: string;\n packages: Record<DreamboardSdkPackageName, string>;\n};\n\nexport const DREAMBOARD_SDK_PACKAGE_SET: DreamboardSdkPackageSet = {\n version: 1,\n sdkVersion: DREAMBOARD_SDK_VERSION,\n packages: DREAMBOARD_SDK_PACKAGES,\n};\n","import {\n DREAMBOARD_PLUGIN_PROTOCOL,\n DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n} from \"../../shared/protocol/protocol.js\";\nimport { HostToPluginEnvelopeSchema } from \"../../shared/protocol/schema.js\";\nimport type { PluginToHostPayload } from \"../../shared/protocol/protocol.js\";\nimport { createSourceLifecycle } from \"./lifecycle.js\";\nimport type { CommandSource } from \"./types.js\";\n\n/** Pins its parent window, origin and channel at the first valid initialization. */\nexport function iframeSource(\n options: {\n timeoutMs?: number;\n /** Trusted pass-and-play hosts may change seats without replacing the iframe. */\n followHostSeat?: boolean;\n } = {},\n): CommandSource {\n const target = window;\n const parent = target.parent;\n let channel: { id: string; origin: string } | null = null;\n let sequence = 0;\n let receivedSequence = -1;\n const send = (payload: PluginToHostPayload) => {\n if (!channel) throw new Error(\"Iframe source is not initialized.\");\n parent.postMessage(\n {\n protocol: DREAMBOARD_PLUGIN_PROTOCOL,\n version: DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n channelId: channel.id,\n sequence: ++sequence,\n payload,\n },\n channel.origin,\n );\n };\n const lifecycle = createSourceLifecycle({\n timeoutMs: options.timeoutMs,\n followHostSeat: options.followHostSeat,\n send,\n recover: () => send({ type: \"runtime.resume\" }),\n close: () => target.removeEventListener(\"message\", receive),\n });\n const isOpen = () => {\n const { connection } = lifecycle.source.store.get();\n return connection !== \"closed\" && connection !== \"failed\";\n };\n function receive(event: MessageEvent) {\n if (event.source !== parent) return;\n const parsed = HostToPluginEnvelopeSchema.safeParse(event.data);\n if (!parsed.success) {\n const data: unknown = event.data;\n if (\n channel &&\n event.origin === channel.origin &&\n typeof data === \"object\" &&\n data !== null &&\n \"channelId\" in data &&\n data.channelId === channel.id\n ) {\n try {\n send({\n type: \"runtime.error\",\n code: \"host-runtime-protocol-mismatch\",\n message: \"Iframe source received an invalid host envelope.\",\n });\n } finally {\n lifecycle.fail(new Error(\"Invalid iframe host envelope.\"));\n }\n }\n return;\n }\n const envelope = parsed.data;\n if (!channel) {\n if (envelope.payload.type !== \"runtime.init\") return;\n channel = { id: envelope.channelId, origin: event.origin };\n }\n if (\n channel.id !== envelope.channelId ||\n channel.origin !== event.origin ||\n envelope.sequence <= receivedSequence\n )\n return;\n receivedSequence = envelope.sequence;\n const payload = envelope.payload;\n if (payload.type === \"runtime.init\") {\n lifecycle.session(payload.session);\n if (isOpen()) send({ type: \"runtime.ready\" });\n } else if (payload.type === \"gameplay.frame\")\n lifecycle.frame(payload.frame);\n else lifecycle.result(payload);\n if (isOpen()) send({ type: \"runtime.ack\", sequence: envelope.sequence });\n }\n target.addEventListener(\"message\", receive);\n return lifecycle.source;\n}\n","import * as z from \"zod\";\nimport {\n InteractionResultSchema,\n PluginGameplayFrameSchema,\n SubmitInteractionCommandSchema,\n CancelInteractionCommandSchema,\n} from \"./schema.js\";\nexport const GameplayCloseCode = {\n GoingAway: 1001,\n CredentialExpired: 4000,\n CredentialInvalid: 4001,\n RefreshContextMismatch: 4002,\n PermissionDenied: 4100,\n ProtocolViolation: 4200,\n FrameBeforeAuth: 4201,\n SlowConsumer: 4300,\n TooManyRequests: 4301,\n} as const;\n\nexport const GameplayCredentialSchema = z.discriminatedUnion(\"kind\", [\n z\n .object({ kind: z.literal(\"user\"), token: z.string().min(1).max(16384) })\n .strict(),\n z\n .object({ kind: z.literal(\"demo\"), secret: z.string().min(1).max(1024) })\n .strict(),\n]);\nexport const AuthConnectFrameSchema = z\n .object({\n type: z.literal(\"auth.connect\"),\n credential: GameplayCredentialSchema,\n sessionId: z.string().uuid(),\n playerId: z.string().min(1).max(128),\n })\n .strict();\nexport const AuthRefreshFrameSchema = z\n .object({\n type: z.literal(\"auth.refresh\"),\n credential: GameplayCredentialSchema,\n })\n .strict();\n\nexport const SessionResumeFrameSchema = z.object({\n type: z.literal(\"session.resume\"),\n lastSeenLogCursor: z.number().int().nonnegative().nullable(),\n unacknowledgedClientActionIds: z.array(z.string().min(1)).max(32),\n});\n\nexport const AuthAcceptedFrameSchema = z.object({\n type: z.literal(\"auth.accepted\"),\n expiresAt: z.string().datetime(),\n});\n\nexport const GameplayBackpressureReasonSchema = z.enum([\n \"queue_full\",\n \"capacity_full\",\n]);\n\nexport const GameplayBackpressureOperationSchema = z.enum([\n \"session.resume\",\n \"interaction.submit\",\n \"interaction.cancel\",\n]);\nexport const GameplayBackpressureFrameSchema = z.object({\n type: z.literal(\"gameplay.backpressure\"),\n reason: GameplayBackpressureReasonSchema,\n retryAfterMs: z.number().int().positive(),\n message: z.string().min(1),\n operation: GameplayBackpressureOperationSchema,\n clientActionId: z.string().min(1).optional(),\n});\nexport const SessionSnapshotFrameSchema = z.object({\n type: z.literal(\"session.snapshot\"),\n frame: PluginGameplayFrameSchema,\n});\nexport const ClientGameplayFrameSchema = z.discriminatedUnion(\"type\", [\n AuthConnectFrameSchema,\n AuthRefreshFrameSchema,\n SessionResumeFrameSchema,\n SubmitInteractionCommandSchema,\n CancelInteractionCommandSchema,\n]);\nexport const ServerGameplayFrameSchema = z.discriminatedUnion(\"type\", [\n AuthAcceptedFrameSchema,\n GameplayBackpressureFrameSchema,\n SessionSnapshotFrameSchema,\n InteractionResultSchema,\n]);\nexport type GameplayCredential = z.infer<typeof GameplayCredentialSchema>;\nexport type ClientGameplayFrame = z.infer<typeof ClientGameplayFrameSchema>;\nexport type ServerGameplayFrame = z.infer<typeof ServerGameplayFrameSchema>;\n","import type { PluginSessionDescriptor } from \"../../shared/protocol/frame.js\";\nimport {\n ClientGameplayFrameSchema,\n ServerGameplayFrameSchema,\n GameplayCloseCode,\n type ClientGameplayFrame,\n type GameplayCredential,\n} from \"../../shared/protocol/gameplay-wire.js\";\nimport { createSourceLifecycle } from \"./lifecycle.js\";\nimport type { CommandSource, SourceCommand } from \"./types.js\";\n\nexport function hostSource(options: {\n url: string;\n session: PluginSessionDescriptor;\n playerId: string;\n getCredential(): Promise<GameplayCredential>;\n timeoutMs?: number;\n}): CommandSource {\n const { url, playerId, getCredential } = options;\n const sessionId = options.session.sessionId;\n let socket: WebSocket | null = null;\n let generation = 0;\n let disposed = false;\n let authenticated = false;\n let queued: SourceCommand | null = null;\n let reconnects = 0;\n let refreshTimer: ReturnType<typeof setTimeout> | undefined;\n let snapshotTimer: ReturnType<typeof setTimeout> | undefined;\n let openTimer: ReturnType<typeof setTimeout> | undefined;\n let cleanup = () => {};\n const timeoutMs = options.timeoutMs ?? 10_000;\n const send = (frame: ClientGameplayFrame) => {\n if (!socket || socket.readyState !== WebSocket.OPEN)\n throw new Error(\"Gameplay socket is not open.\");\n socket.send(JSON.stringify(ClientGameplayFrameSchema.parse(frame)));\n };\n const resume = () =>\n send({\n type: \"session.resume\",\n lastSeenLogCursor: null,\n unacknowledgedClientActionIds: queued ? [queued.clientActionId] : [],\n });\n const lifecycle = createSourceLifecycle({\n context: {\n sessionId,\n playerId,\n },\n timeoutMs,\n send(command) {\n if (!authenticated) {\n queued = command;\n return;\n }\n send(command);\n },\n recover() {\n if (authenticated) resume();\n else if (!openTimer) void connect();\n },\n close() {\n disposed = true;\n generation++;\n clearTimeout(refreshTimer);\n clearTimeout(openTimer);\n clearTimeout(snapshotTimer);\n cleanup();\n socket?.close();\n socket = null;\n queued = null;\n },\n });\n lifecycle.session(options.session);\n async function connect() {\n if (disposed) return;\n const current = ++generation;\n authenticated = false;\n clearTimeout(refreshTimer);\n clearTimeout(openTimer);\n clearTimeout(snapshotTimer);\n cleanup();\n socket?.close();\n socket = null;\n openTimer = setTimeout(\n () =>\n lifecycle.fail(new Error(\"Gameplay socket authentication timed out.\")),\n timeoutMs,\n );\n try {\n const credential = await getCredential();\n if (disposed || current !== generation) return;\n const next = new WebSocket(url);\n socket = next;\n const active = () => !disposed && current === generation;\n const onOpen = () => {\n if (!active()) return;\n try {\n send({\n type: \"auth.connect\",\n credential,\n sessionId,\n playerId,\n });\n } catch (error) {\n lifecycle.fail(asError(error));\n }\n };\n const onMessage = (event: MessageEvent) => {\n if (!active()) return;\n try {\n const value: unknown = JSON.parse(String(event.data));\n if (typeof value !== \"object\" || value === null || !(\"type\" in value))\n throw new Error(\"Invalid gameplay frame.\");\n if (\n ![\n \"auth.accepted\",\n \"session.snapshot\",\n \"interaction.result\",\n \"gameplay.backpressure\",\n ].includes(String(value.type))\n )\n return;\n const frame = ServerGameplayFrameSchema.parse(value);\n if (frame.type === \"auth.accepted\") {\n clearTimeout(openTimer);\n openTimer = undefined;\n const first = !authenticated;\n authenticated = true;\n if (first) {\n snapshotTimer = setTimeout(\n () => lifecycle.fail(new Error(\"Gameplay snapshot timed out.\")),\n timeoutMs,\n );\n resume();\n if (queued) {\n send(queued);\n queued = null;\n }\n }\n clearTimeout(refreshTimer);\n if (credential.kind === \"user\") {\n const ttl = Date.parse(frame.expiresAt) - Date.now();\n if (ttl <= 0)\n throw new Error(\"Gameplay credential is already expired.\");\n refreshTimer = setTimeout(\n () => {\n openTimer = setTimeout(\n () =>\n lifecycle.fail(\n new Error(\"Gameplay credential refresh timed out.\"),\n ),\n timeoutMs,\n );\n void getCredential()\n .then((updated) => {\n if (active())\n send({ type: \"auth.refresh\", credential: updated });\n })\n .catch((error) => {\n if (active()) lifecycle.fail(asError(error));\n });\n },\n Math.max(0, ttl - Math.min(60_000, ttl * 0.2)),\n );\n }\n } else if (!authenticated)\n throw new Error(\"Gameplay frame arrived before authentication.\");\n else if (frame.type === \"session.snapshot\") {\n clearTimeout(snapshotTimer);\n snapshotTimer = undefined;\n reconnects = 0;\n lifecycle.frame(frame.frame);\n } else if (frame.type === \"interaction.result\")\n lifecycle.result(frame);\n else lifecycle.fail(new Error(frame.message));\n } catch (error) {\n lifecycle.fail(asError(error));\n }\n };\n const onClose = (event: CloseEvent) => {\n if (!active()) return;\n authenticated = false;\n lifecycle.recovering();\n if (\n new Set<number>([\n GameplayCloseCode.CredentialInvalid,\n GameplayCloseCode.RefreshContextMismatch,\n GameplayCloseCode.PermissionDenied,\n GameplayCloseCode.ProtocolViolation,\n GameplayCloseCode.FrameBeforeAuth,\n ]).has(event.code) ||\n reconnects++ > 0\n ) {\n lifecycle.fail(new Error(`Gameplay socket closed (${event.code}).`));\n return;\n }\n void connect();\n lifecycle.retry();\n };\n const onError = () => {\n if (active()) next.close();\n };\n next.addEventListener(\"open\", onOpen);\n next.addEventListener(\"message\", onMessage);\n next.addEventListener(\"close\", onClose);\n next.addEventListener(\"error\", onError);\n cleanup = () => {\n next.removeEventListener(\"open\", onOpen);\n next.removeEventListener(\"message\", onMessage);\n next.removeEventListener(\"close\", onClose);\n next.removeEventListener(\"error\", onError);\n };\n } catch (error) {\n if (!disposed && current === generation) lifecycle.fail(asError(error));\n }\n }\n void connect();\n return lifecycle.source;\n}\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n","import type { Card, CoreInstance, SeatCardId, Zone } from \"../model.js\";\n\nexport interface HandOptions<G> {\n /** Compare projected card data only; hidden cards never expose private fields. */\n readonly sort?: (\n left: Card<G, Record<never, never>>,\n right: Card<G, Record<never, never>>,\n ) => number;\n}\n\n// Generic G defers the card visibility union, so ids widen to string here.\nconst seatCardId = <G>(card: { readonly id: string }) =>\n card.id as SeatCardId<G>;\n\n/** Optional hand helpers reuse the zone order and the core selection router. */\nexport function handFeature<G>(\n _game: CoreInstance<G>,\n options: HandOptions<G> = {},\n) {\n return {\n zone: {\n getSortedCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards({ sort: options.sort }).map(seatCardId<G>);\n },\n getSelectedCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards()\n .filter((card) => card.getIsSelected())\n .map(seatCardId<G>);\n },\n getSelectableCardIds(\n this: Zone<G, Record<never, never>>,\n ): readonly SeatCardId<G>[] {\n return this.getCards()\n .filter((card) => card.getCanSelect())\n .map(seatCardId<G>);\n },\n },\n };\n}\n","import { immutableCopy } from \"./immutable.js\";\nimport { createHexTopology } from \"./hex-board.js\";\nimport { getPublicTileFootprint } from \"./tile-appearance.js\";\nimport {\n SeatBoardTopologySchema,\n type SeatBoardTopology,\n} from \"./seat-topology-schema.js\";\nimport type { SeatSpaceRef, SeatTileRef } from \"./domain/seat-reference.js\";\n\nexport type TileLayoutPoint = { readonly x: number; readonly y: number };\ntype PlacedTile = Exclude<\n SeatBoardTopology,\n { layout: \"generic\" }\n>[\"tiles\"][number];\n/** Rendering geometry is separate from inventory and spatial target handles. */\nexport type TileLayoutGeometry<Data extends PlacedTile = PlacedTile> = {\n readonly ref: SeatTileRef;\n readonly data: Data;\n readonly spaceIds: readonly SeatSpaceRef[];\n readonly outlines: readonly (readonly TileLayoutPoint[])[];\n readonly center: TileLayoutPoint;\n readonly anchor: TileLayoutPoint;\n readonly rotationDegrees: number;\n};\ntype Corner = { readonly key: string; readonly point: TileLayoutPoint };\ntype Side = { readonly from: Corner; readonly to: Corner };\ntype Cell = {\n readonly center: TileLayoutPoint;\n readonly corners: readonly Corner[];\n};\nfunction assertFinite(values: readonly number[]): void {\n if (!values.every(Number.isFinite))\n throw new Error(\"Derived tile layout geometry must be finite.\");\n}\nconst frozenPoint = (point: TileLayoutPoint) => {\n assertFinite([point.x, point.y]);\n return Object.freeze({ ...point });\n};\n\n/** Cancel internal sides using exact lattice identities, then walk every oriented boundary. */\nfunction outlines(\n cells: readonly Cell[],\n): readonly (readonly TileLayoutPoint[])[] {\n const sides = new Map<string, Side>();\n for (const cell of cells) {\n for (const [index, from] of cell.corners.entries()) {\n const to = cell.corners[(index + 1) % cell.corners.length];\n const key = [from.key, to.key].sort().join(\"|\");\n if (sides.has(key)) sides.delete(key);\n else sides.set(key, { from, to });\n }\n }\n const outgoing = new Map<string, Side[]>();\n for (const side of sides.values()) {\n const next = outgoing.get(side.from.key) ?? [];\n next.push(side);\n outgoing.set(side.from.key, next);\n }\n const loops: (readonly TileLayoutPoint[])[] = [];\n while (sides.size) {\n const first = sides.values().next().value!;\n const start = first.from.key;\n let side = first;\n const loop: TileLayoutPoint[] = [];\n while (true) {\n loop.push(frozenPoint(side.from.point));\n sides.delete([side.from.key, side.to.key].sort().join(\"|\"));\n const remaining = outgoing.get(side.from.key)!;\n remaining.splice(remaining.indexOf(side), 1);\n if (side.to.key === start) break;\n const candidates = [...(outgoing.get(side.to.key) ?? [])];\n if (!candidates.length)\n throw new Error(\"Tile footprint boundary is not closed.\");\n // At corner-touching islands, preserve the clockwise contour instead of joining islands.\n const angle = Math.atan2(\n side.to.point.y - side.from.point.y,\n side.to.point.x - side.from.point.x,\n );\n const turn = (next: typeof side) => {\n const delta =\n Math.atan2(\n next.to.point.y - next.from.point.y,\n next.to.point.x - next.from.point.x,\n ) - angle;\n return Math.atan2(Math.sin(delta), Math.cos(delta));\n };\n candidates.sort(\n (a, b) =>\n turn(b) - turn(a) ||\n (a.to.key < b.to.key ? -1 : a.to.key > b.to.key ? 1 : 0),\n );\n side = candidates[0];\n }\n loops.push(Object.freeze(loop));\n }\n return Object.freeze(loops);\n}\n\nfunction hexCells(\n boardId: string,\n orientation: \"pointy\" | \"flat\",\n coordinates: readonly { q: number; r: number }[],\n size: number,\n origin: TileLayoutPoint,\n): Cell[] {\n const topology = createHexTopology({\n id: boardId,\n orientation,\n spaces: coordinates.map((coordinate, index) => ({\n ...coordinate,\n id: String(index),\n })),\n });\n const layout = topology.getLayout({ hexSize: size, origin });\n const vertices = new Map(\n layout.vertices.map((vertex) => [vertex.id, vertex.center]),\n );\n return layout.spaces.map((space) => ({\n center: space.center,\n corners: topology\n .verticesOf(space.id)\n .map((key) => ({ key, point: vertices.get(key)! }))\n .sort(\n (a, b) =>\n Math.atan2(a.point.y - space.center.y, a.point.x - space.center.x) -\n Math.atan2(b.point.y - space.center.y, b.point.x - space.center.x),\n ),\n }));\n}\nfunction squareCells(\n coordinates: readonly { col: number; row: number }[],\n size: number,\n origin: TileLayoutPoint,\n): Cell[] {\n return coordinates.map(({ col, row }) => ({\n center: {\n x: origin.x + (col + 0.5) * size,\n y: origin.y + (row + 0.5) * size,\n },\n corners: [\n [col, row],\n [col + 1, row],\n [col + 1, row + 1],\n [col, row + 1],\n ].map(([x, y]) => ({\n key: `${x},${y}`,\n point: { x: origin.x + x * size, y: origin.y + y * size },\n })),\n }));\n}\n\nfunction build(\n board: SeatBoardTopology,\n size: number,\n origin: TileLayoutPoint,\n) {\n if (board.layout === \"generic\")\n throw new Error(\"Generic boards have no tile layout.\");\n const visibleByTile = new Map<\n SeatTileRef,\n { cells: Cell[]; ids: SeatSpaceRef[] }\n >();\n const group = (\n spaces: readonly { tileRef: SeatTileRef; id: SeatSpaceRef }[],\n cells: readonly Cell[],\n ) => {\n spaces.forEach((space, index) => {\n const grouped = visibleByTile.get(space.tileRef) ?? {\n cells: [],\n ids: [],\n };\n grouped.cells.push(cells[index]);\n grouped.ids.push(space.id);\n visibleByTile.set(space.tileRef, grouped);\n });\n };\n if (board.layout === \"hex\") {\n const spaces = Object.values(board.spaces);\n group(spaces, hexCells(board.id, board.orientation, spaces, size, origin));\n } else {\n const spaces = Object.values(board.spaces);\n group(spaces, squareCells(spaces, size, origin));\n }\n const tiles = board.tiles.map((tile): TileLayoutGeometry => {\n const visible = visibleByTile.get(tile.ref);\n const footprint =\n tile.disclosure === \"concealed\"\n ? getPublicTileFootprint(tile.appearance, tile.placement)\n : null;\n let cells: Cell[];\n let anchor: TileLayoutPoint;\n if (board.layout === \"hex\" && tile.placement.layout === \"hex\") {\n const placement = tile.placement;\n cells =\n tile.disclosure === \"visible\"\n ? (visible?.cells ?? [])\n : footprint?.layout === \"hex\"\n ? hexCells(\n board.id,\n board.orientation,\n footprint.cells,\n size,\n origin,\n )\n : [];\n anchor = hexCells(\n board.id,\n board.orientation,\n [{ q: placement.q, r: placement.r }],\n size,\n origin,\n )[0].center;\n } else if (\n board.layout === \"square\" &&\n tile.placement.layout === \"square\"\n ) {\n const placement = tile.placement;\n cells =\n tile.disclosure === \"visible\"\n ? (visible?.cells ?? [])\n : footprint?.layout === \"square\"\n ? squareCells(footprint.cells, size, origin)\n : [];\n anchor = squareCells(\n [{ col: placement.col, row: placement.row }],\n size,\n origin,\n )[0].center;\n } else throw new Error(\"Tile placement layout does not match board.\");\n if (!cells.length)\n throw new Error(\"A projected tile requires a nonempty footprint.\");\n const center = {\n x: cells.reduce((sum, cell) => sum + cell.center.x, 0) / cells.length,\n y: cells.reduce((sum, cell) => sum + cell.center.y, 0) / cells.length,\n };\n return Object.freeze({\n ref: tile.ref,\n data: tile,\n spaceIds: Object.freeze(visible?.ids ?? []),\n outlines: outlines(cells),\n center: frozenPoint(center),\n anchor: frozenPoint(anchor),\n rotationDegrees:\n tile.placement.rotation * (board.layout === \"hex\" ? 60 : 90),\n });\n });\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const tile of tiles)\n for (const loop of tile.outlines)\n for (const point of loop) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n const viewBox = {\n x: tiles.length ? minX : 0,\n y: tiles.length ? minY : 0,\n width: tiles.length ? maxX - minX : 0,\n height: tiles.length ? maxY - minY : 0,\n };\n assertFinite([viewBox.x, viewBox.y, viewBox.width, viewBox.height]);\n return Object.freeze({\n tiles: Object.freeze(tiles),\n viewBox: Object.freeze(viewBox),\n });\n}\nconst cache = new WeakMap<\n SeatBoardTopology,\n { key: string; value: ReturnType<typeof build> }\n>();\n/** Admit projected topology and layout options before caching derived rendering geometry. */\nexport function createTileBoardLayout(\n board: SeatBoardTopology,\n size: number,\n suppliedOrigin: TileLayoutPoint = { x: 0, y: 0 },\n) {\n if (!Number.isFinite(size) || size <= 0)\n throw new Error(\"Tile cell size must be positive and finite.\");\n if (![suppliedOrigin.x, suppliedOrigin.y].every(Number.isFinite))\n throw new Error(\"Tile layout origin must be finite.\");\n const key = JSON.stringify([size, suppliedOrigin.x, suppliedOrigin.y]);\n const cached = cache.get(board);\n if (cached?.key === key) return cached.value;\n const value = build(\n immutableCopy(SeatBoardTopologySchema.parse(board)),\n size,\n {\n ...suppliedOrigin,\n },\n );\n cache.set(board, { key, value });\n return value;\n}\n","import type { SquareBoardTopology } from \"./board-topology.js\";\nimport { parseBoardElementId } from \"./domain/board-element.js\";\n\ntype Point = { readonly x: number; readonly y: number };\n\n/** Render admitted square topology without inferring boundary incidence from cells. */\nexport function createSquareBoardLayout(\n board: {\n readonly id: string;\n readonly spaces: Readonly<\n Record<\n string,\n { readonly id: string; readonly col: number; readonly row: number }\n >\n >;\n readonly vertices: SquareBoardTopology[\"vertices\"];\n readonly edges: SquareBoardTopology[\"edges\"];\n },\n size: number,\n origin: Point,\n) {\n if (!Number.isFinite(size) || size <= 0)\n throw new Error(\"Square cell size must be positive and finite.\");\n if (![origin.x, origin.y].every(Number.isFinite))\n throw new Error(\"Layout origin must be finite.\");\n const spaces = Object.values(board.spaces).map((space) => {\n const x = origin.x + space.col * size;\n const y = origin.y + space.row * size;\n return {\n id: space.id,\n center: { x: x + size / 2, y: y + size / 2 },\n corners: [\n { x, y },\n { x: x + size, y },\n { x: x + size, y: y + size },\n { x, y: y + size },\n ],\n };\n });\n const vertices = board.vertices.map((vertex) => {\n const identity = parseBoardElementId(vertex.id);\n if (\n !identity ||\n identity.kind !== \"vertex\" ||\n identity.layout !== \"square\" ||\n identity.boardId !== board.id\n )\n throw new Error(\n `Square vertex '${vertex.id}' does not belong to board '${board.id}'.`,\n );\n const [col, row] = identity.latticeId.split(\",\").map(Number);\n return {\n id: vertex.id,\n center: { x: origin.x + col * size, y: origin.y + row * size },\n };\n });\n const vertexPoints = new Map(\n vertices.map((vertex) => [vertex.id, vertex.center]),\n );\n const edges = board.edges.map((edge) => {\n const from = vertexPoints.get(edge.vertexIds[0]);\n const to = vertexPoints.get(edge.vertexIds[1]);\n if (!from || !to)\n throw new Error(`Square edge '${edge.id}' references a missing vertex.`);\n return { id: edge.id, from, to };\n });\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const space of spaces) {\n for (const point of space.corners) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n }\n const x = spaces.length ? minX : 0;\n const y = spaces.length ? minY : 0;\n return {\n viewBox: {\n x,\n y,\n width: spaces.length ? maxX - x : 0,\n height: spaces.length ? maxY - y : 0,\n },\n spaces,\n edges,\n vertices,\n pointToSpace(point: Point): string | undefined {\n const col = Math.floor((point.x - origin.x) / size);\n const row = Math.floor((point.y - origin.y) / size);\n return Object.values(board.spaces).find(\n (space) => space.col === col && space.row === row,\n )?.id;\n },\n };\n}\n","import {\n createTileBoardLayout,\n type TileLayoutGeometry,\n} from \"../../shared/tile-board-layout.js\";\nimport type { SeatBoardTopology } from \"../../shared/seat-topology-schema.js\";\ntype ProjectedBoardSpace = SeatBoardTopology[\"spaces\"][string];\nimport { createSquareBoardLayout } from \"../../shared/square-board-layout.js\";\nimport {\n runtimeFeatures,\n type RuntimeBoard,\n type RuntimeFeatureContext,\n type RuntimeFeatureSnapshot,\n type RuntimeCollection,\n} from \"../runtime-features.js\";\nimport type { RuntimeTargetOptions } from \"../targets.js\";\nimport type {\n BoardBase,\n BoardDataOf,\n IdOf,\n BoardCollection,\n BoardSpaceCollection,\n BoardSpace,\n CoreInstance,\n FeatureContext,\n TargetOptions,\n ActionProps,\n} from \"../model.js\";\nimport type { BoardEdge, BoardVertex } from \"../../shared/board-topology.js\";\nimport { requireLookup } from \"../../shared/lookup.js\";\nimport { AmbiguousTargetError } from \"../instance.js\";\nimport {\n createHexTopology,\n createHexTopologyCache,\n} from \"../../shared/hex-board.js\";\nimport type { Point } from \"./pointer-session.js\";\nimport type { ViewportTransform } from \"./pan-zoom.js\";\n\ninterface RuntimeSpace {\n readonly id: string;\n readonly data: ProjectedBoardSpace;\n readonly board: RuntimeBoard;\n getIsEligible(): boolean;\n getIsSelectable(): boolean;\n getIsSelected(): boolean;\n getSelectHandler(options?: RuntimeTargetOptions): () => void;\n getTargetProps(options?: RuntimeTargetOptions): ActionProps;\n}\ninterface RuntimeLayoutTarget {\n readonly id: string;\n getIsEligible(): boolean;\n getIsSelectable(): boolean;\n getIsSelected(): boolean;\n getSelectHandler(options?: RuntimeTargetOptions): () => void;\n getTargetProps(options?: RuntimeTargetOptions): ActionProps;\n}\ninterface RuntimeLayout {\n readonly viewBox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n getSpaces(): readonly (RuntimeSpace & {\n readonly center: Point;\n points(): readonly Point[];\n readonly transform: string;\n })[];\n getEdges(): readonly (RuntimeLayoutTarget & {\n readonly data: BoardEdge | undefined;\n readonly center: Point;\n readonly line: readonly [Point, Point];\n })[];\n getVertices(): readonly (RuntimeLayoutTarget & {\n readonly data: BoardVertex | undefined;\n readonly center: Point;\n })[];\n getTiles(): readonly TileLayoutGeometry[];\n pointToSpace(x: number, y: number): string | undefined;\n}\ntype TargetKind = \"space\" | \"edge\" | \"vertex\";\nexport interface BoardLayoutOptions {\n /** Hex radius, or square cell width and height. */\n readonly hexSize: number;\n readonly origin?: Point;\n readonly viewport?: ViewportTransform;\n}\ninterface Geometry {\n readonly viewBox: { x: number; y: number; width: number; height: number };\n readonly spaces: readonly {\n id: string;\n center: Point;\n corners: readonly Point[];\n }[];\n readonly edges: readonly { id: string; from: Point; to: Point }[];\n readonly vertices: readonly { id: string; center: Point }[];\n pointToSpace(point: Point): string | undefined;\n}\n\n/** Semantic board spaces and captured selection, with optional spatial geometry. */\nfunction createRuntimeBoardFeature(context: RuntimeFeatureContext) {\n const game = context.game;\n const captures = new WeakMap<\n object,\n {\n model: RuntimeFeatureSnapshot;\n source: ReturnType<typeof game.getOptions>[\"source\"];\n geometry?: ReturnType<typeof createHexTopology>;\n }\n >();\n const cachedHexTopology = createHexTopologyCache();\n let cached:\n | {\n view: unknown;\n boards: ReturnType<RuntimeFeatureContext[\"getBoards\"]>;\n interactions: RuntimeFeatureSnapshot[\"interactions\"];\n source: ReturnType<typeof game.getOptions>[\"source\"];\n collection: RuntimeCollection<RuntimeBoard>;\n }\n | undefined;\n function collection(): RuntimeCollection<RuntimeBoard> {\n const model = game.getSnapshot();\n const source = game.getOptions().source;\n const projectedBoards = context.getBoards();\n if (\n cached &&\n cached.view === model.view &&\n cached.boards === projectedBoards &&\n cached.interactions === model.interactions &&\n cached.source === source\n )\n return cached.collection;\n const boards = Object.values(projectedBoards).map((data) => {\n const board = context.createBoard(data);\n const geometry =\n data.layout === \"hex\"\n ? cachedHexTopology({\n id: data.id,\n orientation: data.orientation,\n spaces: Object.values(data.spaces),\n })\n : undefined;\n captures.set(board, { model, source, geometry });\n return board;\n });\n const byId = new Map(boards.map((board) => [board.id, board]));\n const result: RuntimeCollection<RuntimeBoard> = Object.freeze({\n get: (id: string) => requireLookup(byId.get(id), \"Board\", id),\n find: (id: string) => byId.get(id),\n getAll: () => Object.freeze(boards),\n });\n cached = {\n view: model.view,\n boards: projectedBoards,\n interactions: model.interactions,\n source,\n collection: result,\n };\n return result;\n }\n function targetsFor(owner: RuntimeBoard) {\n const board = owner.data;\n const captured = captures.get(owner)!;\n function matchingTargets(\n model: RuntimeFeatureSnapshot,\n kind: TargetKind,\n id: string,\n ) {\n return model.interactions.list().flatMap((interaction) =>\n interaction\n .getInputs()\n .filter((input) => {\n const domain = input.getDomain();\n return (\n domain.type === \"boardTarget\" &&\n domain.targetKind === kind &&\n (domain.valueKind === \"board-space\"\n ? board.scope === \"perPlayer\" &&\n domain.boardBaseId === board.baseId\n : domain.boardId === board.id)\n );\n })\n .map((input) => {\n const domain = input.getDomain();\n return {\n interaction,\n input,\n value:\n domain.type === \"boardTarget\" &&\n domain.valueKind === \"board-space\"\n ? Object.freeze({\n boardId: board.id,\n spaceId: id,\n })\n : id,\n };\n }),\n );\n }\n function target(kind: TargetKind, id: string) {\n const matches = matchingTargets(captured.model, kind, id);\n const eligible = matches.some(({ input, value }) =>\n input.getIsEligible(value),\n );\n const selected = matches.some(({ input, value }) =>\n input.getIsSelected(value),\n );\n const selectable = matches.some(\n ({ input, value }) => !input.getTargetProps(value).disabled,\n );\n function select(options?: RuntimeTargetOptions) {\n if (\n game.getOptions().source !== captured.source ||\n game.snapshot?.me !== captured.model.snapshot?.me\n )\n return;\n const matching = matchingTargets(game.getSnapshot(), kind, id).filter(\n ({ interaction, input, value }) =>\n (!options?.interaction ||\n options.interaction === interaction.key) &&\n (!options?.input || options.input === input.key) &&\n !input.getTargetProps(value).disabled,\n );\n if (!matching.length) return;\n if (matching.length > 1) throw new AmbiguousTargetError(id);\n const domain = matching[0].input.getDomain();\n if (domain.type !== \"boardTarget\") return;\n const value = matching[0].value;\n const target =\n domain.valueKind === \"board-space\" && typeof value !== \"string\"\n ? { kind: \"space\" as const, valueKind: domain.valueKind, value }\n : {\n kind,\n valueKind: \"board-id\" as const,\n value: id,\n boardId: board.id,\n };\n context.routeTarget(target, {\n interaction: matching[0].interaction.key,\n input: matching[0].input.key,\n });\n }\n return {\n id,\n getIsEligible: () => eligible,\n getIsSelectable: () => selectable,\n getIsSelected: () => selected,\n getSelectHandler: (options?: RuntimeTargetOptions) => () =>\n select(options),\n getTargetProps(options?: RuntimeTargetOptions) {\n const candidates = matches.filter(\n ({ interaction, input, value }) =>\n (!options?.interaction ||\n interaction.key === options.interaction) &&\n (!options?.input || options.input === input.key) &&\n !input.getTargetProps(value).disabled,\n );\n const only = candidates.length === 1 ? candidates[0] : undefined;\n return {\n type: \"button\" as const,\n disabled: candidates.length === 0,\n \"data-action\": \"select\",\n \"data-value\":\n only && typeof only.value !== \"string\"\n ? JSON.stringify(only.value)\n : id,\n \"data-board\": board.id,\n \"data-interaction\": options?.interaction ?? only?.interaction.key,\n \"data-input\": only?.input.key,\n \"data-eligible\": eligible,\n \"data-selected\": selected,\n \"data-disabled\": candidates.length === 0,\n onClick: () => select(options),\n };\n },\n };\n }\n return target;\n }\n const spaceCollections = new WeakMap<\n object,\n RuntimeCollection<RuntimeSpace>\n >();\n function spacesFor(owner: RuntimeBoard): RuntimeCollection<RuntimeSpace> {\n const cached = spaceCollections.get(owner);\n if (cached) return cached;\n const target = targetsFor(owner);\n const data = owner.data;\n const values = Object.freeze(\n Object.values(data.spaces).map((space) =>\n Object.freeze({\n ...target(\"space\", space.id),\n data: space,\n board: owner,\n }),\n ),\n );\n const byId = new Map(values.map((space) => [space.id, space]));\n const spaces = Object.freeze({\n get: (id: string) =>\n requireLookup(byId.get(id), `Space on board ${owner.id}`, id),\n find: (id: string) => byId.get(id),\n getAll: () => values,\n });\n spaceCollections.set(owner, spaces);\n return spaces;\n }\n return {\n root: {\n get boards() {\n return collection();\n },\n },\n board: {\n get spaces(): RuntimeCollection<RuntimeSpace> {\n return spacesFor(this);\n },\n getLayout(\n this: RuntimeBoard,\n options: BoardLayoutOptions,\n ): RuntimeLayout {\n const board = this.data;\n if (board.layout === \"generic\")\n throw new Error(\n `Board '${board.id}' has no spatial geometry; use board.spaces for semantic selection.`,\n );\n const {\n hexSize,\n origin: suppliedOrigin = { x: 0, y: 0 },\n viewport: suppliedViewport = { x: 0, y: 0, scale: 1 },\n } = options;\n const origin = { ...suppliedOrigin };\n const viewport = { ...suppliedViewport };\n if (!Number.isFinite(hexSize) || hexSize <= 0)\n throw new Error(\"hexSize must be positive and finite.\");\n if (\n ![origin.x, origin.y, viewport.x, viewport.y, viewport.scale].every(\n Number.isFinite,\n ) ||\n viewport.scale <= 0\n )\n throw new Error(\n \"Layout transform must be finite with positive scale.\",\n );\n const captured = captures.get(this)!;\n const geometry: Geometry =\n board.layout === \"hex\"\n ? captured.geometry!.getLayout({ hexSize, origin })\n : createSquareBoardLayout(board, hexSize, origin);\n const point = (value: Point): Point => {\n const transformed = {\n x: value.x * viewport.scale + viewport.x,\n y: value.y * viewport.scale + viewport.y,\n };\n if (![transformed.x, transformed.y].every(Number.isFinite))\n throw new Error(\"Derived layout transform must be finite.\");\n return Object.freeze(transformed);\n };\n const tileGeometry = createTileBoardLayout(board, hexSize, origin);\n const tiles = Object.freeze(\n tileGeometry.tiles.map((tile) =>\n Object.freeze({\n ...tile,\n center: point(tile.center),\n anchor: point(tile.anchor),\n outlines: Object.freeze(\n tile.outlines.map((loop) => Object.freeze(loop.map(point))),\n ),\n }),\n ),\n );\n const target = targetsFor(this);\n const semanticSpaces = spacesFor(this);\n const spaces = Object.freeze(\n geometry.spaces.map((space) => {\n const corners = Object.freeze(space.corners.map(point));\n const center = point(space.center);\n return Object.freeze({\n ...semanticSpaces.get(space.id),\n center,\n points: () => corners,\n transform: `translate(${center.x} ${center.y})`,\n });\n }),\n );\n const edges = Object.freeze(\n geometry.edges.map((edge) =>\n Object.freeze({\n ...target(\"edge\", edge.id),\n data: board.edges.find((data) => data.id === edge.id),\n center: point({\n x: (edge.from.x + edge.to.x) / 2,\n y: (edge.from.y + edge.to.y) / 2,\n }),\n line: Object.freeze([point(edge.from), point(edge.to)] as const),\n }),\n ),\n );\n const vertices = Object.freeze(\n geometry.vertices.map((vertex) =>\n Object.freeze({\n ...target(\"vertex\", vertex.id),\n data: board.vertices.find((data) => data.id === vertex.id),\n center: point(vertex.center),\n }),\n ),\n );\n return Object.freeze({\n viewBox: tileGeometry.viewBox,\n getTiles: () => tiles,\n getSpaces: () => spaces,\n getEdges: () => edges,\n getVertices: () => vertices,\n pointToSpace(x: number, y: number) {\n return geometry.pointToSpace({\n x: (x - viewport.x) / viewport.scale,\n y: (y - viewport.y) / viewport.scale,\n });\n },\n });\n },\n } satisfies ThisType<RuntimeBoard>,\n };\n}\n\ntype LayoutTarget<G, Value> = Omit<\n Value,\n \"getSelectHandler\" | \"getTargetProps\"\n> & {\n getSelectHandler(options?: TargetOptions<G>): () => void;\n getTargetProps(options?: TargetOptions<G>): ActionProps;\n};\ntype LayoutElementData<G, Kind extends \"edges\" | \"vertices\"> =\n BoardDataOf<G, IdOf<G, \"boardId\">> extends infer Topology\n ? Topology extends Record<Kind, readonly (infer Element)[]>\n ? Element\n : never\n : never;\ntype LayoutElement<G, Kind extends \"edges\" | \"vertices\", Value> = LayoutTarget<\n G,\n Omit<Value, \"data\" | \"id\">\n> & {\n readonly id: LayoutElementData<G, Kind> extends { readonly id: infer Id }\n ? Id\n : never;\n readonly data: LayoutElementData<G, Kind> | undefined;\n};\n/** Seat tile presentation retains its visible/concealed data union without another discriminator. */\nexport type BoardLayoutTile<G> =\n BoardDataOf<G, IdOf<G, \"boardId\">> extends infer Board\n ? Board extends { readonly tiles: readonly (infer Tile)[] }\n ? Omit<TileLayoutGeometry, \"data\"> & { readonly data: Tile }\n : never\n : never;\n\ntype BoardLayout<G> = Omit<\n RuntimeLayout,\n \"getSpaces\" | \"getEdges\" | \"getVertices\" | \"getTiles\"\n> & {\n getTiles(): readonly BoardLayoutTile<G>[];\n getSpaces(): readonly (BoardSpace<G> & {\n readonly center: Point;\n points(): readonly Point[];\n readonly transform: string;\n })[];\n getEdges(): readonly LayoutElement<\n G,\n \"edges\",\n ReturnType<RuntimeLayout[\"getEdges\"]>[number]\n >[];\n getVertices(): readonly LayoutElement<\n G,\n \"vertices\",\n ReturnType<RuntimeLayout[\"getVertices\"]>[number]\n >[];\n};\nexport interface BoardFeature<G> {\n readonly root: { readonly boards: BoardCollection<G> };\n readonly board: {\n readonly spaces: BoardSpaceCollection<G>;\n getLayout(this: BoardBase<G>, options: BoardLayoutOptions): BoardLayout<G>;\n };\n}\n/** Bind one runtime implementation to the same game/source contract as the instance. */\nexport function boardFeature<G>(\n _game: CoreInstance<G>,\n context: FeatureContext<G>,\n): BoardFeature<G> {\n // Game-binding boundary: source identities and installed hooks belong to G.\n // Proven by headless-features/inline-boards type tests and board behavior tests.\n // eslint-disable-next-line no-restricted-syntax -- Instance composition binds these runtime source identities and feature hooks to the same game G.\n return createRuntimeBoardFeature(\n context[runtimeFeatures],\n ) as unknown as BoardFeature<G>;\n}\n","import {\n runtimeFeatures,\n type RuntimeFeatureContext,\n} from \"../runtime-features.js\";\nimport type { RuntimeDropTarget, RuntimeTargetOptions } from \"../targets.js\";\nimport type { DropTarget, TargetOptions } from \"../targets.js\";\nexport type { DropTarget } from \"../targets.js\";\nimport { isSameDropTarget } from \"../drop-targets.js\";\nimport type { CoreInstance, FeatureContext, SeatCardId } from \"../model.js\";\nexport interface DragState<G> {\n readonly cardId: SeatCardId<G>;\n readonly target: DropTarget<G> | null;\n}\n\nexport interface DragController<G> {\n readonly active: DragState<G> | null;\n getCanDrag(cardId: SeatCardId<G>, options?: TargetOptions<G>): boolean;\n begin(cardId: SeatCardId<G>, options?: TargetOptions<G>): boolean;\n getDropTargets(): readonly DropTarget<G>[];\n setDropTarget(target: DropTarget<G> | null): void;\n drop(): void;\n cancel(): void;\n}\n\ninterface RuntimeDragState {\n readonly cardId: string;\n readonly target: RuntimeDropTarget | null;\n}\ninterface RuntimeDragController {\n readonly active: RuntimeDragState | null;\n getCanDrag(cardId: string, options?: RuntimeTargetOptions): boolean;\n begin(cardId: string, options?: RuntimeTargetOptions): boolean;\n getDropTargets(): readonly RuntimeDropTarget[];\n setDropTarget(target: RuntimeDropTarget | null): void;\n drop(): void;\n cancel(): void;\n}\nfunction createRuntimeDragFeature(context: RuntimeFeatureContext) {\n const game = context.game;\n let active: RuntimeDragState | null = null;\n let selection: RuntimeTargetOptions | undefined;\n let source = game.getOptions().source;\n let seat = game.snapshot?.me;\n let disposed = false;\n let version = game.snapshot?.version;\n let lastInteractions = game.interactions;\n let lastCards = game.cards;\n let branch = snapshot();\n function update(next: RuntimeDragState | null) {\n if (disposed) return;\n active = next === null ? null : Object.freeze(next);\n branch = snapshot();\n context.invalidate();\n }\n function targets(\n cardId = active?.cardId,\n selected = selection,\n ): readonly RuntimeDropTarget[] {\n if (!cardId || game.connection !== \"ready\") return [];\n const options = selected;\n const resolved = (game.cards.find(cardId)?.getInteractions() ?? []).flatMap(\n (candidate) => {\n if (\n !candidate.getIsAvailable() ||\n (options?.interaction && candidate.key !== options.interaction)\n )\n return [];\n const inputs = candidate.getInputs();\n const cardInputs = inputs.filter(\n (input) =>\n input.getDomain().type === \"cardTarget\" &&\n (!options?.input || input.key === options.input) &&\n input.getIsEligible(cardId),\n );\n // Without a board input, the card lands on an area that runs the interaction.\n if (!inputs.some((input) => input.getDomain().type === \"boardTarget\"))\n return cardInputs.map((cardInput): RuntimeDropTarget =>\n Object.freeze({\n kind: \"interaction\",\n interactionKey: candidate.key,\n cardInputKey: cardInput.key,\n }),\n );\n return cardInputs.flatMap((cardInput) =>\n inputs.flatMap((input): RuntimeDropTarget[] => {\n const domain = input.getDomain();\n if (domain.type !== \"boardTarget\") return [];\n const route = {\n interactionKey: candidate.key,\n cardInputKey: cardInput.key,\n inputKey: input.key,\n };\n if (domain.valueKind === \"board-space\")\n return domain.eligibleTargets\n .filter((value) => !input.getTargetProps(value).disabled)\n .map((value) =>\n Object.freeze({\n kind: \"space\",\n valueKind: domain.valueKind,\n value,\n ...route,\n }),\n );\n return domain.eligibleTargets\n .filter((value) => !input.getTargetProps(value).disabled)\n .map((value) =>\n Object.freeze({\n kind: domain.targetKind,\n valueKind: domain.valueKind,\n value,\n boardId: domain.boardId,\n ...route,\n }),\n );\n }),\n );\n },\n );\n return resolved;\n }\n function cancel() {\n if (active) update(null);\n }\n function snapshot(): RuntimeDragController {\n const captured = active;\n const dropTargets = Object.freeze(targets());\n return Object.freeze<RuntimeDragController>({\n active: captured,\n getCanDrag: (cardId, options) =>\n !disposed && targets(cardId, options).length > 0,\n begin(cardId, options) {\n if (disposed || !targets(cardId, options).length) return false;\n selection = options;\n update({ cardId, target: null });\n return true;\n },\n getDropTargets: () => dropTargets,\n setDropTarget(target: RuntimeDropTarget | null) {\n if (!active || disposed) return;\n if (\n target &&\n !targets().some((candidate) => isSameDropTarget(candidate, target))\n ) {\n update({ ...active, target: null });\n return;\n }\n update({ ...active, target });\n },\n drop() {\n const finished = active;\n const eligible =\n finished?.target &&\n targets().some((target) =>\n isSameDropTarget(target, finished.target!),\n );\n cancel();\n if (!disposed && finished?.target && eligible)\n context.routeCardDrop(finished.cardId, finished.target);\n },\n cancel,\n });\n }\n const unsubscribe = game.subscribe(() => {\n const nextSource = game.getOptions().source;\n const nextSeat = game.snapshot?.me;\n const nextVersion = game.snapshot?.version;\n if (\n nextSource !== source ||\n nextSeat !== seat ||\n nextVersion !== version ||\n game.connection !== \"ready\"\n ) {\n source = nextSource;\n seat = nextSeat;\n version = nextVersion;\n cancel();\n }\n });\n return {\n root: {\n get drag() {\n if (\n lastInteractions !== game.interactions ||\n lastCards !== game.cards\n ) {\n lastInteractions = game.interactions;\n lastCards = game.cards;\n branch = snapshot();\n }\n return branch;\n },\n },\n dispose() {\n unsubscribe();\n cancel();\n disposed = true;\n },\n };\n}\n\n/**\n * Semantic card/drop routing. A card lands on a board destination when its\n * interaction has a board input, otherwise on an area that runs the\n * interaction. Gestures, hit-testing and feedback belong to /react.\n */\nexport function dragFeature<G>(\n _game: CoreInstance<G>,\n context: FeatureContext<G>,\n): { readonly root: { readonly drag: DragController<G> }; dispose(): void } {\n // Game-binding boundary: routes come from this instance's admitted descriptors.\n // The runtime implementation revalidates both inputs atomically on drop.\n return createRuntimeDragFeature(context[runtimeFeatures]) as {\n readonly root: { readonly drag: DragController<G> };\n dispose(): void;\n };\n}\n","/** Native pointer surface; importing a feature never requires browser globals. */\nexport interface PointerSurface {\n setPointerCapture(pointerId: number): void;\n hasPointerCapture(pointerId: number): boolean;\n releasePointerCapture(pointerId: number): void;\n}\n\nexport interface PointerInput {\n readonly pointerId: number;\n readonly button: number;\n readonly clientX: number;\n readonly clientY: number;\n readonly currentTarget: PointerSurface;\n preventDefault(): void;\n}\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\nexport interface PointerMove {\n readonly origin: Point;\n readonly point: Point;\n readonly delta: Point;\n}\n\n/** One captured gesture. Pointer cancellation and disposal never commit a drop. */\nexport function createPointerSession(callbacks: {\n move(value: PointerMove): void;\n end(value: PointerMove): void;\n cancel(): void;\n}) {\n let disposed = false;\n let active:\n | { id: number; surface: PointerSurface; origin: Point; point: Point }\n | undefined;\n\n function value(): PointerMove {\n const { origin, point } = active!;\n return {\n origin,\n point,\n delta: { x: point.x - origin.x, y: point.y - origin.y },\n };\n }\n\n function release() {\n const previous = active;\n active = undefined;\n if (previous?.surface.hasPointerCapture(previous.id)) {\n previous.surface.releasePointerCapture(previous.id);\n }\n }\n\n function cancel() {\n if (!active) return;\n release();\n callbacks.cancel();\n }\n\n return {\n start(event: PointerInput): boolean {\n if (disposed || active || event.button !== 0) return false;\n event.currentTarget.setPointerCapture(event.pointerId);\n const point = { x: event.clientX, y: event.clientY };\n active = {\n id: event.pointerId,\n surface: event.currentTarget,\n origin: point,\n point,\n };\n event.preventDefault();\n return true;\n },\n move(event: PointerInput) {\n if (event.pointerId !== active?.id) return;\n active.point = { x: event.clientX, y: event.clientY };\n event.preventDefault();\n callbacks.move(value());\n },\n end(event: PointerInput) {\n if (event.pointerId !== active?.id) return;\n active.point = { x: event.clientX, y: event.clientY };\n const result = value();\n release();\n callbacks.end(result);\n },\n cancel(event?: Pick<PointerInput, \"pointerId\">) {\n if (event && event.pointerId !== active?.id) return;\n cancel();\n },\n dispose() {\n disposed = true;\n cancel();\n },\n };\n}\n","import type { CoreInstance, FeatureContext } from \"../model.js\";\nimport {\n createPointerSession,\n type PointerInput,\n type PointerSurface,\n} from \"./pointer-session.js\";\n\nexport interface ViewportTransform {\n readonly x: number;\n readonly y: number;\n readonly scale: number;\n}\nexport interface ViewportSurface extends PointerSurface {\n getBoundingClientRect(): {\n readonly left: number;\n readonly top: number;\n readonly height: number;\n };\n}\nexport interface WheelInput {\n readonly clientX: number;\n readonly clientY: number;\n readonly deltaY: number;\n readonly deltaMode: number;\n readonly currentTarget: ViewportSurface;\n preventDefault(): void;\n}\nexport interface PanZoomOptions {\n readonly initial?: ViewportTransform;\n readonly minScale?: number;\n readonly maxScale?: number;\n}\n\n/** Native pointer panning and wheel zoom around the cursor. No document listeners. */\nexport function panZoomFeature<G>(\n game: CoreInstance<G>,\n context: FeatureContext<G>,\n options: PanZoomOptions = {},\n) {\n const minScale = options.minScale ?? 0.25;\n const maxScale = options.maxScale ?? 4;\n if (\n !Number.isFinite(minScale) ||\n !Number.isFinite(maxScale) ||\n minScale <= 0 ||\n maxScale < minScale\n ) {\n throw new Error(\n \"Viewport scale limits must be positive, finite, and ordered.\",\n );\n }\n const initial = options.initial ?? { x: 0, y: 0, scale: 1 };\n let disposed = false;\n let source = game.getOptions().source;\n let seat = game.snapshot?.me;\n let dragOrigin = initial;\n let transform = admit(initial);\n let branch = snapshot();\n\n function admit(value: ViewportTransform): ViewportTransform {\n if (\n ![value.x, value.y, value.scale].every(Number.isFinite) ||\n value.scale <= 0\n ) {\n throw new Error(\n \"Viewport transform must have finite coordinates and positive scale.\",\n );\n }\n return Object.freeze({\n x: value.x,\n y: value.y,\n scale: Math.min(maxScale, Math.max(minScale, value.scale)),\n });\n }\n function update(value: ViewportTransform) {\n if (disposed) return;\n const next = admit(value);\n if (\n next.x === transform.x &&\n next.y === transform.y &&\n next.scale === transform.scale\n )\n return;\n transform = next;\n branch = snapshot();\n context.invalidate();\n }\n const pointer = createPointerSession({\n move: ({ delta }) =>\n update({\n ...dragOrigin,\n x: dragOrigin.x + delta.x,\n y: dragOrigin.y + delta.y,\n }),\n end: ({ delta }) =>\n update({\n ...dragOrigin,\n x: dragOrigin.x + delta.x,\n y: dragOrigin.y + delta.y,\n }),\n cancel() {},\n });\n function props() {\n return {\n style: { touchAction: \"none\" as const },\n onPointerDown(event: PointerInput) {\n if (pointer.start(event)) dragOrigin = transform;\n },\n onPointerMove: pointer.move,\n onPointerUp: pointer.end,\n onPointerCancel: pointer.cancel,\n onLostPointerCapture: pointer.cancel,\n onWheel(event: WheelInput) {\n if (disposed) return;\n event.preventDefault();\n const rect = event.currentTarget.getBoundingClientRect();\n const unit =\n event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? rect.height : 1;\n const scale = Math.min(\n maxScale,\n Math.max(\n minScale,\n transform.scale * Math.exp(-event.deltaY * unit * 0.002),\n ),\n );\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n const ratio = scale / transform.scale;\n update({\n x: x - (x - transform.x) * ratio,\n y: y - (y - transform.y) * ratio,\n scale,\n });\n },\n };\n }\n function snapshot() {\n const captured = transform;\n return Object.freeze({\n transform: captured,\n getTransform: () => captured,\n getProps: props,\n setTransform: update,\n reset: () => {\n pointer.cancel();\n update(initial);\n },\n });\n }\n const unsubscribe = game.subscribe(() => {\n const nextSource = game.getOptions().source;\n const nextSeat = game.snapshot?.me;\n if (nextSource !== source || nextSeat !== seat) {\n source = nextSource;\n seat = nextSeat;\n pointer.cancel();\n update(initial);\n }\n });\n return {\n root: {\n get viewport() {\n return branch;\n },\n },\n dispose() {\n disposed = true;\n unsubscribe();\n pointer.dispose();\n },\n };\n}\n","import { isHiddenCardId as isHidden } from \"../../shared/domain/cards.js\";\nimport type { CoreInstance, IdOf, SeatCardId, ZoneHostId } from \"../model.js\";\nimport type { SourceSnapshot } from \"../sources/types.js\";\n\n/**\n * Where a card that arrived in its zone with the current frame was on the\n * previous one: another zone, or the private zones of the player who moved.\n * `hidden` says whether the seat saw only the card's back there.\n */\nexport type CardOrigin<G> =\n | {\n readonly zone: IdOf<G, \"zoneId\">;\n readonly hostId: ZoneHostId<G>;\n readonly hidden: boolean;\n }\n | { readonly player: IdOf<G, \"playerId\">; readonly hidden: true };\n\ntype RuntimeOrigin =\n | {\n readonly zone: string;\n readonly hostId?: string;\n readonly hidden: boolean;\n }\n | { readonly player: string; readonly hidden: true };\ntype NestedZones = SourceSnapshot[\"frame\"][\"zones\"];\ntype Zones = Record<\n string,\n import(\"../../shared/protocol/frame\").ZoneHandlesSnapshot\n>;\nconst flatten = (zones: NestedZones): Zones =>\n Object.fromEntries(\n Object.entries(zones).flatMap(([zoneId, hosts]) =>\n Object.entries(hosts).map(([hostId, zone]) => [\n JSON.stringify([zoneId, hostId]),\n zone,\n ]),\n ),\n );\n\nconst hiddenCount = (zones: Zones, zone: string) =>\n zones[zone]?.cardIds.filter(isHidden).length ?? 0;\n\nfunction singleOrigin(\n departures: readonly {\n readonly zone: string;\n readonly hostId?: string;\n readonly hidden: boolean;\n }[],\n count: number,\n) {\n const origin = departures[0];\n return origin &&\n departures.length >= count &&\n departures.every(\n (card) => card.zone === origin.zone && card.hidden === origin.hidden,\n )\n ? Object.freeze(origin)\n : null;\n}\n\n/**\n * Visible ids are card identities, so a visible card is followed between\n * zones. Hidden ids are positions, so only their net counts are compared.\n * An inferred origin requires one compatible source with enough departures;\n * existing hidden cards make the arriving positions ambiguous. Unexplained\n * arrivals can come from the sole mover's private zones, which the seat's\n * frame does not list. Ambiguous origins are omitted.\n */\nexport function findCardOrigins(\n previousNested: NestedZones,\n nextNested: NestedZones,\n mover: string | null,\n): ReadonlyMap<string, RuntimeOrigin> {\n const previous = flatten(previousNested);\n const next = flatten(nextNested);\n const shownBefore = new Map<string, string>();\n for (const [zone, { cardIds }] of Object.entries(previous))\n for (const cardId of cardIds)\n if (!isHidden(cardId)) shownBefore.set(cardId, zone);\n const shownNow = new Set(\n Object.values(next).flatMap(({ cardIds }) =>\n cardIds.filter((cardId) => !isHidden(cardId)),\n ),\n );\n let left = Object.entries(previous).flatMap(([zone, { cardIds }]) => [\n ...cardIds\n .filter((cardId) => !isHidden(cardId) && !shownNow.has(cardId))\n .map(() => ({ zone, hidden: false })),\n ...Array.from(\n {\n length: Math.max(\n 0,\n hiddenCount(previous, zone) - hiddenCount(next, zone),\n ),\n },\n () => ({ zone, hidden: true }),\n ),\n ]);\n const origins = new Map<string, RuntimeOrigin>();\n const shownArrivals: string[] = [];\n const hiddenArrivals: (string | null)[] = [];\n for (const [zone, { cardIds }] of Object.entries(next)) {\n for (const cardId of cardIds) {\n if (isHidden(cardId)) continue;\n const from = shownBefore.get(cardId);\n if (from === undefined) shownArrivals.push(cardId);\n else if (from !== zone)\n origins.set(cardId, Object.freeze({ zone: from, hidden: false }));\n }\n const hidden = cardIds.filter(isHidden);\n const before = hiddenCount(previous, zone);\n // Count ambiguous arrivals too, so another destination cannot claim their source.\n hiddenArrivals.push(\n ...Array.from(\n { length: Math.max(0, hidden.length - before) },\n (_, index) => (before === 0 ? hidden[index] : null),\n ),\n );\n }\n // Concealing a visible card can replace a hidden departure without changing\n // the hidden count. Net counts cannot resolve those simultaneous movements.\n if (\n left.some(\n (card) =>\n !card.hidden &&\n hiddenCount(previous, card.zone) > 0 &&\n hiddenCount(next, card.zone) > 0,\n )\n )\n return decodedOrigins(origins);\n const hiddenLeft = left.filter((card) => card.hidden);\n if (shownArrivals.length) {\n const origin = singleOrigin(hiddenLeft, shownArrivals.length);\n if (origin) {\n for (const cardId of shownArrivals) origins.set(cardId, origin);\n left = [\n ...left.filter((card) => !card.hidden),\n ...hiddenLeft.slice(shownArrivals.length),\n ];\n } else if (hiddenLeft.length) {\n // Which departures the shown cards consumed is also ambiguous.\n return decodedOrigins(origins);\n } else if (mover !== null) {\n const origin = Object.freeze({ player: mover, hidden: true as const });\n for (const cardId of shownArrivals) origins.set(cardId, origin);\n }\n }\n const hiddenOrigin =\n singleOrigin(left, hiddenArrivals.length) ??\n (left.length === 0 && mover !== null\n ? Object.freeze({ player: mover, hidden: true as const })\n : null);\n if (hiddenOrigin) {\n for (const cardId of hiddenArrivals)\n if (cardId !== null) origins.set(cardId, hiddenOrigin);\n }\n return decodedOrigins(origins);\n}\n\n/** The sole active player, when it is another seat. */\nfunction moverOf(snapshot: SourceSnapshot) {\n const active = snapshot.frame.flow.activePlayers;\n return active.length === 1 && active[0] !== snapshot.me ? active[0] : null;\n}\n\n/**\n * Adds `card.getOrigin()`: where a card that arrived in its zone with the\n * current frame came from, or null. Origins last until the next frame and\n * reset when the seat or source changes. Hidden origins are inferred from\n * net counts; ambiguous sources and arriving positions return null.\n */\nexport function originsFeature<G>(game: CoreInstance<G>) {\n type Origins = ReadonlyMap<SeatCardId<G>, CardOrigin<G>>;\n let frame = game.snapshot;\n let source = game.getOptions().source;\n let origins: Origins = new Map();\n function sync() {\n const next = game.snapshot;\n const nextSource = game.getOptions().source;\n if (\n next?.version === frame?.version &&\n next?.me === frame?.me &&\n nextSource === source\n )\n return;\n // Game-binding boundary: card, zone and player ids come from this instance's frames.\n origins =\n frame &&\n next &&\n next.me === frame.me &&\n nextSource === source &&\n next.version === frame.version + 1\n ? (findCardOrigins(\n frame.frame.zones,\n next.frame.zones,\n moverOf(frame),\n ) as Origins)\n : new Map();\n frame = next;\n source = nextSource;\n }\n // Also read lazily, so a reader notified before this listener sees the new frame's origins.\n const unsubscribe = game.subscribe(sync);\n return {\n card: {\n getOrigin(this: { readonly id: SeatCardId<G> }): CardOrigin<G> | null {\n sync();\n return origins.get(this.id) ?? null;\n },\n },\n dispose: unsubscribe,\n };\n}\n\nfunction decodedOrigins(\n origins: ReadonlyMap<string, RuntimeOrigin>,\n): ReadonlyMap<string, RuntimeOrigin> {\n return new Map<string, RuntimeOrigin>(\n [...origins].map(([id, origin]) => {\n if (!(\"zone\" in origin)) return [id, origin];\n const [zone, hostId] = JSON.parse(origin.zone) as [string, string];\n return [id, Object.freeze({ ...origin, zone, hostId })];\n }),\n );\n}\n","const RADIANS = Math.PI / 180;\n\nexport interface FanOptions {\n readonly count: number;\n /** The width available to the fan, in pixels. */\n readonly width: number;\n readonly cardWidth: number;\n readonly cardHeight: number;\n /** Distance between neighbouring cards along the arc when there is room. Default: 60% of the card width. */\n readonly step?: number;\n /** The smallest visible slice of a covered card. Default: 25% of the card width. */\n readonly minStep?: number;\n /** Degrees between neighbouring cards. Default 5; 0 lays a straight row. */\n readonly angle?: number;\n /** The most degrees between the two end cards. Default 30. */\n readonly maxSpread?: number;\n}\n\n/** A card's CSS `translate` from the fan's top-left corner, and its `rotate` about its own centre. */\nexport interface FanCard {\n readonly x: number;\n readonly y: number;\n /** Degrees clockwise. */\n readonly rotate: number;\n}\n\nexport interface FanLayout {\n readonly cards: readonly FanCard[];\n /** The fan's bounding box. It is wider than the available width only when the cards are at `minStep`. */\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Lays cards on a circular arc. The spread grows with the card count up to\n * `maxSpread`; the step shrinks continuously to fit the width, down to\n * `minStep`, past which the fan overflows and the hand should scroll.\n */\nexport function fanLayout({\n count,\n width,\n cardWidth,\n cardHeight,\n step = cardWidth * 0.6,\n minStep = cardWidth * 0.25,\n angle = 5,\n maxSpread = 30,\n}: FanOptions): FanLayout {\n if (count < 1) return { cards: [], width: 0, height: 0 };\n const gaps = count - 1;\n const delta = gaps ? Math.min(angle, maxSpread / gaps) * RADIANS : 0;\n const edge = (gaps * delta) / 2;\n // The horizontal distance between the end cards' centres is `spacing * span`.\n const span = delta ? (2 * Math.sin(edge)) / delta : gaps;\n // The end cards' outer halves, tilted by the edge angle.\n const ends = cardWidth * Math.cos(edge) + cardHeight * Math.sin(edge);\n const spacing = span\n ? Math.max(minStep, Math.min(step, (width - ends) / span))\n : 0;\n const radius = delta ? spacing / delta : 0;\n const centres = Array.from({ length: count }, (_, index) => {\n if (!delta) return { theta: 0, x: (index - gaps / 2) * spacing, y: 0 };\n const theta = (index - gaps / 2) * delta;\n return {\n theta,\n x: radius * Math.sin(theta),\n y: radius * (1 - Math.cos(theta)),\n };\n });\n const halfHeight = (theta: number) =>\n (cardHeight / 2) * Math.cos(theta) +\n (cardWidth / 2) * Math.abs(Math.sin(theta));\n const top = Math.min(\n ...centres.map((card) => card.y - halfHeight(card.theta)),\n );\n const bottom = Math.max(\n ...centres.map((card) => card.y + halfHeight(card.theta)),\n );\n const fanWidth = spacing * span + ends;\n return {\n cards: centres.map((card) => ({\n x: card.x + (fanWidth - cardWidth) / 2,\n y: card.y - top - cardHeight / 2,\n rotate: card.theta / RADIANS,\n })),\n width: fanWidth,\n height: bottom - top,\n };\n}\n\n/** Moves a fanned card outward along its own tilt, as for a selected card. */\nexport function liftFanCard(card: FanCard, distance: number): FanCard {\n const theta = card.rotate * RADIANS;\n return {\n x: card.x + distance * Math.sin(theta),\n y: card.y - distance * Math.cos(theta),\n rotate: card.rotate,\n };\n}\n"],"mappings":"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","names":["x","y","value","target","cached","origin"]}
|
package/dist/testing.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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 = 10 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 { PlayerIdSchema } from \"../domain/player-identity.js\";\nimport { ViewCardSchema } from \"../domain/cards.js\";\nimport * as ReducerWireZod from \"../runtime-schema\";\nimport * as z from \"zod\";\nimport {\n DREAMBOARD_PLUGIN_PROTOCOL,\n DREAMBOARD_PLUGIN_PROTOCOL_VERSION,\n} from \"./protocol.js\";\nimport { RuntimeJsonSchema } from \"../runtime-json.js\";\nimport {\n BoardProjectionSchema,\n ProjectedTileSchema,\n} from \"../seat-topology-schema.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 GameEventDetailSchema =\n ReducerWireZod.ProjectedGameEventDetailSchema;\nexport const SystemActionEventSchema = ReducerWireZod.SystemActionEventSchema;\nexport const GameEventSchema = ReducerWireZod.ProjectedGameEventSchema;\nexport const SeatProjectionBundleSchema =\n ReducerWireZod.SeatProjectionBundleSchema;\n\nexport { PlayerIdSchema } from \"../domain/player-identity.js\";\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 tiles: z.array(ProjectedTileSchema),\n cardIds: z.array(z.string()),\n cardViewsById: z.record(z.string(), ViewCardSchema),\n cardBacksById: 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 sessionId: z.string().min(1),\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\nconst ProjectedViewSchema = z\n .record(z.string(), RuntimeJsonSchema)\n .superRefine((view, context) => {\n if (!Object.hasOwn(view, \"boards\")) return;\n const boards = BoardProjectionSchema.safeParse(view.boards);\n if (!boards.success) {\n for (const issue of boards.error.issues) {\n context.addIssue({\n code: \"custom\",\n path: [\"boards\", ...issue.path],\n message: issue.message,\n });\n }\n }\n });\n\nexport const SeatFrameSchema = z\n .object({\n events: z.array(GameEventSchema).max(32),\n view: ProjectedViewSchema.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(\n z.string(),\n z.record(z.string(), ZoneHandlesSnapshotSchema),\n ),\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 * as z from \"zod\";\nimport {\n SeatFrameSchema,\n PluginPlayerSummarySchema,\n} from \"../../shared/protocol/schema.js\";\nimport { immutableCopy } from \"../../shared/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@6\",\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@6\",\n frame,\n });\n}\n\nexport function digestPluginCommandRequest(\n command: SubmitInteractionCommand | CancelInteractionCommand,\n): string {\n return digestPluginRuntimeJson({\n digestVersion: \"plugin-command-request@6\",\n command,\n });\n}\n","import { canonicalizePluginRuntimeJson } from \"./json\";\nimport {\n PluginGameplayFrameSchema,\n SeatProjectionBundleSchema,\n} from \"./schema.js\";\nimport type {\n InteractionDescriptor,\n PlayerId,\n PluginGameplayFrame,\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 perspectivePlayerId: PlayerId;\n\n readonly sessionId: string;\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 if (\n dynamicProjection.referenceBasis.sessionId !== input.sessionId ||\n dynamicProjection.referenceBasis.version !== input.version\n ) {\n throw new Error(\n \"Projection reference basis does not match the frame basis.\",\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: seat?.events ?? [],\n basis: {\n sessionId: input.sessionId,\n version: input.version,\n actionSetVersion: input.actionSetVersion,\n perspectivePlayerId: input.perspectivePlayerId,\n },\n view: materializeView(seat?.view, seat?.boards),\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 seatView: unknown,\n seatBoards: ReducerSeatProjectionBundle[\"seats\"][string][\"boards\"],\n): RuntimeJson | null {\n const parts = [\n seatView,\n seatBoards === undefined ? undefined : { boards: seatBoards },\n ].filter((part) => part !== undefined && part !== null);\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, Record<string, ZoneHandlesSnapshot>> {\n return Object.fromEntries(\n Object.entries(value).map(([zoneId, hosts]) => [\n zoneId,\n Object.fromEntries(\n Object.entries(hosts).map(([hostId, zone]) => [\n hostId,\n {\n tiles: zone.tiles,\n cardIds: zone.cardIds,\n cardViewsById: zone.cardViewsById,\n cardBacksById: zone.cardBacksById,\n playableByCardId: Object.fromEntries(\n Object.entries(zone.playableByCardId).map(([cardId, refs]) => [\n cardId,\n hydrateInteractionRefs(\n registry,\n refs,\n `${path}.${zoneId}.${hostId}.playableByCardId.${cardId}`,\n ),\n ]),\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 {\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 \"../../shared/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\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.sessionId !== context.sessionId) {\n fail(new Error(\"Gameplay authority session changed.\"));\n return;\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 card views and hidden card backs 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 return {\n ...frame,\n zones: Object.fromEntries(\n Object.entries(frame.zones).map(([zoneId, hosts]) => [\n zoneId,\n Object.fromEntries(\n Object.entries(hosts).map(([hostId, zone]) => [\n hostId,\n {\n ...zone,\n cardViewsById: Object.fromEntries(\n Object.entries(zone.cardViewsById).map(([cardId, card]) => [\n cardId,\n {\n ...card,\n frontImage:\n card.frontImage === undefined\n ? undefined\n : (urls[card.frontImage] ?? card.frontImage),\n backImage:\n card.backImage === undefined\n ? undefined\n : (urls[card.backImage] ?? card.backImage),\n },\n ]),\n ),\n cardBacksById: Object.fromEntries(\n Object.entries(zone.cardBacksById).map(([cardId, path]) => [\n cardId,\n urls[path] ?? path,\n ]),\n ),\n },\n ]),\n ),\n ]),\n ),\n };\n}\n"],"mappings":"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","names":["SystemActionEventSchema","SeatProjectionBundleSchema","GameOutcomeSchema","z","SeatProjectionBundleSchema","createStore","createStore"]}
|