@dreamboard-games/sdk 0.5.0-alpha.3 → 0.5.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +52 -2
  2. package/dist/board-target-B0QG6OYx.d.ts +8 -0
  3. package/dist/chunk-3JXUL4VN.js +139 -0
  4. package/dist/chunk-3JXUL4VN.js.map +1 -0
  5. package/dist/{chunk-LRILEVKC.js → chunk-C77SYIVT.js} +82 -109
  6. package/dist/chunk-C77SYIVT.js.map +1 -0
  7. package/dist/{chunk-SP234IY4.js → chunk-OOFMBCFF.js} +178 -203
  8. package/dist/chunk-OOFMBCFF.js.map +1 -0
  9. package/dist/{chunk-ZPRKWPEP.js → chunk-UG2Q4NLG.js} +108 -29
  10. package/dist/chunk-UG2Q4NLG.js.map +1 -0
  11. package/dist/{chunk-FMM5LVJW.js → chunk-XU6WJW6K.js} +26 -12
  12. package/dist/chunk-XU6WJW6K.js.map +1 -0
  13. package/dist/{diagnostics-B0lgnuZ6.d.ts → diagnostics-B8d5aLad.d.ts} +2 -2
  14. package/dist/{definition-BaHNPZol.d.ts → extract-gVKcB8Og.d.ts} +484 -387
  15. package/dist/index.d.ts +404 -175
  16. package/dist/index.js +266 -215
  17. package/dist/index.js.map +1 -1
  18. package/dist/model-vdpLHrxh.d.ts +432 -0
  19. package/dist/react.d.ts +35 -7
  20. package/dist/react.js +136 -8
  21. package/dist/react.js.map +1 -1
  22. package/dist/reducer.d.ts +169 -118
  23. package/dist/reducer.js +206 -328
  24. package/dist/reducer.js.map +1 -1
  25. package/dist/testing.d.ts +5 -3
  26. package/dist/testing.js +9 -6
  27. package/dist/testing.js.map +1 -1
  28. package/dist/{types-DimqnJBq.d.ts → types-Bj5ZLTUV.d.ts} +38 -10
  29. package/package.json +19 -16
  30. package/dist/chunk-FMM5LVJW.js.map +0 -1
  31. package/dist/chunk-LRILEVKC.js.map +0 -1
  32. package/dist/chunk-SP234IY4.js.map +0 -1
  33. package/dist/chunk-VUWNJXLJ.js +0 -52
  34. package/dist/chunk-VUWNJXLJ.js.map +0 -1
  35. package/dist/chunk-ZPRKWPEP.js.map +0 -1
  36. package/dist/model-BHro6yXu.d.ts +0 -288
@@ -8,10 +8,12 @@ import {
8
8
  createHexBoardGeometry,
9
9
  digestPluginRuntimeJson,
10
10
  encodeCanonicalPluginRuntimeJson
11
- } from "./chunk-FMM5LVJW.js";
11
+ } from "./chunk-XU6WJW6K.js";
12
12
  import {
13
- inputValueInDomain
14
- } from "./chunk-VUWNJXLJ.js";
13
+ inputValueInDomain,
14
+ inputValueKey,
15
+ requireLookup
16
+ } from "./chunk-3JXUL4VN.js";
15
17
 
16
18
  // src/reducer/model/error-codes.ts
17
19
  var FrameworkErrorCodes = {
@@ -120,6 +122,11 @@ function createManifestGameStateSchema({
120
122
  });
121
123
  }
122
124
 
125
+ // src/reducer/model/definition.ts
126
+ var validatedReducerDefinition = /* @__PURE__ */ Symbol(
127
+ "validatedReducerDefinition"
128
+ );
129
+
123
130
  // src/reducer/per-player.ts
124
131
  import { z as z2 } from "zod";
125
132
  function asPlayerId(raw) {
@@ -174,7 +181,7 @@ function isPerPlayerBoardRef(ref) {
174
181
 
175
182
  // src/shared/worker-contract.ts
176
183
  import { z as z3 } from "zod";
177
- var REDUCER_CONTRACT_VERSION = "0.6.0";
184
+ var REDUCER_CONTRACT_VERSION = "0.7.0";
178
185
  var callable = z3.custom(
179
186
  (value) => typeof value === "function"
180
187
  );
@@ -346,7 +353,11 @@ function geometryOf(board) {
346
353
  return geometry;
347
354
  }
348
355
  function getBoard(table, boardId) {
349
- return table.boards.byId[boardId];
356
+ return requireLookup(
357
+ table.boards.byId[boardId],
358
+ "Board",
359
+ boardId
360
+ );
350
361
  }
351
362
  function getTiledBoard(table, boardId) {
352
363
  return getBoard(table, boardId);
@@ -355,13 +366,21 @@ function getSquareBoard(table, boardId) {
355
366
  return getBoard(table, boardId);
356
367
  }
357
368
  function getSpace(table, boardId, spaceId) {
358
- return getBoard(table, boardId).spaces[spaceId];
369
+ return requireLookup(
370
+ getBoard(table, boardId).spaces[spaceId],
371
+ `Space on board ${boardId}`,
372
+ spaceId
373
+ );
359
374
  }
360
375
  function getSquareSpace(table, boardId, spaceId) {
361
- return getSquareBoard(table, boardId).spaces[spaceId];
376
+ return getSpace(table, boardId, spaceId);
362
377
  }
363
378
  function getContainer(table, boardId, containerId) {
364
- return getBoard(table, boardId).containers[containerId];
379
+ return requireLookup(
380
+ getBoard(table, boardId).containers[containerId],
381
+ `Container on board ${boardId}`,
382
+ containerId
383
+ );
365
384
  }
366
385
  function getEdge(table, boardId, edgeId) {
367
386
  const edge = getTiledBoard(table, boardId).edges.find(
@@ -557,10 +576,7 @@ function bindBoardQueries(table, boardId) {
557
576
  const common = {
558
577
  state,
559
578
  space: (id) => {
560
- const space = getSpace(table, boardId, id);
561
- if (!space)
562
- throw new Error(`Unknown space '${id}' on board '${boardId}'.`);
563
- return space;
579
+ return getSpace(table, boardId, id);
564
580
  },
565
581
  container: (id) => getContainer(table, boardId, id),
566
582
  spacesByType: (id) => getSpacesByTypeId(table, boardId, id),
@@ -793,11 +809,15 @@ function cloneRuntimeTable(table) {
793
809
 
794
810
  // src/reducer/table/component-locations.ts
795
811
  function getComponentLocation(table, componentId) {
796
- return table.componentLocations[componentId];
812
+ return requireLookup(
813
+ table.componentLocations[componentId],
814
+ "Component location",
815
+ componentId
816
+ );
797
817
  }
798
818
  function getComponentDeckLocation(table, componentId) {
799
819
  const location = getComponentLocation(table, componentId);
800
- if (location?.type !== "InDeck") {
820
+ if (location.type !== "InDeck") {
801
821
  return null;
802
822
  }
803
823
  return {
@@ -809,7 +829,7 @@ function getComponentDeckLocation(table, componentId) {
809
829
  }
810
830
  function getComponentHandLocation(table, componentId) {
811
831
  const location = getComponentLocation(table, componentId);
812
- if (location?.type !== "InHand") {
832
+ if (location.type !== "InHand") {
813
833
  return null;
814
834
  }
815
835
  return {
@@ -822,7 +842,7 @@ function getComponentHandLocation(table, componentId) {
822
842
  }
823
843
  function getComponentZoneLocation(table, componentId) {
824
844
  const location = getComponentLocation(table, componentId);
825
- if (location?.type !== "InZone") {
845
+ if (location.type !== "InZone") {
826
846
  return null;
827
847
  }
828
848
  return {
@@ -833,7 +853,7 @@ function getComponentZoneLocation(table, componentId) {
833
853
  }
834
854
  function getComponentSpaceLocation(table, componentId) {
835
855
  const location = getComponentLocation(table, componentId);
836
- if (location?.type !== "OnSpace") {
856
+ if (location.type !== "OnSpace") {
837
857
  return null;
838
858
  }
839
859
  const boardId = location.boardId;
@@ -849,7 +869,7 @@ function getComponentSpaceLocation(table, componentId) {
849
869
  }
850
870
  function getComponentContainerLocation(table, componentId) {
851
871
  const location = getComponentLocation(table, componentId);
852
- if (location?.type !== "InContainer") {
872
+ if (location.type !== "InContainer") {
853
873
  return null;
854
874
  }
855
875
  const boardId = location.boardId;
@@ -865,7 +885,7 @@ function getComponentContainerLocation(table, componentId) {
865
885
  }
866
886
  function getComponentEdgeLocation(table, componentId) {
867
887
  const location = getComponentLocation(table, componentId);
868
- if (location?.type !== "OnEdge") {
888
+ if (location.type !== "OnEdge") {
869
889
  return null;
870
890
  }
871
891
  const boardId = location.boardId;
@@ -881,7 +901,7 @@ function getComponentEdgeLocation(table, componentId) {
881
901
  }
882
902
  function getComponentVertexLocation(table, componentId) {
883
903
  const location = getComponentLocation(table, componentId);
884
- if (location?.type !== "OnVertex") {
904
+ if (location.type !== "OnVertex") {
885
905
  return null;
886
906
  }
887
907
  const boardId = location.boardId;
@@ -897,7 +917,7 @@ function getComponentVertexLocation(table, componentId) {
897
917
  }
898
918
  function getComponentSlotLocation(table, componentId) {
899
919
  const location = getComponentLocation(table, componentId);
900
- if (location?.type !== "InSlot") {
920
+ if (location.type !== "InSlot") {
901
921
  return null;
902
922
  }
903
923
  return {
@@ -1003,21 +1023,24 @@ function getAllPlayerZoneCards(table, zoneId) {
1003
1023
  return result;
1004
1024
  }
1005
1025
  function getCard(table, cardId) {
1006
- const card = table.cards[cardId];
1026
+ const card = requireLookup(
1027
+ table.cards[cardId],
1028
+ "Card",
1029
+ cardId
1030
+ );
1007
1031
  return {
1008
1032
  id: card.id,
1009
1033
  cardType: card.cardType,
1010
1034
  name: card.name,
1011
1035
  text: card.text,
1036
+ frontImage: card.frontImage,
1037
+ backImage: card.backImage,
1012
1038
  properties: card.properties
1013
1039
  };
1014
1040
  }
1015
1041
  function getCardsById(table, cardIds) {
1016
1042
  return Object.fromEntries(
1017
- cardIds.map((cardId) => [
1018
- cardId,
1019
- table.cards[cardId] ? getCard(table, cardId) : void 0
1020
- ])
1043
+ cardIds.map((cardId) => [cardId, getCard(table, cardId)])
1021
1044
  );
1022
1045
  }
1023
1046
  function getSharedZoneCardCollection(table, zoneId) {
@@ -2042,7 +2065,11 @@ function createTableQueries(table) {
2042
2065
  missingResources: (playerId, amounts) => getMissingResources(table, playerId, amounts)
2043
2066
  },
2044
2067
  component: {
2045
- data: (componentId) => table.cards[componentId] ?? table.pieces[componentId] ?? table.dice[componentId],
2068
+ data: (componentId) => requireLookup(
2069
+ table.cards[componentId] ?? table.pieces[componentId] ?? table.dice[componentId],
2070
+ "Component",
2071
+ componentId
2072
+ ),
2046
2073
  location: (componentId) => getComponentLocation(table, componentId),
2047
2074
  deck: (componentId) => getComponentDeckLocation(table, componentId),
2048
2075
  hand: (componentId) => getComponentHandLocation(table, componentId),
@@ -2344,6 +2371,8 @@ var currentRuntimeTableSchema = z6.object({
2344
2371
  cardType: z6.string(),
2345
2372
  name: z6.string().optional(),
2346
2373
  text: z6.string().optional(),
2374
+ frontImage: z6.string().optional(),
2375
+ backImage: z6.string().optional(),
2347
2376
  properties: runtimeRecordSchema
2348
2377
  }).strict()
2349
2378
  ),
@@ -3540,44 +3569,6 @@ function findCardInputKeyForZone(interaction, zoneId) {
3540
3569
  )?.[0];
3541
3570
  }
3542
3571
 
3543
- // src/reducer/bundle/trusted/collector-eligibility.ts
3544
- function collectEligibleTargets(interaction, domainState, playerId, options = {}) {
3545
- const collectors = interactionInputsOf(interaction);
3546
- const result = {};
3547
- let queriesLazy = options.queries ?? null;
3548
- const queries = () => queriesLazy ??= createStateQueries(
3549
- domainState
3550
- );
3551
- for (const [key, collector] of Object.entries(collectors)) {
3552
- if (!collector.eligibleTargets) continue;
3553
- const cacheKey = options.eligibleTargetCachePrefix ? `${options.eligibleTargetCachePrefix}:${key}` : null;
3554
- const cached = cacheKey ? options.eligibleTargetCache?.get(cacheKey) : void 0;
3555
- if (cached) {
3556
- result[key] = cached;
3557
- continue;
3558
- }
3559
- const targets = collector.eligibleTargets(
3560
- domainState,
3561
- playerId,
3562
- queries()
3563
- );
3564
- const resolved = Array.from(targets).map(
3565
- (target) => projectEligibleTarget(collector, target)
3566
- );
3567
- result[key] = resolved;
3568
- if (cacheKey) {
3569
- options.eligibleTargetCache?.set(cacheKey, resolved);
3570
- }
3571
- }
3572
- return result;
3573
- }
3574
- function projectEligibleTarget(collector, target) {
3575
- if (collector.kind === "board-space" && collector.meta?.valueKind === "player-board-space" && typeof target === "object" && target !== null && "spaceId" in target && typeof target.spaceId === "string") {
3576
- return target.spaceId;
3577
- }
3578
- return String(target);
3579
- }
3580
-
3581
3572
  // src/reducer/bundle/trusted/interaction-types.ts
3582
3573
  function makeValidationError(errorCode, message) {
3583
3574
  return {
@@ -3588,9 +3579,6 @@ function makeValidationError(errorCode, message) {
3588
3579
  }
3589
3580
 
3590
3581
  // src/reducer/bundle/trusted/collector-params.ts
3591
- function normalizeCollectorValue(collector, value, playerId) {
3592
- return collector.kind === "board-space" && collector.meta?.valueKind === "player-board-space" && typeof value === "string" && playerId ? { boardId: collector.meta.boardId, playerId, spaceId: value } : value;
3593
- }
3594
3582
  function parseInteractionParams(interaction, rawParams, options = {}) {
3595
3583
  const collectors = interactionInputsOf(interaction);
3596
3584
  const record = rawParams ?? {};
@@ -3608,12 +3596,7 @@ function parseInteractionParams(interaction, rawParams, options = {}) {
3608
3596
  const issues = [];
3609
3597
  for (const [key, collector] of Object.entries(collectors)) {
3610
3598
  if (collector.kind === "rng" && options.skipRng) continue;
3611
- const rawValueBase = record[key] === void 0 && "defaultValue" in collector ? collector.defaultValue : record[key];
3612
- const rawValue = normalizeCollectorValue(
3613
- collector,
3614
- rawValueBase,
3615
- options.playerId
3616
- );
3599
+ const rawValue = record[key] === void 0 && "defaultValue" in collector ? collector.defaultValue : record[key];
3617
3600
  const result = collector.schema.safeParse(rawValue);
3618
3601
  if (!result.success) {
3619
3602
  for (const issue of result.error.issues) {
@@ -3713,7 +3696,7 @@ function validateCollectorSelection(collector, value) {
3713
3696
  if (selection.distinct) {
3714
3697
  const seen = /* @__PURE__ */ new Set();
3715
3698
  for (const item of value) {
3716
- const key = stableValueKey(item);
3699
+ const key = inputValueKey(item);
3717
3700
  if (seen.has(key)) {
3718
3701
  return {
3719
3702
  errorCode: "DUPLICATE_INPUT_VALUE",
@@ -3725,19 +3708,6 @@ function validateCollectorSelection(collector, value) {
3725
3708
  }
3726
3709
  return null;
3727
3710
  }
3728
- function stableValueKey(value) {
3729
- if (value === null) return "null";
3730
- switch (typeof value) {
3731
- case "string":
3732
- return `string:${value}`;
3733
- case "number":
3734
- case "boolean":
3735
- case "undefined":
3736
- return `${typeof value}:${String(value)}`;
3737
- default:
3738
- return `json:${JSON.stringify(value)}`;
3739
- }
3740
- }
3741
3711
 
3742
3712
  // src/reducer/bundle/trusted/simultaneous-player.ts
3743
3713
  var SIMULTANEOUS_SUBMIT_INTERACTION_ID = "submit";
@@ -3886,9 +3856,7 @@ function evaluateStepPrefix(steps, state, playerId, values) {
3886
3856
  current = { key: entry.key, collector, domain };
3887
3857
  if (validValues.length === values.length) break;
3888
3858
  const value = values[validValues.length];
3889
- const parsed = collector.schema.safeParse(
3890
- normalizeCollectorValue(collector, value, playerId)
3891
- );
3859
+ const parsed = collector.schema.safeParse(value);
3892
3860
  if (!parsed.success || value === void 0 || parsed.data === void 0) {
3893
3861
  issue = `Invalid value for step '${entry.key}'.`;
3894
3862
  break;
@@ -4568,13 +4536,7 @@ function buildInteractionDescriptor(scope, state, playerId, interactionId, inter
4568
4536
  const shouldMaterializeInputDomains = decision.available || decision.code === FrameworkErrorCodes.NO_LEGAL_INPUT;
4569
4537
  const inputs = shouldMaterializeInputDomains ? enrichResourceInputPresentation(
4570
4538
  collectInteractionInputs(projectedInteraction, domainState, playerId, {
4571
- queries,
4572
- eligibleTargetCache: options.projection?.eligibleTargets,
4573
- eligibleTargetCachePrefix: `${phaseName}:${String(
4574
- interactionId
4575
- )}:${String(playerId)}`,
4576
- includeEligibleTargets: options.includeEligibleTargets,
4577
- diagnostics: scope.diagnostics
4539
+ queries
4578
4540
  }),
4579
4541
  scope.definition.contract.manifest
4580
4542
  ) : [];
@@ -4850,8 +4812,7 @@ function createInteractionDecisionResolver(scope, authorization, options = {}) {
4850
4812
  ok: true,
4851
4813
  params: finalStepSchema?.success ? finalStepSchema.data : submittedPrefix.selected
4852
4814
  } : parseForSubmit ? parseInteractionParams(interaction, params, {
4853
- skipRng: true,
4854
- playerId
4815
+ skipRng: true
4855
4816
  }) : {
4856
4817
  ok: true,
4857
4818
  params: prepareInteractionProjectionParams(interaction, params)
@@ -4874,7 +4835,7 @@ function createInteractionDecisionResolver(scope, authorization, options = {}) {
4874
4835
  trustedInteractionId,
4875
4836
  interaction,
4876
4837
  descriptorDecision2,
4877
- { projection, includeEligibleTargets: false }
4838
+ { projection }
4878
4839
  ),
4879
4840
  validation: makeValidationError(
4880
4841
  "invalid-action-params",
@@ -4967,7 +4928,6 @@ function createInteractionDecisionResolver(scope, authorization, options = {}) {
4967
4928
  {
4968
4929
  projection,
4969
4930
  stepPrefix: mode === "submit" ? void 0 : prefix,
4970
- includeEligibleTargets: available || mode === "card",
4971
4931
  includeDiagnosticReasons: options.diagnostics === "verbose"
4972
4932
  }
4973
4933
  );
@@ -5151,8 +5111,7 @@ function createInteractionDecisionResolver(scope, authorization, options = {}) {
5151
5111
  interaction,
5152
5112
  { available: true },
5153
5113
  {
5154
- projection,
5155
- includeEligibleTargets: true
5114
+ projection
5156
5115
  }
5157
5116
  );
5158
5117
  return {
@@ -5219,7 +5178,6 @@ function createInteractionResolver(scope, options = {}) {
5219
5178
  }
5220
5179
  return {
5221
5180
  currentClientParamSchema: decisions.currentClientParamSchema,
5222
- collectEligibleTargets,
5223
5181
  collectFirstCardZoneId,
5224
5182
  enumerateInteractionParams: decisions.enumerateInteractionParams,
5225
5183
  explainInteraction: decisions.explainInteraction,
@@ -6169,8 +6127,7 @@ function createProjectionContext(options) {
6169
6127
  const q = createStateQueries(options.domainState);
6170
6128
  return {
6171
6129
  domainState: options.domainState,
6172
- q,
6173
- eligibleTargets: /* @__PURE__ */ new Map()
6130
+ q
6174
6131
  };
6175
6132
  }
6176
6133
 
@@ -6409,6 +6366,20 @@ function createProjectionBuilder(scope, interactions) {
6409
6366
  pendingPlayerIds
6410
6367
  };
6411
6368
  }
6369
+ function resolveResourcesFor(combinedState, playerId) {
6370
+ const ownerOnly = new Set(
6371
+ scope.definition.contract.manifest.literals.ownerResourceIds ?? []
6372
+ );
6373
+ const balances = combinedState.table.resources;
6374
+ return Object.fromEntries(
6375
+ Object.entries(balances).map(([holder, resources]) => [
6376
+ holder,
6377
+ holder === playerId ? { ...resources } : Object.fromEntries(
6378
+ Object.entries(resources).filter(([id]) => !ownerOnly.has(id))
6379
+ )
6380
+ ])
6381
+ );
6382
+ }
6412
6383
  function resolvePlayerViewFor(combinedState, playerId, projection) {
6413
6384
  const view = scope.definition.view;
6414
6385
  const viewArgs = {
@@ -6462,7 +6433,8 @@ function createProjectionBuilder(scope, interactions) {
6462
6433
  projection,
6463
6434
  registry
6464
6435
  )
6465
- )
6436
+ ),
6437
+ resources: resolveResourcesFor(combinedState, playerId)
6466
6438
  } : {};
6467
6439
  seats[playerId] = {
6468
6440
  ...fullProjection,
@@ -6753,6 +6725,7 @@ function createReducerBundle(definition, options = {}) {
6753
6725
  }
6754
6726
 
6755
6727
  export {
6728
+ validatedReducerDefinition,
6756
6729
  markManifestScopedSchema,
6757
6730
  isManifestScopedSchema,
6758
6731
  manifestSchemaFamily,
@@ -6786,4 +6759,4 @@ export {
6786
6759
  createProjectionBuilder,
6787
6760
  createReducerBundle
6788
6761
  };
6789
- //# sourceMappingURL=chunk-LRILEVKC.js.map
6762
+ //# sourceMappingURL=chunk-C77SYIVT.js.map