@plasius/scene-object 0.1.2 → 0.1.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.
package/README.md CHANGED
@@ -13,6 +13,7 @@ npm install @plasius/scene-object
13
13
  This package is controlled by a site-owned feature flag:
14
14
 
15
15
  - `scene.object.runtime.enabled`
16
+ - Player System interface extensions inherit `isekai.player-system.interface.enabled`
16
17
 
17
18
  ## Package exports
18
19
 
@@ -20,6 +21,8 @@ This package is controlled by a site-owned feature flag:
20
21
  - deterministic object validation and manifest creation helpers
21
22
  - attachment and attachment-point helpers
22
23
  - state lookup helpers
24
+ - Player System extension contracts for target anchors, focus-pane screens, and localized alert markers
25
+ - `validateSceneObjectPlayerSystemManifest()` plus focus/anchor lookup helpers
23
26
 
24
27
  ## Development
25
28
 
@@ -38,3 +41,5 @@ npm run pack:check
38
41
  - transforms and bounds must be finite numbers with valid units
39
42
  - attachment points and links must reference existing objects/points
40
43
  - state visibility and object references must be structurally valid
44
+ - Player System anchors must reference exported object attachment points
45
+ - focus screens must bind to `focus-pane` anchors and declare a bounded presentation variant
package/dist/index.cjs CHANGED
@@ -20,14 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID: () => SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID,
23
24
  SCENE_OBJECT_RUNTIME_FLAG_ID: () => SCENE_OBJECT_RUNTIME_FLAG_ID,
24
25
  SCENE_OBJECT_SCHEMA_VERSION: () => SCENE_OBJECT_SCHEMA_VERSION,
25
26
  createSceneObjectManifest: () => createSceneObjectManifest,
27
+ resolveSceneObjectAnchorById: () => resolveSceneObjectAnchorById,
26
28
  resolveSceneObjectById: () => resolveSceneObjectById,
29
+ resolveSceneObjectFocusScreenById: () => resolveSceneObjectFocusScreenById,
27
30
  resolveSceneObjectReferences: () => resolveSceneObjectReferences,
28
31
  resolveSceneObjectState: () => resolveSceneObjectState,
29
32
  validateSceneObjectManifest: () => validateSceneObjectManifest,
30
- validateSceneObjectObjectState: () => validateSceneObjectObjectState
33
+ validateSceneObjectObjectState: () => validateSceneObjectObjectState,
34
+ validateSceneObjectPlayerSystemManifest: () => validateSceneObjectPlayerSystemManifest
31
35
  });
32
36
  module.exports = __toCommonJS(index_exports);
33
37
 
@@ -436,6 +440,317 @@ function resolveSceneObjectById(requestOrManifest, objectId) {
436
440
  return result.value.objects.find((object) => object.id === request.objectId);
437
441
  }
438
442
 
443
+ // src/player-system.ts
444
+ var SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID = "isekai.player-system.interface.enabled";
445
+ var ID_PATTERN2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
446
+ var ANCHOR_KINDS = /* @__PURE__ */ new Set([
447
+ "target",
448
+ "focus-pane",
449
+ "localized-alert",
450
+ "line-of-sight-popup"
451
+ ]);
452
+ var ANCHOR_VISIBILITIES = /* @__PURE__ */ new Set([
453
+ "always",
454
+ "combat-safe",
455
+ "focused-only",
456
+ "line-of-sight"
457
+ ]);
458
+ var FOCUS_SCREEN_VARIANTS = /* @__PURE__ */ new Set([
459
+ "single-pane",
460
+ "multi-pane",
461
+ "combat-safe"
462
+ ]);
463
+ function pushIssue2(issues, issue) {
464
+ issues.push(issue);
465
+ }
466
+ function isFiniteNumber2(value) {
467
+ return typeof value === "number" && Number.isFinite(value);
468
+ }
469
+ function isKebabId(value) {
470
+ return typeof value === "string" && ID_PATTERN2.test(value);
471
+ }
472
+ function validateKebabId2(value, path, issues) {
473
+ if (typeof value !== "string") {
474
+ pushIssue2(issues, {
475
+ code: "invalid-type",
476
+ path,
477
+ message: "Expected a string identifier."
478
+ });
479
+ return false;
480
+ }
481
+ if (!ID_PATTERN2.test(value)) {
482
+ pushIssue2(issues, {
483
+ code: "invalid-id",
484
+ path,
485
+ message: "Identifiers must be kebab-case tokens."
486
+ });
487
+ return false;
488
+ }
489
+ return true;
490
+ }
491
+ function findObjectPoint(object, pointId) {
492
+ return object?.attachmentPoints?.find((point) => point.id === pointId);
493
+ }
494
+ function validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds) {
495
+ if (!anchor || typeof anchor !== "object") {
496
+ pushIssue2(issues, {
497
+ code: "required",
498
+ path,
499
+ message: "Expected anchor definition object."
500
+ });
501
+ return false;
502
+ }
503
+ const value = anchor;
504
+ let valid = true;
505
+ if (!validateKebabId2(value.id, `${path}.id`, issues)) {
506
+ valid = false;
507
+ } else if (anchorIds.has(value.id)) {
508
+ pushIssue2(issues, {
509
+ code: "duplicate-id",
510
+ path: `${path}.id`,
511
+ message: "Anchor identifiers must be unique."
512
+ });
513
+ valid = false;
514
+ } else {
515
+ anchorIds.add(value.id);
516
+ }
517
+ if (!validateKebabId2(value.objectId, `${path}.objectId`, issues)) {
518
+ valid = false;
519
+ }
520
+ if (!validateKebabId2(value.pointId, `${path}.pointId`, issues)) {
521
+ valid = false;
522
+ }
523
+ if (!ANCHOR_KINDS.has(value.kind)) {
524
+ pushIssue2(issues, {
525
+ code: "invalid-value",
526
+ path: `${path}.kind`,
527
+ message: "Anchor kind must be target, focus-pane, localized-alert, or line-of-sight-popup."
528
+ });
529
+ valid = false;
530
+ }
531
+ if (!ANCHOR_VISIBILITIES.has(value.visibility)) {
532
+ pushIssue2(issues, {
533
+ code: "invalid-value",
534
+ path: `${path}.visibility`,
535
+ message: "Anchor visibility must be always, combat-safe, focused-only, or line-of-sight."
536
+ });
537
+ valid = false;
538
+ }
539
+ const object = typeof value.objectId === "string" ? objectsById.get(value.objectId) : void 0;
540
+ if (!object) {
541
+ pushIssue2(issues, {
542
+ code: "missing-reference",
543
+ path: `${path}.objectId`,
544
+ message: "Anchor objectId must reference an existing scene object."
545
+ });
546
+ valid = false;
547
+ } else if (typeof value.pointId === "string" && !findObjectPoint(object, value.pointId)) {
548
+ pushIssue2(issues, {
549
+ code: "missing-reference",
550
+ path: `${path}.pointId`,
551
+ message: "Anchor pointId must reference an attachment point on the target object."
552
+ });
553
+ valid = false;
554
+ }
555
+ if (value.kind === "localized-alert") {
556
+ if (typeof value.localeKey !== "string" || value.localeKey.trim().length === 0) {
557
+ pushIssue2(issues, {
558
+ code: "required",
559
+ path: `${path}.localeKey`,
560
+ message: "localized-alert anchors require a localeKey."
561
+ });
562
+ valid = false;
563
+ }
564
+ } else if (value.localeKey !== void 0 && (typeof value.localeKey !== "string" || value.localeKey.trim().length === 0)) {
565
+ pushIssue2(issues, {
566
+ code: "invalid-type",
567
+ path: `${path}.localeKey`,
568
+ message: "localeKey must be a non-empty string when present."
569
+ });
570
+ valid = false;
571
+ }
572
+ if (value.offset !== void 0) {
573
+ if (!value.offset || typeof value.offset !== "object") {
574
+ pushIssue2(issues, {
575
+ code: "invalid-type",
576
+ path: `${path}.offset`,
577
+ message: "offset must be a finite x/y/z vector when present."
578
+ });
579
+ valid = false;
580
+ } else {
581
+ for (const axis of ["x", "y", "z"]) {
582
+ if (!isFiniteNumber2(value.offset[axis])) {
583
+ pushIssue2(issues, {
584
+ code: "invalid-type",
585
+ path: `${path}.offset.${axis}`,
586
+ message: "offset axes must be finite numbers."
587
+ });
588
+ valid = false;
589
+ }
590
+ }
591
+ }
592
+ }
593
+ if (value.tags !== void 0) {
594
+ if (!Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== "string" || tag.trim().length === 0)) {
595
+ pushIssue2(issues, {
596
+ code: "invalid-type",
597
+ path: `${path}.tags`,
598
+ message: "tags must be an array of non-empty strings when present."
599
+ });
600
+ valid = false;
601
+ }
602
+ }
603
+ return valid;
604
+ }
605
+ function validateFocusScreenDefinition(focusScreen, path, issues, objectsById, anchorsById, focusScreenIds) {
606
+ if (!focusScreen || typeof focusScreen !== "object") {
607
+ pushIssue2(issues, {
608
+ code: "required",
609
+ path,
610
+ message: "Expected focus-screen definition object."
611
+ });
612
+ return false;
613
+ }
614
+ const value = focusScreen;
615
+ let valid = true;
616
+ if (!validateKebabId2(value.id, `${path}.id`, issues)) {
617
+ valid = false;
618
+ } else if (focusScreenIds.has(value.id)) {
619
+ pushIssue2(issues, {
620
+ code: "duplicate-id",
621
+ path: `${path}.id`,
622
+ message: "Focus-screen identifiers must be unique."
623
+ });
624
+ valid = false;
625
+ } else {
626
+ focusScreenIds.add(value.id);
627
+ }
628
+ if (!validateKebabId2(value.objectId, `${path}.objectId`, issues)) {
629
+ valid = false;
630
+ } else if (!objectsById.has(value.objectId)) {
631
+ pushIssue2(issues, {
632
+ code: "missing-reference",
633
+ path: `${path}.objectId`,
634
+ message: "Focus-screen objectId must reference an existing scene object."
635
+ });
636
+ valid = false;
637
+ }
638
+ if (!validateKebabId2(value.anchorId, `${path}.anchorId`, issues)) {
639
+ valid = false;
640
+ } else {
641
+ const anchor = anchorsById.get(value.anchorId);
642
+ if (!anchor) {
643
+ pushIssue2(issues, {
644
+ code: "missing-reference",
645
+ path: `${path}.anchorId`,
646
+ message: "Focus-screen anchorId must reference an exported anchor."
647
+ });
648
+ valid = false;
649
+ } else if (anchor.kind !== "focus-pane") {
650
+ pushIssue2(issues, {
651
+ code: "invalid-reference",
652
+ path: `${path}.anchorId`,
653
+ message: "Focus screens must bind to focus-pane anchors."
654
+ });
655
+ valid = false;
656
+ }
657
+ }
658
+ if (!validateKebabId2(value.paneId, `${path}.paneId`, issues)) {
659
+ valid = false;
660
+ }
661
+ if (!FOCUS_SCREEN_VARIANTS.has(value.variant)) {
662
+ pushIssue2(issues, {
663
+ code: "invalid-value",
664
+ path: `${path}.variant`,
665
+ message: "Focus-screen variant must be single-pane, multi-pane, or combat-safe."
666
+ });
667
+ valid = false;
668
+ }
669
+ if (value.headingKey !== void 0 && (typeof value.headingKey !== "string" || value.headingKey.trim().length === 0)) {
670
+ pushIssue2(issues, {
671
+ code: "invalid-type",
672
+ path: `${path}.headingKey`,
673
+ message: "headingKey must be a non-empty string when present."
674
+ });
675
+ valid = false;
676
+ }
677
+ return valid;
678
+ }
679
+ function validateSceneObjectPlayerSystemManifest(manifest) {
680
+ const base = validateSceneObjectManifest(manifest);
681
+ if (!base.valid || !base.value) {
682
+ return base;
683
+ }
684
+ const issues = [...base.issues];
685
+ const value = manifest;
686
+ const objectsById = new Map(
687
+ base.value.objects.map((object) => [object.id, object])
688
+ );
689
+ const anchorIds = /* @__PURE__ */ new Set();
690
+ const anchorsById = /* @__PURE__ */ new Map();
691
+ const focusScreenIds = /* @__PURE__ */ new Set();
692
+ let valid = true;
693
+ if (value.anchors !== void 0) {
694
+ if (!Array.isArray(value.anchors)) {
695
+ pushIssue2(issues, {
696
+ code: "invalid-type",
697
+ path: "$.anchors",
698
+ message: "anchors must be an array when present."
699
+ });
700
+ valid = false;
701
+ } else {
702
+ value.anchors.forEach((anchor, index) => {
703
+ const path = `$.anchors[${index}]`;
704
+ if (validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds)) {
705
+ anchorsById.set(anchor.id, anchor);
706
+ } else {
707
+ valid = false;
708
+ }
709
+ });
710
+ }
711
+ }
712
+ if (value.focusScreens !== void 0) {
713
+ if (!Array.isArray(value.focusScreens)) {
714
+ pushIssue2(issues, {
715
+ code: "invalid-type",
716
+ path: "$.focusScreens",
717
+ message: "focusScreens must be an array when present."
718
+ });
719
+ valid = false;
720
+ } else {
721
+ value.focusScreens.forEach((focusScreen, index) => {
722
+ if (!validateFocusScreenDefinition(
723
+ focusScreen,
724
+ `$.focusScreens[${index}]`,
725
+ issues,
726
+ objectsById,
727
+ anchorsById,
728
+ focusScreenIds
729
+ )) {
730
+ valid = false;
731
+ }
732
+ });
733
+ }
734
+ }
735
+ return {
736
+ valid,
737
+ issues,
738
+ value: valid ? value : void 0
739
+ };
740
+ }
741
+ function resolveSceneObjectAnchorById(manifest, anchorId) {
742
+ if (!isKebabId(anchorId)) {
743
+ return void 0;
744
+ }
745
+ return manifest.anchors?.find((anchor) => anchor.id === anchorId);
746
+ }
747
+ function resolveSceneObjectFocusScreenById(manifest, focusScreenId) {
748
+ if (!isKebabId(focusScreenId)) {
749
+ return void 0;
750
+ }
751
+ return manifest.focusScreens?.find((focusScreen) => focusScreen.id === focusScreenId);
752
+ }
753
+
439
754
  // src/resolve.ts
440
755
  function resolveSceneObjectState(manifest, objectId) {
441
756
  if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {
@@ -447,13 +762,17 @@ function resolveSceneObjectState(manifest, objectId) {
447
762
  }
448
763
  // Annotate the CommonJS export names for ESM import in node:
449
764
  0 && (module.exports = {
765
+ SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID,
450
766
  SCENE_OBJECT_RUNTIME_FLAG_ID,
451
767
  SCENE_OBJECT_SCHEMA_VERSION,
452
768
  createSceneObjectManifest,
769
+ resolveSceneObjectAnchorById,
453
770
  resolveSceneObjectById,
771
+ resolveSceneObjectFocusScreenById,
454
772
  resolveSceneObjectReferences,
455
773
  resolveSceneObjectState,
456
774
  validateSceneObjectManifest,
457
- validateSceneObjectObjectState
775
+ validateSceneObjectObjectState,
776
+ validateSceneObjectPlayerSystemManifest
458
777
  });
459
778
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/validation.ts","../src/resolve.ts"],"sourcesContent":["export {\n SCENE_OBJECT_RUNTIME_FLAG_ID,\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectAttachment,\n type SceneObjectAttachmentPoint,\n type SceneObjectBounds,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectReference,\n type SceneObjectResolutionRequest,\n type SceneObjectResolutionResult,\n type SceneObjectStateKind,\n type SceneObjectTransform,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectVector3,\n} from \"./types.js\";\nexport {\n createSceneObjectManifest,\n resolveSceneObjectById,\n resolveSceneObjectReferences,\n validateSceneObjectManifest,\n validateSceneObjectObjectState,\n} from \"./validation.js\";\nexport { resolveSceneObjectState } from \"./resolve.js\";\n","export const SCENE_OBJECT_SCHEMA_VERSION = \"1.0.0\";\nexport const SCENE_OBJECT_RUNTIME_FLAG_ID = \"scene.object.runtime.enabled\";\n\nexport type SceneObjectStateKind = \"idle\" | \"visible\" | \"hidden\" | \"disabled\";\n\nexport type SceneObjectCoordinateSpace =\n | \"normalized-viewport\"\n | \"pixel-viewport\"\n | \"world\"\n | \"local\";\n\nexport type SceneObjectUnits = \"ratio\" | \"pixels\";\n\nexport interface SceneObjectVector3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport interface SceneObjectTransform {\n translate: SceneObjectVector3;\n rotate: SceneObjectVector3;\n scale: SceneObjectVector3;\n}\n\nexport interface SceneObjectBounds {\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n unit: SceneObjectUnits;\n };\n depth?: number;\n coordinateSpace: SceneObjectCoordinateSpace;\n}\n\nexport interface SceneObjectPoint {\n id: string;\n x: number;\n y: number;\n z?: number;\n}\n\nexport interface SceneObjectAttachment {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n offset?: SceneObjectVector3;\n}\n\nexport type SceneObjectAttachmentPoint = SceneObjectPoint;\n\nexport interface SceneObjectObjectState {\n objectId: string;\n visible: boolean;\n tags?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface SceneObjectReference {\n objectId: string;\n pointId: string;\n}\n\nexport interface SceneObjectManifest {\n schemaVersion: string;\n objects: SceneObjectDefinition[];\n stateSnapshots?: SceneObjectObjectState[];\n}\n\nexport interface SceneObjectDefinition {\n id: string;\n name?: string;\n transform: SceneObjectTransform;\n bounds: SceneObjectBounds;\n attachmentPoints?: SceneObjectPoint[];\n attachments?: SceneObjectAttachment[];\n}\n\nexport type SceneObjectValidationCode =\n | \"required\"\n | \"invalid-type\"\n | \"invalid-value\"\n | \"invalid-id\"\n | \"duplicate-id\"\n | \"invalid-reference\"\n | \"missing-reference\";\n\nexport interface SceneObjectValidationIssue {\n code: SceneObjectValidationCode;\n path: string;\n message: string;\n}\n\nexport interface SceneObjectValidationResult<T> {\n valid: boolean;\n issues: SceneObjectValidationIssue[];\n value?: T;\n}\n\nexport interface SceneObjectResolutionRequest {\n manifest: SceneObjectManifest;\n objectId: string;\n}\n\nexport interface SceneObjectResolutionResult {\n manifest: SceneObjectManifest;\n object: SceneObjectDefinition;\n}\n","import {\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectBounds,\n type SceneObjectCoordinateSpace,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectDefinition,\n type SceneObjectAttachment,\n type SceneObjectResolutionRequest,\n type SceneObjectTransform,\n} from \"./types.js\";\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst COORDINATE_SPACES = new Set<SceneObjectCoordinateSpace>([\n \"normalized-viewport\",\n \"pixel-viewport\",\n \"world\",\n \"local\",\n]);\nconst UNITS = new Set([\"ratio\", \"pixels\"]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction validateTransform(\n value: SceneObjectTransform,\n path: string,\n issues: SceneObjectValidationIssue[],\n): boolean {\n const vectorChecks = [\"translate\", \"rotate\", \"scale\"] as const;\n let valid = true;\n\n for (const field of vectorChecks) {\n const vector = value[field];\n if (!vector || typeof vector !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.${field}`,\n message: `Expected a ${field} vector.`,\n });\n valid = false;\n continue;\n }\n\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n const raw = vector[axis];\n if (!isFiniteNumber(raw)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}.${axis}`,\n message: `Vector ${axis} must be finite.`,\n });\n valid = false;\n }\n }\n }\n\n return valid;\n}\n\nfunction validatePoint(point: SceneObjectPoint, path: string, issues: SceneObjectValidationIssue[]): boolean {\n let valid = true;\n\n if (!validateKebabId(point.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n for (const field of [\"x\", \"y\", \"z\"] as const) {\n const value = point[field];\n if (field === \"z\" && value === undefined) {\n continue;\n }\n if (!isFiniteNumber(value)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}`,\n message: \"Attachment point axis must be finite.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateBounds(bounds: SceneObjectBounds, path: string, issues: SceneObjectValidationIssue[]): boolean {\n if (!bounds || typeof bounds !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected bounds block.\" });\n return false;\n }\n\n if (!COORDINATE_SPACES.has(bounds.coordinateSpace as SceneObjectCoordinateSpace)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.coordinateSpace`,\n message: \"coordinateSpace must be normalized-viewport, pixel-viewport, world, or local.\",\n });\n return false;\n }\n\n const rect = bounds.rect;\n if (!rect || typeof rect !== \"object\") {\n pushIssue(issues, { code: \"required\", path: `${path}.rect`, message: \"Expected rect bounds.\" });\n return false;\n }\n\n if (!UNITS.has(rect.unit as string)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect.unit`,\n message: \"unit must be 'ratio' or 'pixels'.\",\n });\n return false;\n }\n\n let valid = true;\n for (const field of [\"x\", \"y\", \"width\", \"height\"] as const) {\n const value = rect[field];\n if (!isFiniteNumber(value) || value < 0) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.rect.${field}`,\n message: \"Rect fields must be finite non-negative numbers.\",\n });\n valid = false;\n }\n }\n\n if (rect.width === 0 || rect.height === 0) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect`,\n message: \"Rect width and height must be positive.\",\n });\n valid = false;\n }\n\n if (bounds.depth !== undefined && (!isFiniteNumber(bounds.depth) || bounds.depth < 0)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.depth`,\n message: \"depth must be a non-negative number.\",\n });\n valid = false;\n }\n\n return valid && isFiniteNumber(bounds.rect.width) && isFiniteNumber(bounds.rect.height);\n}\n\nfunction validateAttachmentTarget(\n attachment: {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n path: string,\n issues: SceneObjectValidationIssue[],\n seenPoints: Map<string, Set<string>>,\n): boolean {\n let valid = true;\n if (!validateKebabId(attachment.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourceObjectId, `${path}.sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetObjectId, `${path}.targetObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourcePointId, `${path}.sourcePointId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetPointId, `${path}.targetPointId`, issues)) {\n valid = false;\n }\n\n const sourcePoints = seenPoints.get(attachment.sourceObjectId);\n const targetPoints = seenPoints.get(attachment.targetObjectId);\n\n if (sourcePoints && !sourcePoints.has(attachment.sourcePointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.sourcePointId`,\n message: \"sourcePointId does not exist on source object.\",\n });\n valid = false;\n }\n\n if (targetPoints && !targetPoints.has(attachment.targetPointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.targetPointId`,\n message: \"targetPointId does not exist on target object.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const issues: SceneObjectValidationIssue[] = [];\n\n if (!manifest || typeof manifest !== \"object\") {\n return {\n valid: false,\n issues: [{ code: \"required\", path: \"$\", message: \"Expected a scene object manifest object.\" }],\n };\n }\n\n const value = manifest as Record<string, unknown>;\n let valid = true;\n\n if (value.schemaVersion !== SCENE_OBJECT_SCHEMA_VERSION) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: \"$.schemaVersion\",\n message: `schemaVersion must equal ${SCENE_OBJECT_SCHEMA_VERSION}.`,\n });\n valid = false;\n }\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: \"$.objects\",\n message: \"Manifest must contain at least one object.\",\n });\n return { valid: false, issues };\n }\n\n const objects = value.objects as SceneObjectDefinition[];\n const seenObjects = new Set<string>();\n const pointsByObject = new Map<string, Set<string>>();\n\n for (const [index, object] of objects.entries()) {\n const path = `$.objects[${index}]`;\n\n if (!object || typeof object !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected object definition.\" });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(object.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (seenObjects.has(object.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: `Duplicate object id '${object.id}' is not allowed.`,\n });\n valid = false;\n }\n seenObjects.add(object.id);\n\n if (!object.transform || typeof object.transform !== \"object\" || !validateTransform(object.transform as SceneObjectTransform, `${path}.transform`, issues)) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.transform`,\n message: \"Object must define a transform.\",\n });\n valid = false;\n }\n\n if (!object.bounds) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.bounds`,\n message: \"Object must define bounds.\",\n });\n valid = false;\n } else if (!validateBounds(object.bounds, `${path}.bounds`, issues)) {\n valid = false;\n }\n\n const attachmentPointIds = new Set<string>();\n const rawPoints = Array.isArray(object.attachmentPoints)\n ? object.attachmentPoints\n : [];\n for (const [pointIndex, point] of rawPoints.entries()) {\n if (!point || typeof point !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachmentPoints[${pointIndex}]`,\n message: \"Expected attachment point definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validatePoint(point as SceneObjectPoint, `${path}.attachmentPoints[${pointIndex}]`, issues)) {\n valid = false;\n continue;\n }\n\n const pointId = (point as SceneObjectPoint).id;\n if (attachmentPointIds.has(pointId)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachmentPoints[${pointIndex}].id`,\n message: `Duplicate attachment point '${pointId}' within object.`,\n });\n valid = false;\n }\n attachmentPointIds.add(pointId);\n }\n\n if (rawPoints.length > 0) {\n pointsByObject.set(object.id, attachmentPointIds);\n }\n\n if (Array.isArray(object.attachments)) {\n const attachmentIds = new Set<string>();\n for (const [attachmentIndex, attachment] of object.attachments.entries()) {\n if (!attachment || typeof attachment !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachments[${attachmentIndex}]`,\n message: \"Expected attachment definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId((attachment as SceneObjectAttachment).sourceObjectId, `${path}.attachments[${attachmentIndex}].sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!attachmentIds.has((attachment as { id?: string }).id ?? \"\")) {\n attachmentIds.add((attachment as { id?: string }).id ?? \"\");\n } else {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachments[${attachmentIndex}].id`,\n message: \"Duplicate attachment id.\",\n });\n valid = false;\n }\n\n if (\n !validateAttachmentTarget(\n attachment as {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n `${path}.attachments[${attachmentIndex}]`,\n issues,\n pointsByObject,\n )\n ) {\n valid = false;\n }\n }\n }\n }\n\n const objectIds = new Set(\n objects\n .filter((candidate): candidate is SceneObjectDefinition => Boolean(candidate && typeof candidate === \"object\"))\n .map((candidate) => candidate.id),\n );\n if (Array.isArray(value.stateSnapshots)) {\n for (const [stateIndex, state] of value.stateSnapshots.entries()) {\n const stateValue = state as SceneObjectObjectState;\n const path = `$.stateSnapshots[${stateIndex}]`;\n\n if (!stateValue || typeof stateValue !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected object state definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(stateValue.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!objectIds.has(stateValue.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"objectId does not reference an object in objects.\",\n });\n valid = false;\n }\n\n if (typeof stateValue.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.visible`,\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n }\n }\n\n return valid\n ? { valid: true, issues, value: manifest as SceneObjectManifest }\n : { valid: false, issues };\n}\n\nexport function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n const summary = result.issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \");\n throw new Error(`Invalid scene object manifest. ${summary}`);\n }\n\n return result.value;\n}\n\nexport function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState> {\n if (!state || typeof state !== \"object\") {\n return {\n valid: false,\n issues: [{\n code: \"required\",\n path: \"$\",\n message: \"Expected an object state.\",\n }],\n };\n }\n\n const value = state as Record<string, unknown>;\n const issues: SceneObjectValidationIssue[] = [];\n let valid = true;\n\n if (!validateKebabId(value.objectId, \"$.objectId\", issues)) {\n valid = false;\n }\n\n if (typeof value.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.visible\",\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n\n return valid\n ? { valid: true, issues, value: state as SceneObjectObjectState }\n : { valid: false, issues };\n}\n\nexport function resolveSceneObjectReferences(\n manifest: SceneObjectManifest,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n return { valid: false, issues: result.issues };\n }\n\n return { valid: true, issues: [], value: result.value };\n}\n\nexport function resolveSceneObjectById(\n requestOrManifest:\n | SceneObjectResolutionRequest\n | SceneObjectManifest,\n objectId?: string,\n): SceneObjectDefinition | undefined {\n const request: SceneObjectResolutionRequest = typeof objectId === \"string\"\n ? {\n manifest: requestOrManifest as SceneObjectManifest,\n objectId,\n }\n : requestOrManifest as SceneObjectResolutionRequest;\n\n const result = validateSceneObjectManifest(request.manifest);\n if (!result.valid || !result.value) {\n return undefined;\n }\n\n return result.value.objects.find((object) => object.id === request.objectId);\n}\n","import {\n SceneObjectManifest,\n SceneObjectObjectState,\n SceneObjectDefinition,\n} from \"./types.js\";\n\nexport function resolveSceneObjectState(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectObjectState | undefined {\n if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {\n return undefined;\n }\n\n return manifest.stateSnapshots.find(\n (snapshot) => snapshot.objectId === objectId,\n );\n}\n\nexport function resolveSceneObjectById(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectDefinition | undefined {\n return manifest.objects.find((object) => object.id === objectId);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/validation.ts","../src/player-system.ts","../src/resolve.ts"],"sourcesContent":["export {\n SCENE_OBJECT_RUNTIME_FLAG_ID,\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectAttachment,\n type SceneObjectAttachmentPoint,\n type SceneObjectBounds,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectReference,\n type SceneObjectResolutionRequest,\n type SceneObjectResolutionResult,\n type SceneObjectStateKind,\n type SceneObjectTransform,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectVector3,\n} from \"./types.js\";\nexport {\n SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID,\n type SceneObjectAnchorDefinition,\n type SceneObjectAnchorKind,\n type SceneObjectAnchorVisibility,\n type SceneObjectFocusScreenDefinition,\n type SceneObjectPlayerSystemManifest,\n resolveSceneObjectAnchorById,\n resolveSceneObjectFocusScreenById,\n validateSceneObjectPlayerSystemManifest,\n} from \"./player-system.js\";\nexport {\n createSceneObjectManifest,\n resolveSceneObjectById,\n resolveSceneObjectReferences,\n validateSceneObjectManifest,\n validateSceneObjectObjectState,\n} from \"./validation.js\";\nexport { resolveSceneObjectState } from \"./resolve.js\";\n","export const SCENE_OBJECT_SCHEMA_VERSION = \"1.0.0\";\nexport const SCENE_OBJECT_RUNTIME_FLAG_ID = \"scene.object.runtime.enabled\";\n\nexport type SceneObjectStateKind = \"idle\" | \"visible\" | \"hidden\" | \"disabled\";\n\nexport type SceneObjectCoordinateSpace =\n | \"normalized-viewport\"\n | \"pixel-viewport\"\n | \"world\"\n | \"local\";\n\nexport type SceneObjectUnits = \"ratio\" | \"pixels\";\n\nexport interface SceneObjectVector3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport interface SceneObjectTransform {\n translate: SceneObjectVector3;\n rotate: SceneObjectVector3;\n scale: SceneObjectVector3;\n}\n\nexport interface SceneObjectBounds {\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n unit: SceneObjectUnits;\n };\n depth?: number;\n coordinateSpace: SceneObjectCoordinateSpace;\n}\n\nexport interface SceneObjectPoint {\n id: string;\n x: number;\n y: number;\n z?: number;\n}\n\nexport interface SceneObjectAttachment {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n offset?: SceneObjectVector3;\n}\n\nexport type SceneObjectAttachmentPoint = SceneObjectPoint;\n\nexport interface SceneObjectObjectState {\n objectId: string;\n visible: boolean;\n tags?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface SceneObjectReference {\n objectId: string;\n pointId: string;\n}\n\nexport interface SceneObjectManifest {\n schemaVersion: string;\n objects: SceneObjectDefinition[];\n stateSnapshots?: SceneObjectObjectState[];\n}\n\nexport interface SceneObjectDefinition {\n id: string;\n name?: string;\n transform: SceneObjectTransform;\n bounds: SceneObjectBounds;\n attachmentPoints?: SceneObjectPoint[];\n attachments?: SceneObjectAttachment[];\n}\n\nexport type SceneObjectValidationCode =\n | \"required\"\n | \"invalid-type\"\n | \"invalid-value\"\n | \"invalid-id\"\n | \"duplicate-id\"\n | \"invalid-reference\"\n | \"missing-reference\";\n\nexport interface SceneObjectValidationIssue {\n code: SceneObjectValidationCode;\n path: string;\n message: string;\n}\n\nexport interface SceneObjectValidationResult<T> {\n valid: boolean;\n issues: SceneObjectValidationIssue[];\n value?: T;\n}\n\nexport interface SceneObjectResolutionRequest {\n manifest: SceneObjectManifest;\n objectId: string;\n}\n\nexport interface SceneObjectResolutionResult {\n manifest: SceneObjectManifest;\n object: SceneObjectDefinition;\n}\n","import {\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectBounds,\n type SceneObjectCoordinateSpace,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectDefinition,\n type SceneObjectAttachment,\n type SceneObjectResolutionRequest,\n type SceneObjectTransform,\n} from \"./types.js\";\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst COORDINATE_SPACES = new Set<SceneObjectCoordinateSpace>([\n \"normalized-viewport\",\n \"pixel-viewport\",\n \"world\",\n \"local\",\n]);\nconst UNITS = new Set([\"ratio\", \"pixels\"]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction validateTransform(\n value: SceneObjectTransform,\n path: string,\n issues: SceneObjectValidationIssue[],\n): boolean {\n const vectorChecks = [\"translate\", \"rotate\", \"scale\"] as const;\n let valid = true;\n\n for (const field of vectorChecks) {\n const vector = value[field];\n if (!vector || typeof vector !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.${field}`,\n message: `Expected a ${field} vector.`,\n });\n valid = false;\n continue;\n }\n\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n const raw = vector[axis];\n if (!isFiniteNumber(raw)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}.${axis}`,\n message: `Vector ${axis} must be finite.`,\n });\n valid = false;\n }\n }\n }\n\n return valid;\n}\n\nfunction validatePoint(point: SceneObjectPoint, path: string, issues: SceneObjectValidationIssue[]): boolean {\n let valid = true;\n\n if (!validateKebabId(point.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n for (const field of [\"x\", \"y\", \"z\"] as const) {\n const value = point[field];\n if (field === \"z\" && value === undefined) {\n continue;\n }\n if (!isFiniteNumber(value)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}`,\n message: \"Attachment point axis must be finite.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateBounds(bounds: SceneObjectBounds, path: string, issues: SceneObjectValidationIssue[]): boolean {\n if (!bounds || typeof bounds !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected bounds block.\" });\n return false;\n }\n\n if (!COORDINATE_SPACES.has(bounds.coordinateSpace as SceneObjectCoordinateSpace)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.coordinateSpace`,\n message: \"coordinateSpace must be normalized-viewport, pixel-viewport, world, or local.\",\n });\n return false;\n }\n\n const rect = bounds.rect;\n if (!rect || typeof rect !== \"object\") {\n pushIssue(issues, { code: \"required\", path: `${path}.rect`, message: \"Expected rect bounds.\" });\n return false;\n }\n\n if (!UNITS.has(rect.unit as string)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect.unit`,\n message: \"unit must be 'ratio' or 'pixels'.\",\n });\n return false;\n }\n\n let valid = true;\n for (const field of [\"x\", \"y\", \"width\", \"height\"] as const) {\n const value = rect[field];\n if (!isFiniteNumber(value) || value < 0) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.rect.${field}`,\n message: \"Rect fields must be finite non-negative numbers.\",\n });\n valid = false;\n }\n }\n\n if (rect.width === 0 || rect.height === 0) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect`,\n message: \"Rect width and height must be positive.\",\n });\n valid = false;\n }\n\n if (bounds.depth !== undefined && (!isFiniteNumber(bounds.depth) || bounds.depth < 0)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.depth`,\n message: \"depth must be a non-negative number.\",\n });\n valid = false;\n }\n\n return valid && isFiniteNumber(bounds.rect.width) && isFiniteNumber(bounds.rect.height);\n}\n\nfunction validateAttachmentTarget(\n attachment: {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n path: string,\n issues: SceneObjectValidationIssue[],\n seenPoints: Map<string, Set<string>>,\n): boolean {\n let valid = true;\n if (!validateKebabId(attachment.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourceObjectId, `${path}.sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetObjectId, `${path}.targetObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourcePointId, `${path}.sourcePointId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetPointId, `${path}.targetPointId`, issues)) {\n valid = false;\n }\n\n const sourcePoints = seenPoints.get(attachment.sourceObjectId);\n const targetPoints = seenPoints.get(attachment.targetObjectId);\n\n if (sourcePoints && !sourcePoints.has(attachment.sourcePointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.sourcePointId`,\n message: \"sourcePointId does not exist on source object.\",\n });\n valid = false;\n }\n\n if (targetPoints && !targetPoints.has(attachment.targetPointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.targetPointId`,\n message: \"targetPointId does not exist on target object.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const issues: SceneObjectValidationIssue[] = [];\n\n if (!manifest || typeof manifest !== \"object\") {\n return {\n valid: false,\n issues: [{ code: \"required\", path: \"$\", message: \"Expected a scene object manifest object.\" }],\n };\n }\n\n const value = manifest as Record<string, unknown>;\n let valid = true;\n\n if (value.schemaVersion !== SCENE_OBJECT_SCHEMA_VERSION) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: \"$.schemaVersion\",\n message: `schemaVersion must equal ${SCENE_OBJECT_SCHEMA_VERSION}.`,\n });\n valid = false;\n }\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: \"$.objects\",\n message: \"Manifest must contain at least one object.\",\n });\n return { valid: false, issues };\n }\n\n const objects = value.objects as SceneObjectDefinition[];\n const seenObjects = new Set<string>();\n const pointsByObject = new Map<string, Set<string>>();\n\n for (const [index, object] of objects.entries()) {\n const path = `$.objects[${index}]`;\n\n if (!object || typeof object !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected object definition.\" });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(object.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (seenObjects.has(object.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: `Duplicate object id '${object.id}' is not allowed.`,\n });\n valid = false;\n }\n seenObjects.add(object.id);\n\n if (!object.transform || typeof object.transform !== \"object\" || !validateTransform(object.transform as SceneObjectTransform, `${path}.transform`, issues)) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.transform`,\n message: \"Object must define a transform.\",\n });\n valid = false;\n }\n\n if (!object.bounds) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.bounds`,\n message: \"Object must define bounds.\",\n });\n valid = false;\n } else if (!validateBounds(object.bounds, `${path}.bounds`, issues)) {\n valid = false;\n }\n\n const attachmentPointIds = new Set<string>();\n const rawPoints = Array.isArray(object.attachmentPoints)\n ? object.attachmentPoints\n : [];\n for (const [pointIndex, point] of rawPoints.entries()) {\n if (!point || typeof point !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachmentPoints[${pointIndex}]`,\n message: \"Expected attachment point definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validatePoint(point as SceneObjectPoint, `${path}.attachmentPoints[${pointIndex}]`, issues)) {\n valid = false;\n continue;\n }\n\n const pointId = (point as SceneObjectPoint).id;\n if (attachmentPointIds.has(pointId)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachmentPoints[${pointIndex}].id`,\n message: `Duplicate attachment point '${pointId}' within object.`,\n });\n valid = false;\n }\n attachmentPointIds.add(pointId);\n }\n\n if (rawPoints.length > 0) {\n pointsByObject.set(object.id, attachmentPointIds);\n }\n\n if (Array.isArray(object.attachments)) {\n const attachmentIds = new Set<string>();\n for (const [attachmentIndex, attachment] of object.attachments.entries()) {\n if (!attachment || typeof attachment !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachments[${attachmentIndex}]`,\n message: \"Expected attachment definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId((attachment as SceneObjectAttachment).sourceObjectId, `${path}.attachments[${attachmentIndex}].sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!attachmentIds.has((attachment as { id?: string }).id ?? \"\")) {\n attachmentIds.add((attachment as { id?: string }).id ?? \"\");\n } else {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachments[${attachmentIndex}].id`,\n message: \"Duplicate attachment id.\",\n });\n valid = false;\n }\n\n if (\n !validateAttachmentTarget(\n attachment as {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n `${path}.attachments[${attachmentIndex}]`,\n issues,\n pointsByObject,\n )\n ) {\n valid = false;\n }\n }\n }\n }\n\n const objectIds = new Set(\n objects\n .filter((candidate): candidate is SceneObjectDefinition => Boolean(candidate && typeof candidate === \"object\"))\n .map((candidate) => candidate.id),\n );\n if (Array.isArray(value.stateSnapshots)) {\n for (const [stateIndex, state] of value.stateSnapshots.entries()) {\n const stateValue = state as SceneObjectObjectState;\n const path = `$.stateSnapshots[${stateIndex}]`;\n\n if (!stateValue || typeof stateValue !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected object state definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(stateValue.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!objectIds.has(stateValue.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"objectId does not reference an object in objects.\",\n });\n valid = false;\n }\n\n if (typeof stateValue.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.visible`,\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n }\n }\n\n return valid\n ? { valid: true, issues, value: manifest as SceneObjectManifest }\n : { valid: false, issues };\n}\n\nexport function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n const summary = result.issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \");\n throw new Error(`Invalid scene object manifest. ${summary}`);\n }\n\n return result.value;\n}\n\nexport function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState> {\n if (!state || typeof state !== \"object\") {\n return {\n valid: false,\n issues: [{\n code: \"required\",\n path: \"$\",\n message: \"Expected an object state.\",\n }],\n };\n }\n\n const value = state as Record<string, unknown>;\n const issues: SceneObjectValidationIssue[] = [];\n let valid = true;\n\n if (!validateKebabId(value.objectId, \"$.objectId\", issues)) {\n valid = false;\n }\n\n if (typeof value.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.visible\",\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n\n return valid\n ? { valid: true, issues, value: state as SceneObjectObjectState }\n : { valid: false, issues };\n}\n\nexport function resolveSceneObjectReferences(\n manifest: SceneObjectManifest,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n return { valid: false, issues: result.issues };\n }\n\n return { valid: true, issues: [], value: result.value };\n}\n\nexport function resolveSceneObjectById(\n requestOrManifest:\n | SceneObjectResolutionRequest\n | SceneObjectManifest,\n objectId?: string,\n): SceneObjectDefinition | undefined {\n const request: SceneObjectResolutionRequest = typeof objectId === \"string\"\n ? {\n manifest: requestOrManifest as SceneObjectManifest,\n objectId,\n }\n : requestOrManifest as SceneObjectResolutionRequest;\n\n const result = validateSceneObjectManifest(request.manifest);\n if (!result.valid || !result.value) {\n return undefined;\n }\n\n return result.value.objects.find((object) => object.id === request.objectId);\n}\n","import { type SceneObjectDefinition,\n type SceneObjectManifest,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectVector3,\n} from \"./types.js\";\nimport { validateSceneObjectManifest } from \"./validation.js\";\n\nexport const SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID =\n \"isekai.player-system.interface.enabled\";\n\nexport type SceneObjectAnchorKind =\n | \"target\"\n | \"focus-pane\"\n | \"localized-alert\"\n | \"line-of-sight-popup\";\n\nexport type SceneObjectAnchorVisibility =\n | \"always\"\n | \"combat-safe\"\n | \"focused-only\"\n | \"line-of-sight\";\n\nexport interface SceneObjectAnchorDefinition {\n id: string;\n kind: SceneObjectAnchorKind;\n objectId: string;\n pointId: string;\n visibility: SceneObjectAnchorVisibility;\n localeKey?: string;\n offset?: SceneObjectVector3;\n tags?: string[];\n}\n\nexport interface SceneObjectFocusScreenDefinition {\n id: string;\n objectId: string;\n anchorId: string;\n paneId: string;\n variant: \"single-pane\" | \"multi-pane\" | \"combat-safe\";\n headingKey?: string;\n}\n\nexport interface SceneObjectPlayerSystemManifest extends SceneObjectManifest {\n anchors?: SceneObjectAnchorDefinition[];\n focusScreens?: SceneObjectFocusScreenDefinition[];\n}\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst ANCHOR_KINDS = new Set<SceneObjectAnchorKind>([\n \"target\",\n \"focus-pane\",\n \"localized-alert\",\n \"line-of-sight-popup\",\n]);\nconst ANCHOR_VISIBILITIES = new Set<SceneObjectAnchorVisibility>([\n \"always\",\n \"combat-safe\",\n \"focused-only\",\n \"line-of-sight\",\n]);\nconst FOCUS_SCREEN_VARIANTS = new Set<SceneObjectFocusScreenDefinition[\"variant\"]>([\n \"single-pane\",\n \"multi-pane\",\n \"combat-safe\",\n]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isKebabId(value: unknown): value is string {\n return typeof value === \"string\" && ID_PATTERN.test(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction findObjectPoint(\n object: SceneObjectDefinition | undefined,\n pointId: string,\n): SceneObjectPoint | undefined {\n return object?.attachmentPoints?.find((point) => point.id === pointId);\n}\n\nfunction validateAnchorDefinition(\n anchor: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n objectsById: Map<string, SceneObjectDefinition>,\n anchorIds: Set<string>,\n): anchor is SceneObjectAnchorDefinition {\n if (!anchor || typeof anchor !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected anchor definition object.\",\n });\n return false;\n }\n\n const value = anchor as Record<string, unknown>;\n let valid = true;\n\n if (!validateKebabId(value.id, `${path}.id`, issues)) {\n valid = false;\n } else if (anchorIds.has(value.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: \"Anchor identifiers must be unique.\",\n });\n valid = false;\n } else {\n anchorIds.add(value.id);\n }\n\n if (!validateKebabId(value.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(value.pointId, `${path}.pointId`, issues)) {\n valid = false;\n }\n\n if (!ANCHOR_KINDS.has(value.kind as SceneObjectAnchorKind)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.kind`,\n message:\n \"Anchor kind must be target, focus-pane, localized-alert, or line-of-sight-popup.\",\n });\n valid = false;\n }\n\n if (!ANCHOR_VISIBILITIES.has(value.visibility as SceneObjectAnchorVisibility)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.visibility`,\n message:\n \"Anchor visibility must be always, combat-safe, focused-only, or line-of-sight.\",\n });\n valid = false;\n }\n\n const object =\n typeof value.objectId === \"string\"\n ? objectsById.get(value.objectId)\n : undefined;\n if (!object) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"Anchor objectId must reference an existing scene object.\",\n });\n valid = false;\n } else if (\n typeof value.pointId === \"string\" &&\n !findObjectPoint(object, value.pointId)\n ) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.pointId`,\n message:\n \"Anchor pointId must reference an attachment point on the target object.\",\n });\n valid = false;\n }\n\n if (value.kind === \"localized-alert\") {\n if (typeof value.localeKey !== \"string\" || value.localeKey.trim().length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.localeKey`,\n message: \"localized-alert anchors require a localeKey.\",\n });\n valid = false;\n }\n } else if (\n value.localeKey !== undefined &&\n (typeof value.localeKey !== \"string\" || value.localeKey.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.localeKey`,\n message: \"localeKey must be a non-empty string when present.\",\n });\n valid = false;\n }\n\n if (value.offset !== undefined) {\n if (!value.offset || typeof value.offset !== \"object\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.offset`,\n message: \"offset must be a finite x/y/z vector when present.\",\n });\n valid = false;\n } else {\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n if (!isFiniteNumber((value.offset as Record<string, unknown>)[axis])) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.offset.${axis}`,\n message: \"offset axes must be finite numbers.\",\n });\n valid = false;\n }\n }\n }\n }\n\n if (value.tags !== undefined) {\n if (\n !Array.isArray(value.tags) ||\n value.tags.some((tag) => typeof tag !== \"string\" || tag.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.tags`,\n message: \"tags must be an array of non-empty strings when present.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateFocusScreenDefinition(\n focusScreen: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n objectsById: Map<string, SceneObjectDefinition>,\n anchorsById: Map<string, SceneObjectAnchorDefinition>,\n focusScreenIds: Set<string>,\n): focusScreen is SceneObjectFocusScreenDefinition {\n if (!focusScreen || typeof focusScreen !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected focus-screen definition object.\",\n });\n return false;\n }\n\n const value = focusScreen as Record<string, unknown>;\n let valid = true;\n\n if (!validateKebabId(value.id, `${path}.id`, issues)) {\n valid = false;\n } else if (focusScreenIds.has(value.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: \"Focus-screen identifiers must be unique.\",\n });\n valid = false;\n } else {\n focusScreenIds.add(value.id);\n }\n\n if (!validateKebabId(value.objectId, `${path}.objectId`, issues)) {\n valid = false;\n } else if (!objectsById.has(value.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"Focus-screen objectId must reference an existing scene object.\",\n });\n valid = false;\n }\n\n if (!validateKebabId(value.anchorId, `${path}.anchorId`, issues)) {\n valid = false;\n } else {\n const anchor = anchorsById.get(value.anchorId);\n if (!anchor) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.anchorId`,\n message: \"Focus-screen anchorId must reference an exported anchor.\",\n });\n valid = false;\n } else if (anchor.kind !== \"focus-pane\") {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.anchorId`,\n message: \"Focus screens must bind to focus-pane anchors.\",\n });\n valid = false;\n }\n }\n\n if (!validateKebabId(value.paneId, `${path}.paneId`, issues)) {\n valid = false;\n }\n\n if (!FOCUS_SCREEN_VARIANTS.has(value.variant as SceneObjectFocusScreenDefinition[\"variant\"])) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.variant`,\n message: \"Focus-screen variant must be single-pane, multi-pane, or combat-safe.\",\n });\n valid = false;\n }\n\n if (\n value.headingKey !== undefined &&\n (typeof value.headingKey !== \"string\" || value.headingKey.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.headingKey`,\n message: \"headingKey must be a non-empty string when present.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectPlayerSystemManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectPlayerSystemManifest> {\n const base = validateSceneObjectManifest(manifest);\n if (!base.valid || !base.value) {\n return base as SceneObjectValidationResult<SceneObjectPlayerSystemManifest>;\n }\n\n const issues = [...base.issues];\n const value = manifest as SceneObjectPlayerSystemManifest;\n const objectsById = new Map(\n base.value.objects.map((object) => [object.id, object] as const),\n );\n const anchorIds = new Set<string>();\n const anchorsById = new Map<string, SceneObjectAnchorDefinition>();\n const focusScreenIds = new Set<string>();\n let valid = true;\n\n if (value.anchors !== undefined) {\n if (!Array.isArray(value.anchors)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.anchors\",\n message: \"anchors must be an array when present.\",\n });\n valid = false;\n } else {\n value.anchors.forEach((anchor, index) => {\n const path = `$.anchors[${index}]`;\n if (\n validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds)\n ) {\n anchorsById.set(anchor.id, anchor);\n } else {\n valid = false;\n }\n });\n }\n }\n\n if (value.focusScreens !== undefined) {\n if (!Array.isArray(value.focusScreens)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.focusScreens\",\n message: \"focusScreens must be an array when present.\",\n });\n valid = false;\n } else {\n value.focusScreens.forEach((focusScreen, index) => {\n if (\n !validateFocusScreenDefinition(\n focusScreen,\n `$.focusScreens[${index}]`,\n issues,\n objectsById,\n anchorsById,\n focusScreenIds,\n )\n ) {\n valid = false;\n }\n });\n }\n }\n\n return {\n valid,\n issues,\n value: valid ? value : undefined,\n };\n}\n\nexport function resolveSceneObjectAnchorById(\n manifest: SceneObjectPlayerSystemManifest,\n anchorId: string,\n): SceneObjectAnchorDefinition | undefined {\n if (!isKebabId(anchorId)) {\n return undefined;\n }\n\n return manifest.anchors?.find((anchor) => anchor.id === anchorId);\n}\n\nexport function resolveSceneObjectFocusScreenById(\n manifest: SceneObjectPlayerSystemManifest,\n focusScreenId: string,\n): SceneObjectFocusScreenDefinition | undefined {\n if (!isKebabId(focusScreenId)) {\n return undefined;\n }\n\n return manifest.focusScreens?.find((focusScreen) => focusScreen.id === focusScreenId);\n}\n","import {\n SceneObjectManifest,\n SceneObjectObjectState,\n SceneObjectDefinition,\n} from \"./types.js\";\n\nexport function resolveSceneObjectState(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectObjectState | undefined {\n if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {\n return undefined;\n }\n\n return manifest.stateSnapshots.find(\n (snapshot) => snapshot.objectId === objectId,\n );\n}\n\nexport function resolveSceneObjectById(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectDefinition | undefined {\n return manifest.objects.find((object) => object.id === objectId);\n}\n"],"mappings":"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","names":["ID_PATTERN","pushIssue","isFiniteNumber","validateKebabId"]}
package/dist/index.d.cts CHANGED
@@ -82,6 +82,35 @@ interface SceneObjectResolutionResult {
82
82
  object: SceneObjectDefinition;
83
83
  }
84
84
 
85
+ declare const SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID = "isekai.player-system.interface.enabled";
86
+ type SceneObjectAnchorKind = "target" | "focus-pane" | "localized-alert" | "line-of-sight-popup";
87
+ type SceneObjectAnchorVisibility = "always" | "combat-safe" | "focused-only" | "line-of-sight";
88
+ interface SceneObjectAnchorDefinition {
89
+ id: string;
90
+ kind: SceneObjectAnchorKind;
91
+ objectId: string;
92
+ pointId: string;
93
+ visibility: SceneObjectAnchorVisibility;
94
+ localeKey?: string;
95
+ offset?: SceneObjectVector3;
96
+ tags?: string[];
97
+ }
98
+ interface SceneObjectFocusScreenDefinition {
99
+ id: string;
100
+ objectId: string;
101
+ anchorId: string;
102
+ paneId: string;
103
+ variant: "single-pane" | "multi-pane" | "combat-safe";
104
+ headingKey?: string;
105
+ }
106
+ interface SceneObjectPlayerSystemManifest extends SceneObjectManifest {
107
+ anchors?: SceneObjectAnchorDefinition[];
108
+ focusScreens?: SceneObjectFocusScreenDefinition[];
109
+ }
110
+ declare function validateSceneObjectPlayerSystemManifest(manifest: unknown): SceneObjectValidationResult<SceneObjectPlayerSystemManifest>;
111
+ declare function resolveSceneObjectAnchorById(manifest: SceneObjectPlayerSystemManifest, anchorId: string): SceneObjectAnchorDefinition | undefined;
112
+ declare function resolveSceneObjectFocusScreenById(manifest: SceneObjectPlayerSystemManifest, focusScreenId: string): SceneObjectFocusScreenDefinition | undefined;
113
+
85
114
  declare function validateSceneObjectManifest(manifest: unknown): SceneObjectValidationResult<SceneObjectManifest>;
86
115
  declare function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest;
87
116
  declare function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState>;
@@ -90,4 +119,4 @@ declare function resolveSceneObjectById(requestOrManifest: SceneObjectResolution
90
119
 
91
120
  declare function resolveSceneObjectState(manifest: SceneObjectManifest, objectId: string): SceneObjectObjectState | undefined;
92
121
 
93
- export { SCENE_OBJECT_RUNTIME_FLAG_ID, SCENE_OBJECT_SCHEMA_VERSION, type SceneObjectAttachment, type SceneObjectAttachmentPoint, type SceneObjectBounds, type SceneObjectManifest, type SceneObjectObjectState, type SceneObjectPoint, type SceneObjectReference, type SceneObjectResolutionRequest, type SceneObjectResolutionResult, type SceneObjectStateKind, type SceneObjectTransform, type SceneObjectValidationIssue, type SceneObjectValidationResult, type SceneObjectVector3, createSceneObjectManifest, resolveSceneObjectById, resolveSceneObjectReferences, resolveSceneObjectState, validateSceneObjectManifest, validateSceneObjectObjectState };
122
+ export { SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID, SCENE_OBJECT_RUNTIME_FLAG_ID, SCENE_OBJECT_SCHEMA_VERSION, type SceneObjectAnchorDefinition, type SceneObjectAnchorKind, type SceneObjectAnchorVisibility, type SceneObjectAttachment, type SceneObjectAttachmentPoint, type SceneObjectBounds, type SceneObjectFocusScreenDefinition, type SceneObjectManifest, type SceneObjectObjectState, type SceneObjectPlayerSystemManifest, type SceneObjectPoint, type SceneObjectReference, type SceneObjectResolutionRequest, type SceneObjectResolutionResult, type SceneObjectStateKind, type SceneObjectTransform, type SceneObjectValidationIssue, type SceneObjectValidationResult, type SceneObjectVector3, createSceneObjectManifest, resolveSceneObjectAnchorById, resolveSceneObjectById, resolveSceneObjectFocusScreenById, resolveSceneObjectReferences, resolveSceneObjectState, validateSceneObjectManifest, validateSceneObjectObjectState, validateSceneObjectPlayerSystemManifest };
package/dist/index.d.ts CHANGED
@@ -82,6 +82,35 @@ interface SceneObjectResolutionResult {
82
82
  object: SceneObjectDefinition;
83
83
  }
84
84
 
85
+ declare const SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID = "isekai.player-system.interface.enabled";
86
+ type SceneObjectAnchorKind = "target" | "focus-pane" | "localized-alert" | "line-of-sight-popup";
87
+ type SceneObjectAnchorVisibility = "always" | "combat-safe" | "focused-only" | "line-of-sight";
88
+ interface SceneObjectAnchorDefinition {
89
+ id: string;
90
+ kind: SceneObjectAnchorKind;
91
+ objectId: string;
92
+ pointId: string;
93
+ visibility: SceneObjectAnchorVisibility;
94
+ localeKey?: string;
95
+ offset?: SceneObjectVector3;
96
+ tags?: string[];
97
+ }
98
+ interface SceneObjectFocusScreenDefinition {
99
+ id: string;
100
+ objectId: string;
101
+ anchorId: string;
102
+ paneId: string;
103
+ variant: "single-pane" | "multi-pane" | "combat-safe";
104
+ headingKey?: string;
105
+ }
106
+ interface SceneObjectPlayerSystemManifest extends SceneObjectManifest {
107
+ anchors?: SceneObjectAnchorDefinition[];
108
+ focusScreens?: SceneObjectFocusScreenDefinition[];
109
+ }
110
+ declare function validateSceneObjectPlayerSystemManifest(manifest: unknown): SceneObjectValidationResult<SceneObjectPlayerSystemManifest>;
111
+ declare function resolveSceneObjectAnchorById(manifest: SceneObjectPlayerSystemManifest, anchorId: string): SceneObjectAnchorDefinition | undefined;
112
+ declare function resolveSceneObjectFocusScreenById(manifest: SceneObjectPlayerSystemManifest, focusScreenId: string): SceneObjectFocusScreenDefinition | undefined;
113
+
85
114
  declare function validateSceneObjectManifest(manifest: unknown): SceneObjectValidationResult<SceneObjectManifest>;
86
115
  declare function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest;
87
116
  declare function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState>;
@@ -90,4 +119,4 @@ declare function resolveSceneObjectById(requestOrManifest: SceneObjectResolution
90
119
 
91
120
  declare function resolveSceneObjectState(manifest: SceneObjectManifest, objectId: string): SceneObjectObjectState | undefined;
92
121
 
93
- export { SCENE_OBJECT_RUNTIME_FLAG_ID, SCENE_OBJECT_SCHEMA_VERSION, type SceneObjectAttachment, type SceneObjectAttachmentPoint, type SceneObjectBounds, type SceneObjectManifest, type SceneObjectObjectState, type SceneObjectPoint, type SceneObjectReference, type SceneObjectResolutionRequest, type SceneObjectResolutionResult, type SceneObjectStateKind, type SceneObjectTransform, type SceneObjectValidationIssue, type SceneObjectValidationResult, type SceneObjectVector3, createSceneObjectManifest, resolveSceneObjectById, resolveSceneObjectReferences, resolveSceneObjectState, validateSceneObjectManifest, validateSceneObjectObjectState };
122
+ export { SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID, SCENE_OBJECT_RUNTIME_FLAG_ID, SCENE_OBJECT_SCHEMA_VERSION, type SceneObjectAnchorDefinition, type SceneObjectAnchorKind, type SceneObjectAnchorVisibility, type SceneObjectAttachment, type SceneObjectAttachmentPoint, type SceneObjectBounds, type SceneObjectFocusScreenDefinition, type SceneObjectManifest, type SceneObjectObjectState, type SceneObjectPlayerSystemManifest, type SceneObjectPoint, type SceneObjectReference, type SceneObjectResolutionRequest, type SceneObjectResolutionResult, type SceneObjectStateKind, type SceneObjectTransform, type SceneObjectValidationIssue, type SceneObjectValidationResult, type SceneObjectVector3, createSceneObjectManifest, resolveSceneObjectAnchorById, resolveSceneObjectById, resolveSceneObjectFocusScreenById, resolveSceneObjectReferences, resolveSceneObjectState, validateSceneObjectManifest, validateSceneObjectObjectState, validateSceneObjectPlayerSystemManifest };
package/dist/index.js CHANGED
@@ -403,6 +403,317 @@ function resolveSceneObjectById(requestOrManifest, objectId) {
403
403
  return result.value.objects.find((object) => object.id === request.objectId);
404
404
  }
405
405
 
406
+ // src/player-system.ts
407
+ var SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID = "isekai.player-system.interface.enabled";
408
+ var ID_PATTERN2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
409
+ var ANCHOR_KINDS = /* @__PURE__ */ new Set([
410
+ "target",
411
+ "focus-pane",
412
+ "localized-alert",
413
+ "line-of-sight-popup"
414
+ ]);
415
+ var ANCHOR_VISIBILITIES = /* @__PURE__ */ new Set([
416
+ "always",
417
+ "combat-safe",
418
+ "focused-only",
419
+ "line-of-sight"
420
+ ]);
421
+ var FOCUS_SCREEN_VARIANTS = /* @__PURE__ */ new Set([
422
+ "single-pane",
423
+ "multi-pane",
424
+ "combat-safe"
425
+ ]);
426
+ function pushIssue2(issues, issue) {
427
+ issues.push(issue);
428
+ }
429
+ function isFiniteNumber2(value) {
430
+ return typeof value === "number" && Number.isFinite(value);
431
+ }
432
+ function isKebabId(value) {
433
+ return typeof value === "string" && ID_PATTERN2.test(value);
434
+ }
435
+ function validateKebabId2(value, path, issues) {
436
+ if (typeof value !== "string") {
437
+ pushIssue2(issues, {
438
+ code: "invalid-type",
439
+ path,
440
+ message: "Expected a string identifier."
441
+ });
442
+ return false;
443
+ }
444
+ if (!ID_PATTERN2.test(value)) {
445
+ pushIssue2(issues, {
446
+ code: "invalid-id",
447
+ path,
448
+ message: "Identifiers must be kebab-case tokens."
449
+ });
450
+ return false;
451
+ }
452
+ return true;
453
+ }
454
+ function findObjectPoint(object, pointId) {
455
+ return object?.attachmentPoints?.find((point) => point.id === pointId);
456
+ }
457
+ function validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds) {
458
+ if (!anchor || typeof anchor !== "object") {
459
+ pushIssue2(issues, {
460
+ code: "required",
461
+ path,
462
+ message: "Expected anchor definition object."
463
+ });
464
+ return false;
465
+ }
466
+ const value = anchor;
467
+ let valid = true;
468
+ if (!validateKebabId2(value.id, `${path}.id`, issues)) {
469
+ valid = false;
470
+ } else if (anchorIds.has(value.id)) {
471
+ pushIssue2(issues, {
472
+ code: "duplicate-id",
473
+ path: `${path}.id`,
474
+ message: "Anchor identifiers must be unique."
475
+ });
476
+ valid = false;
477
+ } else {
478
+ anchorIds.add(value.id);
479
+ }
480
+ if (!validateKebabId2(value.objectId, `${path}.objectId`, issues)) {
481
+ valid = false;
482
+ }
483
+ if (!validateKebabId2(value.pointId, `${path}.pointId`, issues)) {
484
+ valid = false;
485
+ }
486
+ if (!ANCHOR_KINDS.has(value.kind)) {
487
+ pushIssue2(issues, {
488
+ code: "invalid-value",
489
+ path: `${path}.kind`,
490
+ message: "Anchor kind must be target, focus-pane, localized-alert, or line-of-sight-popup."
491
+ });
492
+ valid = false;
493
+ }
494
+ if (!ANCHOR_VISIBILITIES.has(value.visibility)) {
495
+ pushIssue2(issues, {
496
+ code: "invalid-value",
497
+ path: `${path}.visibility`,
498
+ message: "Anchor visibility must be always, combat-safe, focused-only, or line-of-sight."
499
+ });
500
+ valid = false;
501
+ }
502
+ const object = typeof value.objectId === "string" ? objectsById.get(value.objectId) : void 0;
503
+ if (!object) {
504
+ pushIssue2(issues, {
505
+ code: "missing-reference",
506
+ path: `${path}.objectId`,
507
+ message: "Anchor objectId must reference an existing scene object."
508
+ });
509
+ valid = false;
510
+ } else if (typeof value.pointId === "string" && !findObjectPoint(object, value.pointId)) {
511
+ pushIssue2(issues, {
512
+ code: "missing-reference",
513
+ path: `${path}.pointId`,
514
+ message: "Anchor pointId must reference an attachment point on the target object."
515
+ });
516
+ valid = false;
517
+ }
518
+ if (value.kind === "localized-alert") {
519
+ if (typeof value.localeKey !== "string" || value.localeKey.trim().length === 0) {
520
+ pushIssue2(issues, {
521
+ code: "required",
522
+ path: `${path}.localeKey`,
523
+ message: "localized-alert anchors require a localeKey."
524
+ });
525
+ valid = false;
526
+ }
527
+ } else if (value.localeKey !== void 0 && (typeof value.localeKey !== "string" || value.localeKey.trim().length === 0)) {
528
+ pushIssue2(issues, {
529
+ code: "invalid-type",
530
+ path: `${path}.localeKey`,
531
+ message: "localeKey must be a non-empty string when present."
532
+ });
533
+ valid = false;
534
+ }
535
+ if (value.offset !== void 0) {
536
+ if (!value.offset || typeof value.offset !== "object") {
537
+ pushIssue2(issues, {
538
+ code: "invalid-type",
539
+ path: `${path}.offset`,
540
+ message: "offset must be a finite x/y/z vector when present."
541
+ });
542
+ valid = false;
543
+ } else {
544
+ for (const axis of ["x", "y", "z"]) {
545
+ if (!isFiniteNumber2(value.offset[axis])) {
546
+ pushIssue2(issues, {
547
+ code: "invalid-type",
548
+ path: `${path}.offset.${axis}`,
549
+ message: "offset axes must be finite numbers."
550
+ });
551
+ valid = false;
552
+ }
553
+ }
554
+ }
555
+ }
556
+ if (value.tags !== void 0) {
557
+ if (!Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== "string" || tag.trim().length === 0)) {
558
+ pushIssue2(issues, {
559
+ code: "invalid-type",
560
+ path: `${path}.tags`,
561
+ message: "tags must be an array of non-empty strings when present."
562
+ });
563
+ valid = false;
564
+ }
565
+ }
566
+ return valid;
567
+ }
568
+ function validateFocusScreenDefinition(focusScreen, path, issues, objectsById, anchorsById, focusScreenIds) {
569
+ if (!focusScreen || typeof focusScreen !== "object") {
570
+ pushIssue2(issues, {
571
+ code: "required",
572
+ path,
573
+ message: "Expected focus-screen definition object."
574
+ });
575
+ return false;
576
+ }
577
+ const value = focusScreen;
578
+ let valid = true;
579
+ if (!validateKebabId2(value.id, `${path}.id`, issues)) {
580
+ valid = false;
581
+ } else if (focusScreenIds.has(value.id)) {
582
+ pushIssue2(issues, {
583
+ code: "duplicate-id",
584
+ path: `${path}.id`,
585
+ message: "Focus-screen identifiers must be unique."
586
+ });
587
+ valid = false;
588
+ } else {
589
+ focusScreenIds.add(value.id);
590
+ }
591
+ if (!validateKebabId2(value.objectId, `${path}.objectId`, issues)) {
592
+ valid = false;
593
+ } else if (!objectsById.has(value.objectId)) {
594
+ pushIssue2(issues, {
595
+ code: "missing-reference",
596
+ path: `${path}.objectId`,
597
+ message: "Focus-screen objectId must reference an existing scene object."
598
+ });
599
+ valid = false;
600
+ }
601
+ if (!validateKebabId2(value.anchorId, `${path}.anchorId`, issues)) {
602
+ valid = false;
603
+ } else {
604
+ const anchor = anchorsById.get(value.anchorId);
605
+ if (!anchor) {
606
+ pushIssue2(issues, {
607
+ code: "missing-reference",
608
+ path: `${path}.anchorId`,
609
+ message: "Focus-screen anchorId must reference an exported anchor."
610
+ });
611
+ valid = false;
612
+ } else if (anchor.kind !== "focus-pane") {
613
+ pushIssue2(issues, {
614
+ code: "invalid-reference",
615
+ path: `${path}.anchorId`,
616
+ message: "Focus screens must bind to focus-pane anchors."
617
+ });
618
+ valid = false;
619
+ }
620
+ }
621
+ if (!validateKebabId2(value.paneId, `${path}.paneId`, issues)) {
622
+ valid = false;
623
+ }
624
+ if (!FOCUS_SCREEN_VARIANTS.has(value.variant)) {
625
+ pushIssue2(issues, {
626
+ code: "invalid-value",
627
+ path: `${path}.variant`,
628
+ message: "Focus-screen variant must be single-pane, multi-pane, or combat-safe."
629
+ });
630
+ valid = false;
631
+ }
632
+ if (value.headingKey !== void 0 && (typeof value.headingKey !== "string" || value.headingKey.trim().length === 0)) {
633
+ pushIssue2(issues, {
634
+ code: "invalid-type",
635
+ path: `${path}.headingKey`,
636
+ message: "headingKey must be a non-empty string when present."
637
+ });
638
+ valid = false;
639
+ }
640
+ return valid;
641
+ }
642
+ function validateSceneObjectPlayerSystemManifest(manifest) {
643
+ const base = validateSceneObjectManifest(manifest);
644
+ if (!base.valid || !base.value) {
645
+ return base;
646
+ }
647
+ const issues = [...base.issues];
648
+ const value = manifest;
649
+ const objectsById = new Map(
650
+ base.value.objects.map((object) => [object.id, object])
651
+ );
652
+ const anchorIds = /* @__PURE__ */ new Set();
653
+ const anchorsById = /* @__PURE__ */ new Map();
654
+ const focusScreenIds = /* @__PURE__ */ new Set();
655
+ let valid = true;
656
+ if (value.anchors !== void 0) {
657
+ if (!Array.isArray(value.anchors)) {
658
+ pushIssue2(issues, {
659
+ code: "invalid-type",
660
+ path: "$.anchors",
661
+ message: "anchors must be an array when present."
662
+ });
663
+ valid = false;
664
+ } else {
665
+ value.anchors.forEach((anchor, index) => {
666
+ const path = `$.anchors[${index}]`;
667
+ if (validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds)) {
668
+ anchorsById.set(anchor.id, anchor);
669
+ } else {
670
+ valid = false;
671
+ }
672
+ });
673
+ }
674
+ }
675
+ if (value.focusScreens !== void 0) {
676
+ if (!Array.isArray(value.focusScreens)) {
677
+ pushIssue2(issues, {
678
+ code: "invalid-type",
679
+ path: "$.focusScreens",
680
+ message: "focusScreens must be an array when present."
681
+ });
682
+ valid = false;
683
+ } else {
684
+ value.focusScreens.forEach((focusScreen, index) => {
685
+ if (!validateFocusScreenDefinition(
686
+ focusScreen,
687
+ `$.focusScreens[${index}]`,
688
+ issues,
689
+ objectsById,
690
+ anchorsById,
691
+ focusScreenIds
692
+ )) {
693
+ valid = false;
694
+ }
695
+ });
696
+ }
697
+ }
698
+ return {
699
+ valid,
700
+ issues,
701
+ value: valid ? value : void 0
702
+ };
703
+ }
704
+ function resolveSceneObjectAnchorById(manifest, anchorId) {
705
+ if (!isKebabId(anchorId)) {
706
+ return void 0;
707
+ }
708
+ return manifest.anchors?.find((anchor) => anchor.id === anchorId);
709
+ }
710
+ function resolveSceneObjectFocusScreenById(manifest, focusScreenId) {
711
+ if (!isKebabId(focusScreenId)) {
712
+ return void 0;
713
+ }
714
+ return manifest.focusScreens?.find((focusScreen) => focusScreen.id === focusScreenId);
715
+ }
716
+
406
717
  // src/resolve.ts
407
718
  function resolveSceneObjectState(manifest, objectId) {
408
719
  if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {
@@ -413,13 +724,17 @@ function resolveSceneObjectState(manifest, objectId) {
413
724
  );
414
725
  }
415
726
  export {
727
+ SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID,
416
728
  SCENE_OBJECT_RUNTIME_FLAG_ID,
417
729
  SCENE_OBJECT_SCHEMA_VERSION,
418
730
  createSceneObjectManifest,
731
+ resolveSceneObjectAnchorById,
419
732
  resolveSceneObjectById,
733
+ resolveSceneObjectFocusScreenById,
420
734
  resolveSceneObjectReferences,
421
735
  resolveSceneObjectState,
422
736
  validateSceneObjectManifest,
423
- validateSceneObjectObjectState
737
+ validateSceneObjectObjectState,
738
+ validateSceneObjectPlayerSystemManifest
424
739
  };
425
740
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/validation.ts","../src/resolve.ts"],"sourcesContent":["export const SCENE_OBJECT_SCHEMA_VERSION = \"1.0.0\";\nexport const SCENE_OBJECT_RUNTIME_FLAG_ID = \"scene.object.runtime.enabled\";\n\nexport type SceneObjectStateKind = \"idle\" | \"visible\" | \"hidden\" | \"disabled\";\n\nexport type SceneObjectCoordinateSpace =\n | \"normalized-viewport\"\n | \"pixel-viewport\"\n | \"world\"\n | \"local\";\n\nexport type SceneObjectUnits = \"ratio\" | \"pixels\";\n\nexport interface SceneObjectVector3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport interface SceneObjectTransform {\n translate: SceneObjectVector3;\n rotate: SceneObjectVector3;\n scale: SceneObjectVector3;\n}\n\nexport interface SceneObjectBounds {\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n unit: SceneObjectUnits;\n };\n depth?: number;\n coordinateSpace: SceneObjectCoordinateSpace;\n}\n\nexport interface SceneObjectPoint {\n id: string;\n x: number;\n y: number;\n z?: number;\n}\n\nexport interface SceneObjectAttachment {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n offset?: SceneObjectVector3;\n}\n\nexport type SceneObjectAttachmentPoint = SceneObjectPoint;\n\nexport interface SceneObjectObjectState {\n objectId: string;\n visible: boolean;\n tags?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface SceneObjectReference {\n objectId: string;\n pointId: string;\n}\n\nexport interface SceneObjectManifest {\n schemaVersion: string;\n objects: SceneObjectDefinition[];\n stateSnapshots?: SceneObjectObjectState[];\n}\n\nexport interface SceneObjectDefinition {\n id: string;\n name?: string;\n transform: SceneObjectTransform;\n bounds: SceneObjectBounds;\n attachmentPoints?: SceneObjectPoint[];\n attachments?: SceneObjectAttachment[];\n}\n\nexport type SceneObjectValidationCode =\n | \"required\"\n | \"invalid-type\"\n | \"invalid-value\"\n | \"invalid-id\"\n | \"duplicate-id\"\n | \"invalid-reference\"\n | \"missing-reference\";\n\nexport interface SceneObjectValidationIssue {\n code: SceneObjectValidationCode;\n path: string;\n message: string;\n}\n\nexport interface SceneObjectValidationResult<T> {\n valid: boolean;\n issues: SceneObjectValidationIssue[];\n value?: T;\n}\n\nexport interface SceneObjectResolutionRequest {\n manifest: SceneObjectManifest;\n objectId: string;\n}\n\nexport interface SceneObjectResolutionResult {\n manifest: SceneObjectManifest;\n object: SceneObjectDefinition;\n}\n","import {\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectBounds,\n type SceneObjectCoordinateSpace,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectDefinition,\n type SceneObjectAttachment,\n type SceneObjectResolutionRequest,\n type SceneObjectTransform,\n} from \"./types.js\";\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst COORDINATE_SPACES = new Set<SceneObjectCoordinateSpace>([\n \"normalized-viewport\",\n \"pixel-viewport\",\n \"world\",\n \"local\",\n]);\nconst UNITS = new Set([\"ratio\", \"pixels\"]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction validateTransform(\n value: SceneObjectTransform,\n path: string,\n issues: SceneObjectValidationIssue[],\n): boolean {\n const vectorChecks = [\"translate\", \"rotate\", \"scale\"] as const;\n let valid = true;\n\n for (const field of vectorChecks) {\n const vector = value[field];\n if (!vector || typeof vector !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.${field}`,\n message: `Expected a ${field} vector.`,\n });\n valid = false;\n continue;\n }\n\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n const raw = vector[axis];\n if (!isFiniteNumber(raw)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}.${axis}`,\n message: `Vector ${axis} must be finite.`,\n });\n valid = false;\n }\n }\n }\n\n return valid;\n}\n\nfunction validatePoint(point: SceneObjectPoint, path: string, issues: SceneObjectValidationIssue[]): boolean {\n let valid = true;\n\n if (!validateKebabId(point.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n for (const field of [\"x\", \"y\", \"z\"] as const) {\n const value = point[field];\n if (field === \"z\" && value === undefined) {\n continue;\n }\n if (!isFiniteNumber(value)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}`,\n message: \"Attachment point axis must be finite.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateBounds(bounds: SceneObjectBounds, path: string, issues: SceneObjectValidationIssue[]): boolean {\n if (!bounds || typeof bounds !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected bounds block.\" });\n return false;\n }\n\n if (!COORDINATE_SPACES.has(bounds.coordinateSpace as SceneObjectCoordinateSpace)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.coordinateSpace`,\n message: \"coordinateSpace must be normalized-viewport, pixel-viewport, world, or local.\",\n });\n return false;\n }\n\n const rect = bounds.rect;\n if (!rect || typeof rect !== \"object\") {\n pushIssue(issues, { code: \"required\", path: `${path}.rect`, message: \"Expected rect bounds.\" });\n return false;\n }\n\n if (!UNITS.has(rect.unit as string)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect.unit`,\n message: \"unit must be 'ratio' or 'pixels'.\",\n });\n return false;\n }\n\n let valid = true;\n for (const field of [\"x\", \"y\", \"width\", \"height\"] as const) {\n const value = rect[field];\n if (!isFiniteNumber(value) || value < 0) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.rect.${field}`,\n message: \"Rect fields must be finite non-negative numbers.\",\n });\n valid = false;\n }\n }\n\n if (rect.width === 0 || rect.height === 0) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect`,\n message: \"Rect width and height must be positive.\",\n });\n valid = false;\n }\n\n if (bounds.depth !== undefined && (!isFiniteNumber(bounds.depth) || bounds.depth < 0)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.depth`,\n message: \"depth must be a non-negative number.\",\n });\n valid = false;\n }\n\n return valid && isFiniteNumber(bounds.rect.width) && isFiniteNumber(bounds.rect.height);\n}\n\nfunction validateAttachmentTarget(\n attachment: {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n path: string,\n issues: SceneObjectValidationIssue[],\n seenPoints: Map<string, Set<string>>,\n): boolean {\n let valid = true;\n if (!validateKebabId(attachment.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourceObjectId, `${path}.sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetObjectId, `${path}.targetObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourcePointId, `${path}.sourcePointId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetPointId, `${path}.targetPointId`, issues)) {\n valid = false;\n }\n\n const sourcePoints = seenPoints.get(attachment.sourceObjectId);\n const targetPoints = seenPoints.get(attachment.targetObjectId);\n\n if (sourcePoints && !sourcePoints.has(attachment.sourcePointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.sourcePointId`,\n message: \"sourcePointId does not exist on source object.\",\n });\n valid = false;\n }\n\n if (targetPoints && !targetPoints.has(attachment.targetPointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.targetPointId`,\n message: \"targetPointId does not exist on target object.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const issues: SceneObjectValidationIssue[] = [];\n\n if (!manifest || typeof manifest !== \"object\") {\n return {\n valid: false,\n issues: [{ code: \"required\", path: \"$\", message: \"Expected a scene object manifest object.\" }],\n };\n }\n\n const value = manifest as Record<string, unknown>;\n let valid = true;\n\n if (value.schemaVersion !== SCENE_OBJECT_SCHEMA_VERSION) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: \"$.schemaVersion\",\n message: `schemaVersion must equal ${SCENE_OBJECT_SCHEMA_VERSION}.`,\n });\n valid = false;\n }\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: \"$.objects\",\n message: \"Manifest must contain at least one object.\",\n });\n return { valid: false, issues };\n }\n\n const objects = value.objects as SceneObjectDefinition[];\n const seenObjects = new Set<string>();\n const pointsByObject = new Map<string, Set<string>>();\n\n for (const [index, object] of objects.entries()) {\n const path = `$.objects[${index}]`;\n\n if (!object || typeof object !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected object definition.\" });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(object.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (seenObjects.has(object.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: `Duplicate object id '${object.id}' is not allowed.`,\n });\n valid = false;\n }\n seenObjects.add(object.id);\n\n if (!object.transform || typeof object.transform !== \"object\" || !validateTransform(object.transform as SceneObjectTransform, `${path}.transform`, issues)) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.transform`,\n message: \"Object must define a transform.\",\n });\n valid = false;\n }\n\n if (!object.bounds) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.bounds`,\n message: \"Object must define bounds.\",\n });\n valid = false;\n } else if (!validateBounds(object.bounds, `${path}.bounds`, issues)) {\n valid = false;\n }\n\n const attachmentPointIds = new Set<string>();\n const rawPoints = Array.isArray(object.attachmentPoints)\n ? object.attachmentPoints\n : [];\n for (const [pointIndex, point] of rawPoints.entries()) {\n if (!point || typeof point !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachmentPoints[${pointIndex}]`,\n message: \"Expected attachment point definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validatePoint(point as SceneObjectPoint, `${path}.attachmentPoints[${pointIndex}]`, issues)) {\n valid = false;\n continue;\n }\n\n const pointId = (point as SceneObjectPoint).id;\n if (attachmentPointIds.has(pointId)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachmentPoints[${pointIndex}].id`,\n message: `Duplicate attachment point '${pointId}' within object.`,\n });\n valid = false;\n }\n attachmentPointIds.add(pointId);\n }\n\n if (rawPoints.length > 0) {\n pointsByObject.set(object.id, attachmentPointIds);\n }\n\n if (Array.isArray(object.attachments)) {\n const attachmentIds = new Set<string>();\n for (const [attachmentIndex, attachment] of object.attachments.entries()) {\n if (!attachment || typeof attachment !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachments[${attachmentIndex}]`,\n message: \"Expected attachment definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId((attachment as SceneObjectAttachment).sourceObjectId, `${path}.attachments[${attachmentIndex}].sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!attachmentIds.has((attachment as { id?: string }).id ?? \"\")) {\n attachmentIds.add((attachment as { id?: string }).id ?? \"\");\n } else {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachments[${attachmentIndex}].id`,\n message: \"Duplicate attachment id.\",\n });\n valid = false;\n }\n\n if (\n !validateAttachmentTarget(\n attachment as {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n `${path}.attachments[${attachmentIndex}]`,\n issues,\n pointsByObject,\n )\n ) {\n valid = false;\n }\n }\n }\n }\n\n const objectIds = new Set(\n objects\n .filter((candidate): candidate is SceneObjectDefinition => Boolean(candidate && typeof candidate === \"object\"))\n .map((candidate) => candidate.id),\n );\n if (Array.isArray(value.stateSnapshots)) {\n for (const [stateIndex, state] of value.stateSnapshots.entries()) {\n const stateValue = state as SceneObjectObjectState;\n const path = `$.stateSnapshots[${stateIndex}]`;\n\n if (!stateValue || typeof stateValue !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected object state definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(stateValue.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!objectIds.has(stateValue.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"objectId does not reference an object in objects.\",\n });\n valid = false;\n }\n\n if (typeof stateValue.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.visible`,\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n }\n }\n\n return valid\n ? { valid: true, issues, value: manifest as SceneObjectManifest }\n : { valid: false, issues };\n}\n\nexport function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n const summary = result.issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \");\n throw new Error(`Invalid scene object manifest. ${summary}`);\n }\n\n return result.value;\n}\n\nexport function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState> {\n if (!state || typeof state !== \"object\") {\n return {\n valid: false,\n issues: [{\n code: \"required\",\n path: \"$\",\n message: \"Expected an object state.\",\n }],\n };\n }\n\n const value = state as Record<string, unknown>;\n const issues: SceneObjectValidationIssue[] = [];\n let valid = true;\n\n if (!validateKebabId(value.objectId, \"$.objectId\", issues)) {\n valid = false;\n }\n\n if (typeof value.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.visible\",\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n\n return valid\n ? { valid: true, issues, value: state as SceneObjectObjectState }\n : { valid: false, issues };\n}\n\nexport function resolveSceneObjectReferences(\n manifest: SceneObjectManifest,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n return { valid: false, issues: result.issues };\n }\n\n return { valid: true, issues: [], value: result.value };\n}\n\nexport function resolveSceneObjectById(\n requestOrManifest:\n | SceneObjectResolutionRequest\n | SceneObjectManifest,\n objectId?: string,\n): SceneObjectDefinition | undefined {\n const request: SceneObjectResolutionRequest = typeof objectId === \"string\"\n ? {\n manifest: requestOrManifest as SceneObjectManifest,\n objectId,\n }\n : requestOrManifest as SceneObjectResolutionRequest;\n\n const result = validateSceneObjectManifest(request.manifest);\n if (!result.valid || !result.value) {\n return undefined;\n }\n\n return result.value.objects.find((object) => object.id === request.objectId);\n}\n","import {\n SceneObjectManifest,\n SceneObjectObjectState,\n SceneObjectDefinition,\n} from \"./types.js\";\n\nexport function resolveSceneObjectState(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectObjectState | undefined {\n if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {\n return undefined;\n }\n\n return manifest.stateSnapshots.find(\n (snapshot) => snapshot.objectId === objectId,\n );\n}\n\nexport function resolveSceneObjectById(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectDefinition | undefined {\n return manifest.objects.find((object) => object.id === objectId);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/types.ts","../src/validation.ts","../src/player-system.ts","../src/resolve.ts"],"sourcesContent":["export const SCENE_OBJECT_SCHEMA_VERSION = \"1.0.0\";\nexport const SCENE_OBJECT_RUNTIME_FLAG_ID = \"scene.object.runtime.enabled\";\n\nexport type SceneObjectStateKind = \"idle\" | \"visible\" | \"hidden\" | \"disabled\";\n\nexport type SceneObjectCoordinateSpace =\n | \"normalized-viewport\"\n | \"pixel-viewport\"\n | \"world\"\n | \"local\";\n\nexport type SceneObjectUnits = \"ratio\" | \"pixels\";\n\nexport interface SceneObjectVector3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport interface SceneObjectTransform {\n translate: SceneObjectVector3;\n rotate: SceneObjectVector3;\n scale: SceneObjectVector3;\n}\n\nexport interface SceneObjectBounds {\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n unit: SceneObjectUnits;\n };\n depth?: number;\n coordinateSpace: SceneObjectCoordinateSpace;\n}\n\nexport interface SceneObjectPoint {\n id: string;\n x: number;\n y: number;\n z?: number;\n}\n\nexport interface SceneObjectAttachment {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n offset?: SceneObjectVector3;\n}\n\nexport type SceneObjectAttachmentPoint = SceneObjectPoint;\n\nexport interface SceneObjectObjectState {\n objectId: string;\n visible: boolean;\n tags?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface SceneObjectReference {\n objectId: string;\n pointId: string;\n}\n\nexport interface SceneObjectManifest {\n schemaVersion: string;\n objects: SceneObjectDefinition[];\n stateSnapshots?: SceneObjectObjectState[];\n}\n\nexport interface SceneObjectDefinition {\n id: string;\n name?: string;\n transform: SceneObjectTransform;\n bounds: SceneObjectBounds;\n attachmentPoints?: SceneObjectPoint[];\n attachments?: SceneObjectAttachment[];\n}\n\nexport type SceneObjectValidationCode =\n | \"required\"\n | \"invalid-type\"\n | \"invalid-value\"\n | \"invalid-id\"\n | \"duplicate-id\"\n | \"invalid-reference\"\n | \"missing-reference\";\n\nexport interface SceneObjectValidationIssue {\n code: SceneObjectValidationCode;\n path: string;\n message: string;\n}\n\nexport interface SceneObjectValidationResult<T> {\n valid: boolean;\n issues: SceneObjectValidationIssue[];\n value?: T;\n}\n\nexport interface SceneObjectResolutionRequest {\n manifest: SceneObjectManifest;\n objectId: string;\n}\n\nexport interface SceneObjectResolutionResult {\n manifest: SceneObjectManifest;\n object: SceneObjectDefinition;\n}\n","import {\n SCENE_OBJECT_SCHEMA_VERSION,\n type SceneObjectBounds,\n type SceneObjectCoordinateSpace,\n type SceneObjectManifest,\n type SceneObjectObjectState,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectDefinition,\n type SceneObjectAttachment,\n type SceneObjectResolutionRequest,\n type SceneObjectTransform,\n} from \"./types.js\";\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst COORDINATE_SPACES = new Set<SceneObjectCoordinateSpace>([\n \"normalized-viewport\",\n \"pixel-viewport\",\n \"world\",\n \"local\",\n]);\nconst UNITS = new Set([\"ratio\", \"pixels\"]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction validateTransform(\n value: SceneObjectTransform,\n path: string,\n issues: SceneObjectValidationIssue[],\n): boolean {\n const vectorChecks = [\"translate\", \"rotate\", \"scale\"] as const;\n let valid = true;\n\n for (const field of vectorChecks) {\n const vector = value[field];\n if (!vector || typeof vector !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.${field}`,\n message: `Expected a ${field} vector.`,\n });\n valid = false;\n continue;\n }\n\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n const raw = vector[axis];\n if (!isFiniteNumber(raw)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}.${axis}`,\n message: `Vector ${axis} must be finite.`,\n });\n valid = false;\n }\n }\n }\n\n return valid;\n}\n\nfunction validatePoint(point: SceneObjectPoint, path: string, issues: SceneObjectValidationIssue[]): boolean {\n let valid = true;\n\n if (!validateKebabId(point.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n for (const field of [\"x\", \"y\", \"z\"] as const) {\n const value = point[field];\n if (field === \"z\" && value === undefined) {\n continue;\n }\n if (!isFiniteNumber(value)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.${field}`,\n message: \"Attachment point axis must be finite.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateBounds(bounds: SceneObjectBounds, path: string, issues: SceneObjectValidationIssue[]): boolean {\n if (!bounds || typeof bounds !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected bounds block.\" });\n return false;\n }\n\n if (!COORDINATE_SPACES.has(bounds.coordinateSpace as SceneObjectCoordinateSpace)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.coordinateSpace`,\n message: \"coordinateSpace must be normalized-viewport, pixel-viewport, world, or local.\",\n });\n return false;\n }\n\n const rect = bounds.rect;\n if (!rect || typeof rect !== \"object\") {\n pushIssue(issues, { code: \"required\", path: `${path}.rect`, message: \"Expected rect bounds.\" });\n return false;\n }\n\n if (!UNITS.has(rect.unit as string)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect.unit`,\n message: \"unit must be 'ratio' or 'pixels'.\",\n });\n return false;\n }\n\n let valid = true;\n for (const field of [\"x\", \"y\", \"width\", \"height\"] as const) {\n const value = rect[field];\n if (!isFiniteNumber(value) || value < 0) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.rect.${field}`,\n message: \"Rect fields must be finite non-negative numbers.\",\n });\n valid = false;\n }\n }\n\n if (rect.width === 0 || rect.height === 0) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.rect`,\n message: \"Rect width and height must be positive.\",\n });\n valid = false;\n }\n\n if (bounds.depth !== undefined && (!isFiniteNumber(bounds.depth) || bounds.depth < 0)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.depth`,\n message: \"depth must be a non-negative number.\",\n });\n valid = false;\n }\n\n return valid && isFiniteNumber(bounds.rect.width) && isFiniteNumber(bounds.rect.height);\n}\n\nfunction validateAttachmentTarget(\n attachment: {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n path: string,\n issues: SceneObjectValidationIssue[],\n seenPoints: Map<string, Set<string>>,\n): boolean {\n let valid = true;\n if (!validateKebabId(attachment.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourceObjectId, `${path}.sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetObjectId, `${path}.targetObjectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.sourcePointId, `${path}.sourcePointId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(attachment.targetPointId, `${path}.targetPointId`, issues)) {\n valid = false;\n }\n\n const sourcePoints = seenPoints.get(attachment.sourceObjectId);\n const targetPoints = seenPoints.get(attachment.targetObjectId);\n\n if (sourcePoints && !sourcePoints.has(attachment.sourcePointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.sourcePointId`,\n message: \"sourcePointId does not exist on source object.\",\n });\n valid = false;\n }\n\n if (targetPoints && !targetPoints.has(attachment.targetPointId)) {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.targetPointId`,\n message: \"targetPointId does not exist on target object.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const issues: SceneObjectValidationIssue[] = [];\n\n if (!manifest || typeof manifest !== \"object\") {\n return {\n valid: false,\n issues: [{ code: \"required\", path: \"$\", message: \"Expected a scene object manifest object.\" }],\n };\n }\n\n const value = manifest as Record<string, unknown>;\n let valid = true;\n\n if (value.schemaVersion !== SCENE_OBJECT_SCHEMA_VERSION) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: \"$.schemaVersion\",\n message: `schemaVersion must equal ${SCENE_OBJECT_SCHEMA_VERSION}.`,\n });\n valid = false;\n }\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: \"$.objects\",\n message: \"Manifest must contain at least one object.\",\n });\n return { valid: false, issues };\n }\n\n const objects = value.objects as SceneObjectDefinition[];\n const seenObjects = new Set<string>();\n const pointsByObject = new Map<string, Set<string>>();\n\n for (const [index, object] of objects.entries()) {\n const path = `$.objects[${index}]`;\n\n if (!object || typeof object !== \"object\") {\n pushIssue(issues, { code: \"required\", path, message: \"Expected object definition.\" });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(object.id, `${path}.id`, issues)) {\n valid = false;\n }\n\n if (seenObjects.has(object.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: `Duplicate object id '${object.id}' is not allowed.`,\n });\n valid = false;\n }\n seenObjects.add(object.id);\n\n if (!object.transform || typeof object.transform !== \"object\" || !validateTransform(object.transform as SceneObjectTransform, `${path}.transform`, issues)) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.transform`,\n message: \"Object must define a transform.\",\n });\n valid = false;\n }\n\n if (!object.bounds) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.bounds`,\n message: \"Object must define bounds.\",\n });\n valid = false;\n } else if (!validateBounds(object.bounds, `${path}.bounds`, issues)) {\n valid = false;\n }\n\n const attachmentPointIds = new Set<string>();\n const rawPoints = Array.isArray(object.attachmentPoints)\n ? object.attachmentPoints\n : [];\n for (const [pointIndex, point] of rawPoints.entries()) {\n if (!point || typeof point !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachmentPoints[${pointIndex}]`,\n message: \"Expected attachment point definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validatePoint(point as SceneObjectPoint, `${path}.attachmentPoints[${pointIndex}]`, issues)) {\n valid = false;\n continue;\n }\n\n const pointId = (point as SceneObjectPoint).id;\n if (attachmentPointIds.has(pointId)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachmentPoints[${pointIndex}].id`,\n message: `Duplicate attachment point '${pointId}' within object.`,\n });\n valid = false;\n }\n attachmentPointIds.add(pointId);\n }\n\n if (rawPoints.length > 0) {\n pointsByObject.set(object.id, attachmentPointIds);\n }\n\n if (Array.isArray(object.attachments)) {\n const attachmentIds = new Set<string>();\n for (const [attachmentIndex, attachment] of object.attachments.entries()) {\n if (!attachment || typeof attachment !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.attachments[${attachmentIndex}]`,\n message: \"Expected attachment definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId((attachment as SceneObjectAttachment).sourceObjectId, `${path}.attachments[${attachmentIndex}].sourceObjectId`, issues)) {\n valid = false;\n }\n\n if (!attachmentIds.has((attachment as { id?: string }).id ?? \"\")) {\n attachmentIds.add((attachment as { id?: string }).id ?? \"\");\n } else {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.attachments[${attachmentIndex}].id`,\n message: \"Duplicate attachment id.\",\n });\n valid = false;\n }\n\n if (\n !validateAttachmentTarget(\n attachment as {\n id: string;\n sourceObjectId: string;\n sourcePointId: string;\n targetObjectId: string;\n targetPointId: string;\n },\n `${path}.attachments[${attachmentIndex}]`,\n issues,\n pointsByObject,\n )\n ) {\n valid = false;\n }\n }\n }\n }\n\n const objectIds = new Set(\n objects\n .filter((candidate): candidate is SceneObjectDefinition => Boolean(candidate && typeof candidate === \"object\"))\n .map((candidate) => candidate.id),\n );\n if (Array.isArray(value.stateSnapshots)) {\n for (const [stateIndex, state] of value.stateSnapshots.entries()) {\n const stateValue = state as SceneObjectObjectState;\n const path = `$.stateSnapshots[${stateIndex}]`;\n\n if (!stateValue || typeof stateValue !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected object state definition.\",\n });\n valid = false;\n continue;\n }\n\n if (!validateKebabId(stateValue.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!objectIds.has(stateValue.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"objectId does not reference an object in objects.\",\n });\n valid = false;\n }\n\n if (typeof stateValue.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.visible`,\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n }\n }\n\n return valid\n ? { valid: true, issues, value: manifest as SceneObjectManifest }\n : { valid: false, issues };\n}\n\nexport function createSceneObjectManifest(manifest: SceneObjectManifest): SceneObjectManifest {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n const summary = result.issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \");\n throw new Error(`Invalid scene object manifest. ${summary}`);\n }\n\n return result.value;\n}\n\nexport function validateSceneObjectObjectState(state: unknown): SceneObjectValidationResult<SceneObjectObjectState> {\n if (!state || typeof state !== \"object\") {\n return {\n valid: false,\n issues: [{\n code: \"required\",\n path: \"$\",\n message: \"Expected an object state.\",\n }],\n };\n }\n\n const value = state as Record<string, unknown>;\n const issues: SceneObjectValidationIssue[] = [];\n let valid = true;\n\n if (!validateKebabId(value.objectId, \"$.objectId\", issues)) {\n valid = false;\n }\n\n if (typeof value.visible !== \"boolean\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.visible\",\n message: \"visible must be a boolean.\",\n });\n valid = false;\n }\n\n return valid\n ? { valid: true, issues, value: state as SceneObjectObjectState }\n : { valid: false, issues };\n}\n\nexport function resolveSceneObjectReferences(\n manifest: SceneObjectManifest,\n): SceneObjectValidationResult<SceneObjectManifest> {\n const result = validateSceneObjectManifest(manifest);\n if (!result.valid || !result.value) {\n return { valid: false, issues: result.issues };\n }\n\n return { valid: true, issues: [], value: result.value };\n}\n\nexport function resolveSceneObjectById(\n requestOrManifest:\n | SceneObjectResolutionRequest\n | SceneObjectManifest,\n objectId?: string,\n): SceneObjectDefinition | undefined {\n const request: SceneObjectResolutionRequest = typeof objectId === \"string\"\n ? {\n manifest: requestOrManifest as SceneObjectManifest,\n objectId,\n }\n : requestOrManifest as SceneObjectResolutionRequest;\n\n const result = validateSceneObjectManifest(request.manifest);\n if (!result.valid || !result.value) {\n return undefined;\n }\n\n return result.value.objects.find((object) => object.id === request.objectId);\n}\n","import { type SceneObjectDefinition,\n type SceneObjectManifest,\n type SceneObjectPoint,\n type SceneObjectValidationIssue,\n type SceneObjectValidationResult,\n type SceneObjectVector3,\n} from \"./types.js\";\nimport { validateSceneObjectManifest } from \"./validation.js\";\n\nexport const SCENE_OBJECT_PLAYER_SYSTEM_INTERFACE_FLAG_ID =\n \"isekai.player-system.interface.enabled\";\n\nexport type SceneObjectAnchorKind =\n | \"target\"\n | \"focus-pane\"\n | \"localized-alert\"\n | \"line-of-sight-popup\";\n\nexport type SceneObjectAnchorVisibility =\n | \"always\"\n | \"combat-safe\"\n | \"focused-only\"\n | \"line-of-sight\";\n\nexport interface SceneObjectAnchorDefinition {\n id: string;\n kind: SceneObjectAnchorKind;\n objectId: string;\n pointId: string;\n visibility: SceneObjectAnchorVisibility;\n localeKey?: string;\n offset?: SceneObjectVector3;\n tags?: string[];\n}\n\nexport interface SceneObjectFocusScreenDefinition {\n id: string;\n objectId: string;\n anchorId: string;\n paneId: string;\n variant: \"single-pane\" | \"multi-pane\" | \"combat-safe\";\n headingKey?: string;\n}\n\nexport interface SceneObjectPlayerSystemManifest extends SceneObjectManifest {\n anchors?: SceneObjectAnchorDefinition[];\n focusScreens?: SceneObjectFocusScreenDefinition[];\n}\n\nconst ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst ANCHOR_KINDS = new Set<SceneObjectAnchorKind>([\n \"target\",\n \"focus-pane\",\n \"localized-alert\",\n \"line-of-sight-popup\",\n]);\nconst ANCHOR_VISIBILITIES = new Set<SceneObjectAnchorVisibility>([\n \"always\",\n \"combat-safe\",\n \"focused-only\",\n \"line-of-sight\",\n]);\nconst FOCUS_SCREEN_VARIANTS = new Set<SceneObjectFocusScreenDefinition[\"variant\"]>([\n \"single-pane\",\n \"multi-pane\",\n \"combat-safe\",\n]);\n\nfunction pushIssue(\n issues: SceneObjectValidationIssue[],\n issue: SceneObjectValidationIssue,\n): void {\n issues.push(issue);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isKebabId(value: unknown): value is string {\n return typeof value === \"string\" && ID_PATTERN.test(value);\n}\n\nfunction validateKebabId(\n value: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n): value is string {\n if (typeof value !== \"string\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path,\n message: \"Expected a string identifier.\",\n });\n return false;\n }\n\n if (!ID_PATTERN.test(value)) {\n pushIssue(issues, {\n code: \"invalid-id\",\n path,\n message: \"Identifiers must be kebab-case tokens.\",\n });\n return false;\n }\n\n return true;\n}\n\nfunction findObjectPoint(\n object: SceneObjectDefinition | undefined,\n pointId: string,\n): SceneObjectPoint | undefined {\n return object?.attachmentPoints?.find((point) => point.id === pointId);\n}\n\nfunction validateAnchorDefinition(\n anchor: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n objectsById: Map<string, SceneObjectDefinition>,\n anchorIds: Set<string>,\n): anchor is SceneObjectAnchorDefinition {\n if (!anchor || typeof anchor !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected anchor definition object.\",\n });\n return false;\n }\n\n const value = anchor as Record<string, unknown>;\n let valid = true;\n\n if (!validateKebabId(value.id, `${path}.id`, issues)) {\n valid = false;\n } else if (anchorIds.has(value.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: \"Anchor identifiers must be unique.\",\n });\n valid = false;\n } else {\n anchorIds.add(value.id);\n }\n\n if (!validateKebabId(value.objectId, `${path}.objectId`, issues)) {\n valid = false;\n }\n\n if (!validateKebabId(value.pointId, `${path}.pointId`, issues)) {\n valid = false;\n }\n\n if (!ANCHOR_KINDS.has(value.kind as SceneObjectAnchorKind)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.kind`,\n message:\n \"Anchor kind must be target, focus-pane, localized-alert, or line-of-sight-popup.\",\n });\n valid = false;\n }\n\n if (!ANCHOR_VISIBILITIES.has(value.visibility as SceneObjectAnchorVisibility)) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.visibility`,\n message:\n \"Anchor visibility must be always, combat-safe, focused-only, or line-of-sight.\",\n });\n valid = false;\n }\n\n const object =\n typeof value.objectId === \"string\"\n ? objectsById.get(value.objectId)\n : undefined;\n if (!object) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"Anchor objectId must reference an existing scene object.\",\n });\n valid = false;\n } else if (\n typeof value.pointId === \"string\" &&\n !findObjectPoint(object, value.pointId)\n ) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.pointId`,\n message:\n \"Anchor pointId must reference an attachment point on the target object.\",\n });\n valid = false;\n }\n\n if (value.kind === \"localized-alert\") {\n if (typeof value.localeKey !== \"string\" || value.localeKey.trim().length === 0) {\n pushIssue(issues, {\n code: \"required\",\n path: `${path}.localeKey`,\n message: \"localized-alert anchors require a localeKey.\",\n });\n valid = false;\n }\n } else if (\n value.localeKey !== undefined &&\n (typeof value.localeKey !== \"string\" || value.localeKey.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.localeKey`,\n message: \"localeKey must be a non-empty string when present.\",\n });\n valid = false;\n }\n\n if (value.offset !== undefined) {\n if (!value.offset || typeof value.offset !== \"object\") {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.offset`,\n message: \"offset must be a finite x/y/z vector when present.\",\n });\n valid = false;\n } else {\n for (const axis of [\"x\", \"y\", \"z\"] as const) {\n if (!isFiniteNumber((value.offset as Record<string, unknown>)[axis])) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.offset.${axis}`,\n message: \"offset axes must be finite numbers.\",\n });\n valid = false;\n }\n }\n }\n }\n\n if (value.tags !== undefined) {\n if (\n !Array.isArray(value.tags) ||\n value.tags.some((tag) => typeof tag !== \"string\" || tag.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.tags`,\n message: \"tags must be an array of non-empty strings when present.\",\n });\n valid = false;\n }\n }\n\n return valid;\n}\n\nfunction validateFocusScreenDefinition(\n focusScreen: unknown,\n path: string,\n issues: SceneObjectValidationIssue[],\n objectsById: Map<string, SceneObjectDefinition>,\n anchorsById: Map<string, SceneObjectAnchorDefinition>,\n focusScreenIds: Set<string>,\n): focusScreen is SceneObjectFocusScreenDefinition {\n if (!focusScreen || typeof focusScreen !== \"object\") {\n pushIssue(issues, {\n code: \"required\",\n path,\n message: \"Expected focus-screen definition object.\",\n });\n return false;\n }\n\n const value = focusScreen as Record<string, unknown>;\n let valid = true;\n\n if (!validateKebabId(value.id, `${path}.id`, issues)) {\n valid = false;\n } else if (focusScreenIds.has(value.id)) {\n pushIssue(issues, {\n code: \"duplicate-id\",\n path: `${path}.id`,\n message: \"Focus-screen identifiers must be unique.\",\n });\n valid = false;\n } else {\n focusScreenIds.add(value.id);\n }\n\n if (!validateKebabId(value.objectId, `${path}.objectId`, issues)) {\n valid = false;\n } else if (!objectsById.has(value.objectId)) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.objectId`,\n message: \"Focus-screen objectId must reference an existing scene object.\",\n });\n valid = false;\n }\n\n if (!validateKebabId(value.anchorId, `${path}.anchorId`, issues)) {\n valid = false;\n } else {\n const anchor = anchorsById.get(value.anchorId);\n if (!anchor) {\n pushIssue(issues, {\n code: \"missing-reference\",\n path: `${path}.anchorId`,\n message: \"Focus-screen anchorId must reference an exported anchor.\",\n });\n valid = false;\n } else if (anchor.kind !== \"focus-pane\") {\n pushIssue(issues, {\n code: \"invalid-reference\",\n path: `${path}.anchorId`,\n message: \"Focus screens must bind to focus-pane anchors.\",\n });\n valid = false;\n }\n }\n\n if (!validateKebabId(value.paneId, `${path}.paneId`, issues)) {\n valid = false;\n }\n\n if (!FOCUS_SCREEN_VARIANTS.has(value.variant as SceneObjectFocusScreenDefinition[\"variant\"])) {\n pushIssue(issues, {\n code: \"invalid-value\",\n path: `${path}.variant`,\n message: \"Focus-screen variant must be single-pane, multi-pane, or combat-safe.\",\n });\n valid = false;\n }\n\n if (\n value.headingKey !== undefined &&\n (typeof value.headingKey !== \"string\" || value.headingKey.trim().length === 0)\n ) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: `${path}.headingKey`,\n message: \"headingKey must be a non-empty string when present.\",\n });\n valid = false;\n }\n\n return valid;\n}\n\nexport function validateSceneObjectPlayerSystemManifest(\n manifest: unknown,\n): SceneObjectValidationResult<SceneObjectPlayerSystemManifest> {\n const base = validateSceneObjectManifest(manifest);\n if (!base.valid || !base.value) {\n return base as SceneObjectValidationResult<SceneObjectPlayerSystemManifest>;\n }\n\n const issues = [...base.issues];\n const value = manifest as SceneObjectPlayerSystemManifest;\n const objectsById = new Map(\n base.value.objects.map((object) => [object.id, object] as const),\n );\n const anchorIds = new Set<string>();\n const anchorsById = new Map<string, SceneObjectAnchorDefinition>();\n const focusScreenIds = new Set<string>();\n let valid = true;\n\n if (value.anchors !== undefined) {\n if (!Array.isArray(value.anchors)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.anchors\",\n message: \"anchors must be an array when present.\",\n });\n valid = false;\n } else {\n value.anchors.forEach((anchor, index) => {\n const path = `$.anchors[${index}]`;\n if (\n validateAnchorDefinition(anchor, path, issues, objectsById, anchorIds)\n ) {\n anchorsById.set(anchor.id, anchor);\n } else {\n valid = false;\n }\n });\n }\n }\n\n if (value.focusScreens !== undefined) {\n if (!Array.isArray(value.focusScreens)) {\n pushIssue(issues, {\n code: \"invalid-type\",\n path: \"$.focusScreens\",\n message: \"focusScreens must be an array when present.\",\n });\n valid = false;\n } else {\n value.focusScreens.forEach((focusScreen, index) => {\n if (\n !validateFocusScreenDefinition(\n focusScreen,\n `$.focusScreens[${index}]`,\n issues,\n objectsById,\n anchorsById,\n focusScreenIds,\n )\n ) {\n valid = false;\n }\n });\n }\n }\n\n return {\n valid,\n issues,\n value: valid ? value : undefined,\n };\n}\n\nexport function resolveSceneObjectAnchorById(\n manifest: SceneObjectPlayerSystemManifest,\n anchorId: string,\n): SceneObjectAnchorDefinition | undefined {\n if (!isKebabId(anchorId)) {\n return undefined;\n }\n\n return manifest.anchors?.find((anchor) => anchor.id === anchorId);\n}\n\nexport function resolveSceneObjectFocusScreenById(\n manifest: SceneObjectPlayerSystemManifest,\n focusScreenId: string,\n): SceneObjectFocusScreenDefinition | undefined {\n if (!isKebabId(focusScreenId)) {\n return undefined;\n }\n\n return manifest.focusScreens?.find((focusScreen) => focusScreen.id === focusScreenId);\n}\n","import {\n SceneObjectManifest,\n SceneObjectObjectState,\n SceneObjectDefinition,\n} from \"./types.js\";\n\nexport function resolveSceneObjectState(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectObjectState | undefined {\n if (!manifest.stateSnapshots || !Array.isArray(manifest.stateSnapshots)) {\n return undefined;\n }\n\n return manifest.stateSnapshots.find(\n (snapshot) => snapshot.objectId === objectId,\n );\n}\n\nexport function resolveSceneObjectById(\n manifest: SceneObjectManifest,\n objectId: string,\n): SceneObjectDefinition | undefined {\n return manifest.objects.find((object) => object.id === objectId);\n}\n"],"mappings":"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","names":["ID_PATTERN","pushIssue","isFiniteNumber","validateKebabId"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/scene-object",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Reusable scene-object transforms, bounds, attachment points, and snapshot contracts",
5
5
  "type": "module",
6
6
  "sideEffects": false,