@prometheus-ags/entity-graph-core 3.0.5 → 3.2.0

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/dist/index.mjs CHANGED
@@ -1,13 +1,6 @@
1
+ import { graphStore, useGraphStore, subscribeDevtoolsEvent, getGraphDevtoolsCompatibilityDelegate, subscribeGraphDevtoolsCompatibility, matchesFilter, matchesSearch, compareEntities, emitLegacyDevtoolsEvent, __require } from './chunk-BE3BMRKF.mjs';
2
+ export { EMPTY_ENTITY_STATE, EMPTY_IDS, EMPTY_LIST_STATE, EMPTY_SYNC_METADATA, applyView, attachGlobalListeners, cascadeInvalidation, checkCompleteness, compareEntities, configureEngine, createGraphStore, dedupe, fetchEntity, fetchList, findInsertionIndex, getActiveSubscriberCount, getEngineOptions, getMergeStrategy, getSchema, graphStore, hasMergeStrategy, lwwStrategy, matchesFilter, matchesSearch, readRelations, registerMergeStrategy, registerSchema, registerSubscriber, serializeKey, setDefaultMergeStrategy, startGarbageCollector, stopGarbageCollector, subscribeDevtoolsEvent, subscribeSubscriberStats, unregisterSubscriber, useGraphStore } from './chunk-BE3BMRKF.mjs';
1
3
  import { createStore } from 'zustand/vanilla';
2
- import { subscribeWithSelector } from 'zustand/middleware';
3
- import { immer } from 'zustand/middleware/immer';
4
-
5
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
6
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
7
- }) : x)(function(x) {
8
- if (typeof require !== "undefined") return require.apply(this, arguments);
9
- throw Error('Dynamic require of "' + x + '" is not supported');
10
- });
11
4
 
12
5
  // src/errors.ts
13
6
  var TerminalError = class _TerminalError extends Error {
@@ -494,506 +487,6 @@ function mapPostgrestError(error, status) {
494
487
  return toEntityError(error);
495
488
  }
496
489
 
497
- // src/merge/lww.ts
498
- var lwwStrategy = (prev, next) => {
499
- return prev ? { ...prev, ...next } : { ...next };
500
- };
501
-
502
- // src/merge/registry.ts
503
- var byType = /* @__PURE__ */ new Map();
504
- var globalDefault = null;
505
- function registerMergeStrategy(type, strategy) {
506
- byType.set(type, strategy);
507
- }
508
- function setDefaultMergeStrategy(strategy) {
509
- globalDefault = strategy;
510
- }
511
- function getMergeStrategy(type) {
512
- return byType.get(type) ?? globalDefault ?? lwwStrategy;
513
- }
514
- function hasMergeStrategy(type) {
515
- return byType.has(type) || globalDefault !== null;
516
- }
517
-
518
- // src/view/evaluator.ts
519
- function matchesFilter(entity, filter) {
520
- if (Array.isArray(filter)) return filter.every((clause) => matchesClause(entity, clause));
521
- return matchesGroup(entity, filter);
522
- }
523
- function matchesGroup(entity, group) {
524
- const { logic, clauses } = group;
525
- if (logic === "and") return clauses.every((c) => "logic" in c ? matchesGroup(entity, c) : matchesClause(entity, c));
526
- return clauses.some((c) => "logic" in c ? matchesGroup(entity, c) : matchesClause(entity, c));
527
- }
528
- function matchesClause(entity, clause) {
529
- const { field, op, value, predicate } = clause;
530
- const fv = getNestedValue(entity, field);
531
- switch (op) {
532
- case "eq":
533
- return fv === value;
534
- case "neq":
535
- return fv !== value;
536
- case "gt":
537
- return fv > value;
538
- case "gte":
539
- return fv >= value;
540
- case "lt":
541
- return fv < value;
542
- case "lte":
543
- return fv <= value;
544
- case "in":
545
- return Array.isArray(value) && value.includes(fv);
546
- case "nin":
547
- return Array.isArray(value) && !value.includes(fv);
548
- case "isNull":
549
- return fv == null;
550
- case "isNotNull":
551
- return fv != null;
552
- case "contains":
553
- return typeof fv === "string" && typeof value === "string" && fv.toLowerCase().includes(value.toLowerCase());
554
- case "startsWith":
555
- return typeof fv === "string" && typeof value === "string" && fv.toLowerCase().startsWith(value.toLowerCase());
556
- case "endsWith":
557
- return typeof fv === "string" && typeof value === "string" && fv.toLowerCase().endsWith(value.toLowerCase());
558
- case "between": {
559
- const [lo, hi] = value;
560
- return fv >= lo && fv <= hi;
561
- }
562
- case "arrayContains":
563
- return Array.isArray(fv) && fv.includes(value);
564
- case "arrayOverlaps":
565
- return Array.isArray(fv) && Array.isArray(value) && value.some((v) => fv.includes(v));
566
- case "matches":
567
- return typeof fv === "string" && new RegExp(value).test(fv);
568
- case "custom":
569
- return predicate ? predicate(fv, entity) : true;
570
- default:
571
- return true;
572
- }
573
- }
574
- function matchesSearch(entity, query, fields) {
575
- if (!query.trim()) return true;
576
- const lq = query.toLowerCase();
577
- return fields.some((field) => {
578
- const v = getNestedValue(entity, field);
579
- return typeof v === "string" && v.toLowerCase().includes(lq);
580
- });
581
- }
582
- function compareEntities(a, b, sort) {
583
- for (const clause of sort) {
584
- const r = compareByClause(a, b, clause);
585
- if (r !== 0) return r;
586
- }
587
- return 0;
588
- }
589
- function compareByClause(a, b, clause) {
590
- const { field, direction, nulls = "last", comparator } = clause;
591
- const av = getNestedValue(a, field);
592
- const bv = getNestedValue(b, field);
593
- const aNull = av == null;
594
- const bNull = bv == null;
595
- if (aNull && bNull) return 0;
596
- if (aNull) return nulls === "first" ? -1 : 1;
597
- if (bNull) return nulls === "first" ? 1 : -1;
598
- let cmp;
599
- if (comparator) cmp = comparator(av, bv);
600
- else if (typeof av === "string" && typeof bv === "string") cmp = av.localeCompare(bv, void 0, { sensitivity: "base", numeric: true });
601
- else if (typeof av === "number" && typeof bv === "number") cmp = av - bv;
602
- else cmp = String(av).localeCompare(String(bv));
603
- return direction === "desc" ? -cmp : cmp;
604
- }
605
- function findInsertionIndex(entity, sortedIds, getEntity, sort) {
606
- let lo = 0;
607
- let hi = sortedIds.length;
608
- while (lo < hi) {
609
- const mid = lo + hi >>> 1;
610
- const me = getEntity(sortedIds[mid]);
611
- if (!me) {
612
- lo = mid + 1;
613
- continue;
614
- }
615
- if (compareEntities(entity, me, sort) <= 0) hi = mid;
616
- else lo = mid + 1;
617
- }
618
- return lo;
619
- }
620
- function applyView(ids, getEntity, filter, sort, search) {
621
- let entries = [];
622
- for (const id of ids) {
623
- const entity = getEntity(id);
624
- if (!entity) continue;
625
- entries.push({ id, entity });
626
- }
627
- if (filter && entries.length > 0) entries = entries.filter(({ entity }) => matchesFilter(entity, filter));
628
- if (search?.query) entries = entries.filter(({ entity }) => matchesSearch(entity, search.query, search.fields));
629
- if (sort && sort.length > 0) entries.sort((a, b) => compareEntities(a.entity, b.entity, sort));
630
- return entries.map((e) => e.id);
631
- }
632
- function checkCompleteness(loadedCount, total, hasNextPage) {
633
- if (!hasNextPage && total !== null && loadedCount >= total) return { isComplete: true, reason: "all-loaded" };
634
- if (hasNextPage) return { isComplete: false, reason: "has-more-pages" };
635
- return { isComplete: true, reason: "no-more-pages" };
636
- }
637
- function getNestedValue(obj, path) {
638
- const parts = path.replace(/\[(\d+)\]/g, ".$1").split(".");
639
- let current = obj;
640
- for (const part of parts) {
641
- if (current == null || typeof current !== "object") return void 0;
642
- current = current[part];
643
- }
644
- return current;
645
- }
646
-
647
- // src/graph.ts
648
- var EMPTY_IDS = [];
649
- var EMPTY_ENTITY_STATE = {
650
- isFetching: false,
651
- lastFetched: null,
652
- error: null,
653
- stale: false
654
- };
655
- var EMPTY_SYNC_METADATA = {
656
- synced: true,
657
- origin: "server",
658
- updatedAt: null
659
- };
660
- var EMPTY_LIST_STATE = {
661
- ids: EMPTY_IDS,
662
- total: null,
663
- nextCursor: null,
664
- prevCursor: null,
665
- hasNextPage: false,
666
- hasPrevPage: false,
667
- isFetching: false,
668
- isFetchingMore: false,
669
- error: null,
670
- lastError: null,
671
- lastFetched: null,
672
- stale: false,
673
- currentPage: null,
674
- pageSize: null
675
- };
676
- function defaultEntityState() {
677
- return { ...EMPTY_ENTITY_STATE };
678
- }
679
- function defaultSyncMetadata() {
680
- return { ...EMPTY_SYNC_METADATA };
681
- }
682
- function defaultListState() {
683
- return { ...EMPTY_LIST_STATE, ids: [] };
684
- }
685
- function ek(type, id) {
686
- return `${type}:${id}`;
687
- }
688
- var snapshotCache = /* @__PURE__ */ new Map();
689
- function readCachedEntitySnapshot(type, id, base, patch, metadata) {
690
- const key = ek(type, id);
691
- const cached = snapshotCache.get(key);
692
- if (cached && cached.base === base && cached.patch === patch && cached.metadata === metadata) {
693
- return cached.snapshot;
694
- }
695
- const snapshot = {
696
- ...patch ? { ...base, ...patch } : base,
697
- $synced: metadata.synced,
698
- $origin: metadata.origin,
699
- $updatedAt: metadata.updatedAt
700
- };
701
- snapshotCache.set(key, { base, patch, metadata, snapshot });
702
- return snapshot;
703
- }
704
- function createGraphStore() {
705
- return createStore()(
706
- subscribeWithSelector(
707
- immer((set, get) => ({
708
- entities: {},
709
- patches: {},
710
- entityStates: {},
711
- syncMetadata: {},
712
- lists: {},
713
- upsertEntity: (type, id, data) => set((s) => {
714
- if (!s.entities[type]) s.entities[type] = {};
715
- const key = ek(type, id);
716
- const strategy = getMergeStrategy(type);
717
- const ctx = { type, id, origin: s.syncMetadata[key]?.origin ?? "server", updatedAt: Date.now() };
718
- s.entities[type][id] = strategy(s.entities[type][id], data, ctx);
719
- if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
720
- }),
721
- upsertEntities: (type, entries) => set((s) => {
722
- if (!s.entities[type]) s.entities[type] = {};
723
- const strategy = getMergeStrategy(type);
724
- for (const { id, data } of entries) {
725
- const key = ek(type, id);
726
- const ctx = { type, id, origin: s.syncMetadata[key]?.origin ?? "server", updatedAt: Date.now() };
727
- s.entities[type][id] = strategy(s.entities[type][id], data, ctx);
728
- if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
729
- }
730
- }),
731
- ingestFetchedList: (type, entries, options = {}) => set((s) => {
732
- const fetchedAt = Date.now();
733
- const ids = entries.map(({ id }) => id);
734
- const batches = [
735
- { type, entries },
736
- ...options.sideBatches ?? []
737
- ];
738
- const origins = /* @__PURE__ */ new Map();
739
- for (const batch of batches) {
740
- if (!s.entities[batch.type]) s.entities[batch.type] = {};
741
- for (const { id } of batch.entries) {
742
- const key = ek(batch.type, id);
743
- if (!origins.has(key)) {
744
- origins.set(key, s.syncMetadata[key]?.origin ?? "server");
745
- }
746
- }
747
- }
748
- for (const batch of batches) {
749
- const strategy = getMergeStrategy(batch.type);
750
- for (const { id, data } of batch.entries) {
751
- const key = ek(batch.type, id);
752
- const ctx = {
753
- type: batch.type,
754
- id,
755
- origin: origins.get(key) ?? "server",
756
- updatedAt: fetchedAt
757
- };
758
- s.entities[batch.type][id] = strategy(s.entities[batch.type][id], data, ctx);
759
- }
760
- }
761
- const completed = /* @__PURE__ */ new Set();
762
- for (const batch of batches) {
763
- for (const { id } of batch.entries) {
764
- const key = ek(batch.type, id);
765
- if (completed.has(key)) continue;
766
- completed.add(key);
767
- if (!s.entityStates[key]) s.entityStates[key] = defaultEntityState();
768
- s.entityStates[key].lastFetched = fetchedAt;
769
- s.entityStates[key].isFetching = false;
770
- s.entityStates[key].error = null;
771
- s.entityStates[key].stale = false;
772
- s.syncMetadata[key] = {
773
- ...s.syncMetadata[key] ?? defaultSyncMetadata(),
774
- synced: true,
775
- origin: "server",
776
- updatedAt: fetchedAt
777
- };
778
- }
779
- }
780
- const readDraftEntity = (id) => {
781
- const base = s.entities[type]?.[id];
782
- if (!base) return null;
783
- const patch = s.patches[type]?.[id];
784
- const metadata = s.syncMetadata[ek(type, id)] ?? defaultSyncMetadata();
785
- return {
786
- ...base,
787
- ...patch ?? {},
788
- $synced: metadata.synced,
789
- $origin: metadata.origin,
790
- $updatedAt: metadata.updatedAt
791
- };
792
- };
793
- for (const target of options.lists ?? []) {
794
- const existing = s.lists[target.key] ?? defaultListState();
795
- const targetIds = target.ids ?? ids;
796
- const nextIds = target.mode === "append" ? Array.from(/* @__PURE__ */ new Set([...existing.ids, ...targetIds])) : targetIds;
797
- s.lists[target.key] = {
798
- ...existing,
799
- ...target.meta ?? {},
800
- ids: nextIds,
801
- isFetching: false,
802
- isFetchingMore: false,
803
- error: null,
804
- lastError: null,
805
- stale: false,
806
- lastFetched: fetchedAt
807
- };
808
- }
809
- for (const projection of options.projections ?? []) {
810
- const existing = s.lists[projection.key] ?? defaultListState();
811
- const nextIds = [...existing.ids];
812
- const { filter, sort, search } = projection.view;
813
- for (const id of new Set(ids)) {
814
- if (nextIds.includes(id)) continue;
815
- const entity = readDraftEntity(id);
816
- if (!entity) continue;
817
- const matches = (!filter || matchesFilter(entity, filter)) && (!search?.query || matchesSearch(entity, search.query, search.fields));
818
- if (!matches) continue;
819
- if (sort && sort.length > 0) {
820
- const index = findInsertionIndex(entity, nextIds, readDraftEntity, sort);
821
- nextIds.splice(index, 0, id);
822
- } else {
823
- nextIds.unshift(id);
824
- }
825
- }
826
- s.lists[projection.key] = projection.completeFetch ? {
827
- ...existing,
828
- ids: nextIds,
829
- isFetching: false,
830
- isFetchingMore: false,
831
- error: null,
832
- lastError: null,
833
- stale: false,
834
- lastFetched: fetchedAt
835
- } : { ...existing, ids: nextIds };
836
- }
837
- for (const key of options.finishListFetches ?? []) {
838
- if (!s.lists[key]) s.lists[key] = defaultListState();
839
- s.lists[key].isFetching = false;
840
- }
841
- }),
842
- replaceEntity: (type, id, data) => set((s) => {
843
- if (!s.entities[type]) s.entities[type] = {};
844
- s.entities[type][id] = data;
845
- const key = ek(type, id);
846
- if (!s.syncMetadata[key]) s.syncMetadata[key] = defaultSyncMetadata();
847
- }),
848
- removeEntity: (type, id) => set((s) => {
849
- delete s.entities[type]?.[id];
850
- delete s.patches[type]?.[id];
851
- delete s.entityStates[ek(type, id)];
852
- delete s.syncMetadata[ek(type, id)];
853
- }),
854
- patchEntity: (type, id, patch) => set((s) => {
855
- if (!s.patches[type]) s.patches[type] = {};
856
- s.patches[type][id] = { ...s.patches[type][id] ?? {}, ...patch };
857
- }),
858
- unpatchEntity: (type, id, keys) => set((s) => {
859
- const p = s.patches[type]?.[id];
860
- if (!p) return;
861
- for (const k of keys) delete p[k];
862
- }),
863
- clearPatch: (type, id) => set((s) => {
864
- delete s.patches[type]?.[id];
865
- }),
866
- setEntityFetching: (type, id, fetching) => set((s) => {
867
- const k = ek(type, id);
868
- if (!s.entityStates[k]) s.entityStates[k] = defaultEntityState();
869
- s.entityStates[k].isFetching = fetching;
870
- }),
871
- setEntityError: (type, id, error) => set((s) => {
872
- const k = ek(type, id);
873
- if (!s.entityStates[k]) s.entityStates[k] = defaultEntityState();
874
- s.entityStates[k].error = error;
875
- s.entityStates[k].isFetching = false;
876
- }),
877
- setEntityFetched: (type, id) => set((s) => {
878
- const k = ek(type, id);
879
- if (!s.entityStates[k]) s.entityStates[k] = defaultEntityState();
880
- s.entityStates[k].lastFetched = Date.now();
881
- s.entityStates[k].isFetching = false;
882
- s.entityStates[k].error = null;
883
- s.entityStates[k].stale = false;
884
- s.syncMetadata[k] = { ...s.syncMetadata[k] ?? defaultSyncMetadata(), synced: true, origin: "server", updatedAt: Date.now() };
885
- }),
886
- setEntityStale: (type, id, stale) => set((s) => {
887
- const k = ek(type, id);
888
- if (!s.entityStates[k]) s.entityStates[k] = defaultEntityState();
889
- s.entityStates[k].stale = stale;
890
- }),
891
- setEntitySyncMetadata: (type, id, metadata) => set((s) => {
892
- const k = ek(type, id);
893
- s.syncMetadata[k] = { ...s.syncMetadata[k] ?? defaultSyncMetadata(), ...metadata };
894
- }),
895
- clearEntitySyncMetadata: (type, id) => set((s) => {
896
- delete s.syncMetadata[ek(type, id)];
897
- }),
898
- setListResult: (key, ids, meta) => set((s) => {
899
- const ex = s.lists[key] ?? defaultListState();
900
- s.lists[key] = { ...ex, ...meta, ids, isFetching: false, isFetchingMore: false, error: null, lastError: null, stale: false, lastFetched: Date.now() };
901
- }),
902
- appendListResult: (key, ids, meta) => set((s) => {
903
- const ex = s.lists[key] ?? defaultListState();
904
- s.lists[key] = { ...ex, ...meta, ids: Array.from(/* @__PURE__ */ new Set([...ex.ids, ...ids])), isFetching: false, isFetchingMore: false, error: null, lastError: null, stale: false, lastFetched: Date.now() };
905
- }),
906
- prependListResult: (key, ids, meta) => set((s) => {
907
- const ex = s.lists[key] ?? defaultListState();
908
- s.lists[key] = { ...ex, ...meta ?? {}, ids: Array.from(/* @__PURE__ */ new Set([...ids, ...ex.ids])), isFetching: false, isFetchingMore: false, error: null, lastError: null, stale: false, lastFetched: Date.now() };
909
- }),
910
- removeIdFromAllLists: (_type, id) => set((s) => {
911
- for (const key of Object.keys(s.lists)) {
912
- const list = s.lists[key];
913
- const idx = list.ids.indexOf(id);
914
- if (idx !== -1) {
915
- list.ids.splice(idx, 1);
916
- if (list.total !== null) list.total -= 1;
917
- }
918
- }
919
- }),
920
- insertIdInList: (key, id, position) => set((s) => {
921
- if (!s.lists[key]) s.lists[key] = defaultListState();
922
- const ids = s.lists[key].ids;
923
- const ex = ids.indexOf(id);
924
- if (ex !== -1) ids.splice(ex, 1);
925
- if (position === "start") ids.unshift(id);
926
- else if (position === "end") ids.push(id);
927
- else ids.splice(position, 0, id);
928
- }),
929
- setListFetching: (key, fetching) => set((s) => {
930
- if (!s.lists[key]) s.lists[key] = defaultListState();
931
- s.lists[key].isFetching = fetching;
932
- }),
933
- setListFetchingMore: (key, fetchingMore) => set((s) => {
934
- if (!s.lists[key]) s.lists[key] = defaultListState();
935
- s.lists[key].isFetchingMore = fetchingMore;
936
- }),
937
- setListError: (key, error, typed) => set((s) => {
938
- if (!s.lists[key]) s.lists[key] = defaultListState();
939
- s.lists[key].error = error;
940
- s.lists[key].lastError = typed ?? (error === null ? null : s.lists[key].lastError);
941
- s.lists[key].isFetching = false;
942
- s.lists[key].isFetchingMore = false;
943
- s.lists[key].lastFetched = Date.now();
944
- s.lists[key].stale = false;
945
- }),
946
- setListStale: (key, stale) => set((s) => {
947
- if (!s.lists[key]) s.lists[key] = defaultListState();
948
- s.lists[key].stale = stale;
949
- }),
950
- invalidateEntity: (type, id) => set((s) => {
951
- if (id) {
952
- const k = ek(type, id);
953
- if (s.entityStates[k]) s.entityStates[k].stale = true;
954
- } else {
955
- for (const k of Object.keys(s.entityStates)) if (k.startsWith(`${type}:`)) s.entityStates[k].stale = true;
956
- }
957
- }),
958
- invalidateLists: (matcher) => set((s) => {
959
- const pred = typeof matcher === "string" ? (k) => k.startsWith(matcher) : matcher;
960
- for (const key of Object.keys(s.lists)) if (pred(key)) s.lists[key].stale = true;
961
- }),
962
- invalidateType: (type) => {
963
- get().invalidateEntity(type);
964
- get().invalidateLists(type);
965
- },
966
- readEntity: (type, id) => {
967
- const s = get();
968
- const base = s.entities[type]?.[id];
969
- if (!base) return null;
970
- const patch = s.patches[type]?.[id];
971
- return patch ? { ...base, ...patch } : base;
972
- },
973
- readEntitySnapshot: (type, id) => {
974
- const s = get();
975
- const base = s.entities[type]?.[id];
976
- if (!base) {
977
- snapshotCache.delete(ek(type, id));
978
- return null;
979
- }
980
- const patch = s.patches[type]?.[id];
981
- const metadata = s.syncMetadata[ek(type, id)] ?? EMPTY_SYNC_METADATA;
982
- return readCachedEntitySnapshot(
983
- type,
984
- id,
985
- base,
986
- patch,
987
- metadata
988
- );
989
- }
990
- }))
991
- )
992
- );
993
- }
994
- var graphStore = createGraphStore();
995
- var useGraphStore = graphStore;
996
-
997
490
  // src/object-path.ts
998
491
  function isObject(value) {
999
492
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1037,8 +530,9 @@ function collectDirtyPaths(current, original, prefix = "", acc = /* @__PURE__ */
1037
530
 
1038
531
  // src/merge/loro.ts
1039
532
  var ROOT_MAP = "entity";
533
+ var LORO_MODULE_SPECIFIER = "loro-crdt";
1040
534
  var docs = /* @__PURE__ */ new Map();
1041
- function ek2(type, id) {
535
+ function ek(type, id) {
1042
536
  return `${type}:${id}`;
1043
537
  }
1044
538
  async function createLoroMergeStrategy(loadLoro) {
@@ -1046,7 +540,7 @@ async function createLoroMergeStrategy(loadLoro) {
1046
540
  try {
1047
541
  const loaded = loadLoro ? await loadLoro() : await import(
1048
542
  /* @vite-ignore */
1049
- 'loro-crdt'
543
+ LORO_MODULE_SPECIFIER
1050
544
  );
1051
545
  if (typeof loaded.LoroDoc !== "function") {
1052
546
  throw new TypeError("loro-crdt did not export a LoroDoc constructor");
@@ -1060,7 +554,7 @@ async function createLoroMergeStrategy(loadLoro) {
1060
554
  }
1061
555
  const { LoroDoc } = mod;
1062
556
  return (prev, next, ctx) => {
1063
- const key = ek2(ctx.type, ctx.id);
557
+ const key = ek(ctx.type, ctx.id);
1064
558
  let doc = docs.get(key);
1065
559
  if (!doc) {
1066
560
  doc = new LoroDoc();
@@ -1148,272 +642,6 @@ function applySelection(row, select) {
1148
642
  return picked;
1149
643
  }
1150
644
 
1151
- // src/engine.ts
1152
- function serializeKey(key) {
1153
- return JSON.stringify(key, (_, v) => v && typeof v === "object" && !Array.isArray(v) ? Object.fromEntries(Object.entries(v).sort()) : v);
1154
- }
1155
- function sleep(ms) {
1156
- return new Promise((r) => setTimeout(r, ms));
1157
- }
1158
- var inflightByStore = /* @__PURE__ */ new WeakMap();
1159
- function inflightFor(store) {
1160
- let inflight = inflightByStore.get(store);
1161
- if (!inflight) {
1162
- inflight = /* @__PURE__ */ new Map();
1163
- inflightByStore.set(store, inflight);
1164
- }
1165
- return inflight;
1166
- }
1167
- function dedupe(key, fn, store = graphStore) {
1168
- const inflight = inflightFor(store);
1169
- if (inflight.has(key)) return inflight.get(key);
1170
- const p = fn().finally(() => inflight.delete(key));
1171
- inflight.set(key, p);
1172
- return p;
1173
- }
1174
- var subscriberStatsListeners = /* @__PURE__ */ new Set();
1175
- function emitSubscriberStatsChange() {
1176
- for (const cb of subscriberStatsListeners) cb();
1177
- }
1178
- var subscribersByStore = /* @__PURE__ */ new WeakMap();
1179
- function subscribersFor(store) {
1180
- let subscribers = subscribersByStore.get(store);
1181
- if (!subscribers) {
1182
- subscribers = /* @__PURE__ */ new Map();
1183
- subscribersByStore.set(store, subscribers);
1184
- }
1185
- return subscribers;
1186
- }
1187
- function registerSubscriber(key, store = graphStore) {
1188
- const subscribers = subscribersFor(store);
1189
- const token = Symbol(key);
1190
- if (!subscribers.has(key)) subscribers.set(key, /* @__PURE__ */ new Set());
1191
- subscribers.get(key).add(token);
1192
- emitSubscriberStatsChange();
1193
- return token;
1194
- }
1195
- function unregisterSubscriber(key, token, store = graphStore) {
1196
- const subscribers = subscribersFor(store);
1197
- const set = subscribers.get(key);
1198
- if (!set) return;
1199
- set.delete(token);
1200
- if (set.size === 0) subscribers.delete(key);
1201
- emitSubscriberStatsChange();
1202
- }
1203
- function hasSubscribers(key, store = graphStore) {
1204
- return (subscribersFor(store).get(key)?.size ?? 0) > 0;
1205
- }
1206
- var DEFAULT_OPTIONS = {
1207
- defaultStaleTime: 3e4,
1208
- defaultGcTime: 3e5,
1209
- gcInterval: 6e4,
1210
- maxRetries: 3,
1211
- retryBaseDelay: 1e3,
1212
- revalidateOnFocus: true,
1213
- revalidateOnReconnect: true
1214
- };
1215
- var engineOptions = { ...DEFAULT_OPTIONS };
1216
- function subscribeSubscriberStats(onChange) {
1217
- subscriberStatsListeners.add(onChange);
1218
- return () => subscriberStatsListeners.delete(onChange);
1219
- }
1220
- function getActiveSubscriberCount(store = graphStore) {
1221
- let n = 0;
1222
- for (const set of subscribersFor(store).values()) n += set.size;
1223
- return n;
1224
- }
1225
- var devtoolsSubscribers = /* @__PURE__ */ new Set();
1226
- function subscribeDevtoolsEvent(cb) {
1227
- devtoolsSubscribers.add(cb);
1228
- return () => {
1229
- devtoolsSubscribers.delete(cb);
1230
- };
1231
- }
1232
- function notifyDevtools(event) {
1233
- if (devtoolsSubscribers.size === 0) return;
1234
- const listeners2 = [...devtoolsSubscribers];
1235
- for (const cb of listeners2) {
1236
- try {
1237
- cb(event);
1238
- } catch (err) {
1239
- console.warn("[engine] devtools subscriber threw:", err);
1240
- }
1241
- }
1242
- }
1243
- var gcIntervalsByStore = /* @__PURE__ */ new Map();
1244
- function runGarbageCollection(storeApi = graphStore) {
1245
- const store = storeApi.getState();
1246
- const { defaultGcTime: gcTime } = getEngineOptions();
1247
- const now = Date.now();
1248
- const toRemove = [];
1249
- for (const type of Object.keys(store.entities)) {
1250
- const bucket = store.entities[type];
1251
- if (!bucket) continue;
1252
- for (const id of Object.keys(bucket)) {
1253
- const key = `${type}:${id}`;
1254
- if (hasSubscribers(key, storeApi)) continue;
1255
- const patch = store.patches[type]?.[id];
1256
- if (patch !== void 0 && Object.keys(patch).length > 0) continue;
1257
- const entityState = store.entityStates[key];
1258
- if (entityState?.isFetching) continue;
1259
- const lastFetched = entityState?.lastFetched;
1260
- if (lastFetched == null) continue;
1261
- if (now - lastFetched <= gcTime) continue;
1262
- toRemove.push({ type, id });
1263
- }
1264
- }
1265
- for (const { type, id } of toRemove) {
1266
- store.removeEntity(type, id);
1267
- store.removeIdFromAllLists(type, id);
1268
- }
1269
- }
1270
- function stopGarbageCollector(storeApi = graphStore) {
1271
- const intervalId = gcIntervalsByStore.get(storeApi);
1272
- if (intervalId != null && typeof clearInterval !== "undefined") {
1273
- clearInterval(intervalId);
1274
- gcIntervalsByStore.delete(storeApi);
1275
- }
1276
- }
1277
- function startGarbageCollector(storeApi = graphStore) {
1278
- stopGarbageCollector(storeApi);
1279
- if (typeof window === "undefined" || typeof setInterval === "undefined") return () => {
1280
- };
1281
- const intervalId = setInterval(
1282
- () => runGarbageCollection(storeApi),
1283
- getEngineOptions().gcInterval
1284
- );
1285
- gcIntervalsByStore.set(storeApi, intervalId);
1286
- return () => stopGarbageCollector(storeApi);
1287
- }
1288
- function restartGarbageCollector(storeApi = graphStore) {
1289
- startGarbageCollector(storeApi);
1290
- }
1291
- function configureEngine(opts) {
1292
- engineOptions = { ...DEFAULT_OPTIONS, ...opts };
1293
- const activeStores = [...gcIntervalsByStore.keys()];
1294
- if (activeStores.length === 0) restartGarbageCollector();
1295
- else for (const storeApi of activeStores) restartGarbageCollector(storeApi);
1296
- }
1297
- function getEngineOptions() {
1298
- return engineOptions;
1299
- }
1300
- async function fetchEntity(opts, engineOpts, storeApi = graphStore) {
1301
- const { type, id, fetch, normalize, sideEffects, idField = "id" } = opts;
1302
- if (!id) return;
1303
- storeApi.getState().setEntityFetching(type, id, true);
1304
- const attempt = async (retries) => {
1305
- try {
1306
- const raw = await fetch(id);
1307
- const normalized = normalize(raw);
1308
- const resolvedId = normalized[idField] ?? id;
1309
- storeApi.getState().upsertEntity(type, resolvedId, normalized);
1310
- storeApi.getState().setEntityFetched(type, resolvedId);
1311
- if (sideEffects) sideEffects(raw, storeApi);
1312
- opts.onSuccess?.(normalized);
1313
- } catch (err) {
1314
- const error = err instanceof Error ? err : new Error(String(err));
1315
- if (retries < engineOpts.maxRetries) {
1316
- await sleep(engineOpts.retryBaseDelay * Math.pow(2, retries));
1317
- return attempt(retries + 1);
1318
- }
1319
- storeApi.getState().setEntityError(type, id, error.message);
1320
- opts.onError?.(error);
1321
- }
1322
- };
1323
- await dedupe(`${type}:${id}`, () => attempt(0), storeApi);
1324
- }
1325
- async function fetchList(opts, params, engineOpts, isLoadMore = false, storeApi = graphStore) {
1326
- const { type, queryKey, fetch, normalize, sideEffects, mode = "replace" } = opts;
1327
- const key = serializeKey(queryKey);
1328
- const store = storeApi.getState();
1329
- if (!fetch || !normalize) return;
1330
- if (isLoadMore) store.setListFetchingMore(key, true);
1331
- else store.setListFetching(key, true);
1332
- const attempt = async (retries) => {
1333
- try {
1334
- const response = await fetch(params);
1335
- const normalized = response.items.map(normalize);
1336
- const meta = { total: response.total ?? null, nextCursor: response.nextCursor ?? null, prevCursor: response.prevCursor ?? null, hasNextPage: response.hasNextPage ?? !!response.nextCursor, hasPrevPage: response.hasPrevPage ?? !!response.prevCursor, currentPage: response.page ?? null, pageSize: response.pageSize ?? null };
1337
- storeApi.getState().ingestFetchedList(
1338
- type,
1339
- normalized.map(({ id, data }) => ({ id, data })),
1340
- { lists: [{ key, mode: mode === "append" && isLoadMore ? "append" : "replace", meta }] }
1341
- );
1342
- if (sideEffects) sideEffects(response.items, storeApi);
1343
- opts.onSuccess?.(response);
1344
- } catch (err) {
1345
- const error = err instanceof Error ? err : new Error(String(err));
1346
- if (retries < engineOpts.maxRetries) {
1347
- await sleep(engineOpts.retryBaseDelay * Math.pow(2, retries));
1348
- return attempt(retries + 1);
1349
- }
1350
- storeApi.getState().setListError(key, error.message);
1351
- opts.onError?.(error);
1352
- }
1353
- };
1354
- await dedupe(isLoadMore ? `${key}:more` : key, () => attempt(0), storeApi);
1355
- }
1356
- var globalListenerAttachments = /* @__PURE__ */ new WeakMap();
1357
- function releaseGlobalListenerAttachment(storeApi, attachment) {
1358
- let released = false;
1359
- return () => {
1360
- if (released) return;
1361
- released = true;
1362
- const current = globalListenerAttachments.get(storeApi);
1363
- if (current !== attachment) return;
1364
- current.references -= 1;
1365
- if (current.references > 0) return;
1366
- current.dispose();
1367
- globalListenerAttachments.delete(storeApi);
1368
- };
1369
- }
1370
- function attachGlobalListeners(storeApi = graphStore) {
1371
- if (typeof window === "undefined") return () => {
1372
- };
1373
- const existing = globalListenerAttachments.get(storeApi);
1374
- if (existing) {
1375
- existing.references += 1;
1376
- return releaseGlobalListenerAttachment(storeApi, existing);
1377
- }
1378
- const stopGc = startGarbageCollector(storeApi);
1379
- const revalidateAll = () => {
1380
- const state = storeApi.getState();
1381
- for (const key of subscribersFor(storeApi).keys()) {
1382
- if (!hasSubscribers(key, storeApi)) continue;
1383
- const colonIdx = key.indexOf(":");
1384
- if (colonIdx === -1) continue;
1385
- const type = key.slice(0, colonIdx);
1386
- const id = key.slice(colonIdx + 1);
1387
- state.setEntityStale(type, id, true);
1388
- }
1389
- };
1390
- const revalidateWhenVisible = () => {
1391
- if (document.visibilityState === "visible") revalidateAll();
1392
- };
1393
- const revalidateOnFocus = engineOptions.revalidateOnFocus;
1394
- const revalidateOnReconnect = engineOptions.revalidateOnReconnect;
1395
- if (revalidateOnFocus) {
1396
- window.addEventListener("visibilitychange", revalidateWhenVisible);
1397
- window.addEventListener("focus", revalidateAll);
1398
- }
1399
- if (revalidateOnReconnect) window.addEventListener("online", revalidateAll);
1400
- const attachment = {
1401
- references: 1,
1402
- dispose: () => {
1403
- if (revalidateOnFocus) {
1404
- window.removeEventListener("visibilitychange", revalidateWhenVisible);
1405
- window.removeEventListener("focus", revalidateAll);
1406
- }
1407
- if (revalidateOnReconnect) {
1408
- window.removeEventListener("online", revalidateAll);
1409
- }
1410
- stopGc();
1411
- }
1412
- };
1413
- globalListenerAttachments.set(storeApi, attachment);
1414
- return releaseGlobalListenerAttachment(storeApi, attachment);
1415
- }
1416
-
1417
645
  // src/graph-actions.ts
1418
646
  var graphActionListeners = /* @__PURE__ */ new Set();
1419
647
  var graphActionReplayers = /* @__PURE__ */ new Map();
@@ -1424,7 +652,7 @@ function createGraphTransaction(storeApi = graphStore) {
1424
652
  upsertEntity(type, id, data) {
1425
653
  storeApi.getState().upsertEntity(type, id, data);
1426
654
  if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
1427
- notifyDevtools({ kind: "upsert", type, id, data, at: (/* @__PURE__ */ new Date()).toISOString() });
655
+ emitLegacyDevtoolsEvent({ kind: "upsert", type, id, data, at: (/* @__PURE__ */ new Date()).toISOString() });
1428
656
  }
1429
657
  return tx;
1430
658
  },
@@ -1439,14 +667,14 @@ function createGraphTransaction(storeApi = graphStore) {
1439
667
  patchEntity(type, id, patch) {
1440
668
  storeApi.getState().patchEntity(type, id, patch);
1441
669
  if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
1442
- notifyDevtools({ kind: "patch", type, id, patch, at: (/* @__PURE__ */ new Date()).toISOString() });
670
+ emitLegacyDevtoolsEvent({ kind: "patch", type, id, patch, at: (/* @__PURE__ */ new Date()).toISOString() });
1443
671
  }
1444
672
  return tx;
1445
673
  },
1446
674
  clearPatch(type, id) {
1447
675
  storeApi.getState().clearPatch(type, id);
1448
676
  if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
1449
- notifyDevtools({ kind: "clearPatch", type, id, at: (/* @__PURE__ */ new Date()).toISOString() });
677
+ emitLegacyDevtoolsEvent({ kind: "clearPatch", type, id, at: (/* @__PURE__ */ new Date()).toISOString() });
1450
678
  }
1451
679
  return tx;
1452
680
  },
@@ -1929,7 +1157,7 @@ function computeDelay(policy, attempt) {
1929
1157
  return base / 2 + Math.random() * (base / 2);
1930
1158
  }
1931
1159
  }
1932
- function sleep2(ms) {
1160
+ function sleep(ms) {
1933
1161
  if (ms <= 0) return Promise.resolve();
1934
1162
  return new Promise((r) => setTimeout(r, ms));
1935
1163
  }
@@ -1942,7 +1170,7 @@ async function replayActionWithRetry(action, policy, storeApi = graphStore) {
1942
1170
  } catch (error) {
1943
1171
  lastError = error;
1944
1172
  if (attempt >= policy.maxAttempts) break;
1945
- await sleep2(computeDelay(policy, attempt));
1173
+ await sleep(computeDelay(policy, attempt));
1946
1174
  }
1947
1175
  }
1948
1176
  try {
@@ -1976,9 +1204,9 @@ function getDefaultOnlineSource() {
1976
1204
 
1977
1205
  // src/devtools-event-bus.ts
1978
1206
  var _busInjectMap = /* @__PURE__ */ new WeakMap();
1979
- var registry = /* @__PURE__ */ new Map();
1207
+ var registries = /* @__PURE__ */ new Map();
1980
1208
  function __resetStoreRegistry() {
1981
- registry.clear();
1209
+ registries.clear();
1982
1210
  }
1983
1211
  function createDevtoolsEventBus(opts) {
1984
1212
  const bufferSize = opts?.bufferSize ?? 500;
@@ -2093,8 +1321,10 @@ function createDevtoolsEventBus(opts) {
2093
1321
  pendingBurst = [];
2094
1322
  dispatchedCount = 0;
2095
1323
  flushScheduled = false;
2096
- for (const entry of registry.values()) {
2097
- if (entry.bus === bus && entry.active) {
1324
+ const registry = registries.get(bus);
1325
+ if (registry) {
1326
+ for (const entry of registry.values()) {
1327
+ if (!entry.active) continue;
2098
1328
  entry.active = false;
2099
1329
  try {
2100
1330
  entry.unsubscribeSrc();
@@ -2102,12 +1332,19 @@ function createDevtoolsEventBus(opts) {
2102
1332
  }
2103
1333
  }
2104
1334
  }
1335
+ registries.delete(bus);
1336
+ _busInjectMap.delete(bus);
2105
1337
  }
2106
1338
  };
2107
1339
  _busInjectMap.set(bus, handleEngineEvent);
2108
1340
  return bus;
2109
1341
  }
2110
1342
  function registerStore(bus, source, name) {
1343
+ let registry = registries.get(bus);
1344
+ if (!registry) {
1345
+ registry = /* @__PURE__ */ new Map();
1346
+ registries.set(bus, registry);
1347
+ }
2111
1348
  if (registry.get(name)?.active === true) {
2112
1349
  throw new Error(
2113
1350
  `[devtools-store-registry] Store name "${name}" is already registered and active`
@@ -2128,75 +1365,38 @@ function registerStore(bus, source, name) {
2128
1365
  unsubscribeSrc();
2129
1366
  };
2130
1367
  }
2131
- function getRegisteredStores() {
2132
- return Array.from(registry.values()).map((e) => ({ name: e.name, active: e.active }));
1368
+ function getRegisteredStores(bus) {
1369
+ const entries = bus ? [...registries.get(bus)?.values() ?? []] : [...registries.values()].flatMap((registry) => [...registry.values()]);
1370
+ return entries.map((entry) => ({ name: entry.name, active: entry.active }));
2133
1371
  }
2134
1372
 
2135
1373
  // src/devtools-time-travel.ts
2136
- var capacity = 50;
2137
- var ring = [];
2138
- var seqCounter = 0;
2139
- var cursor = null;
2140
- var listeners = /* @__PURE__ */ new Set();
2141
- function notify() {
2142
- for (const l of listeners) l();
2143
- }
2144
- function cloneSlice(s) {
2145
- return {
2146
- entities: structuredClone(s.entities),
2147
- patches: structuredClone(s.patches),
2148
- entityStates: structuredClone(s.entityStates),
2149
- syncMetadata: structuredClone(s.syncMetadata),
2150
- lists: structuredClone(s.lists)
2151
- };
2152
- }
2153
- function configureTimeTravel(opts) {
2154
- if (opts.capacity && opts.capacity > 0) capacity = opts.capacity;
2155
- if (ring.length > capacity) ring = ring.slice(-capacity);
2156
- notify();
1374
+ function configureTimeTravel(opts, storeApi = graphStore) {
1375
+ if (opts.capacity && opts.capacity > 0) {
1376
+ getGraphDevtoolsCompatibilityDelegate(storeApi)?.configure(opts.capacity);
1377
+ }
2157
1378
  }
2158
1379
  function recordGraphSnapshot(label, storeApi = graphStore) {
2159
- const s = storeApi.getState();
2160
- const snap = {
2161
- seq: seqCounter++,
2162
- at: Date.now(),
2163
- ...label !== void 0 ? { label } : {},
2164
- data: cloneSlice(s)
2165
- };
2166
- ring.push(snap);
2167
- if (ring.length > capacity) ring = ring.slice(-capacity);
2168
- cursor = null;
2169
- notify();
2170
- return snap.seq;
1380
+ return getGraphDevtoolsCompatibilityDelegate(storeApi)?.capture(label) ?? -1;
2171
1381
  }
2172
1382
  function restoreGraphSnapshot(index, storeApi = graphStore) {
2173
- const snap = ring[index];
2174
- if (!snap) return false;
2175
- const clone2 = cloneSlice(snap.data);
2176
- storeApi.setState(clone2);
2177
- cursor = index;
2178
- notify();
2179
- return true;
1383
+ return getGraphDevtoolsCompatibilityDelegate(storeApi)?.restoreByIndex(index) ?? false;
2180
1384
  }
2181
1385
  function restoreGraphSnapshotBySeq(seq, storeApi = graphStore) {
2182
- const index = ring.findIndex((s) => s.seq === seq);
2183
- return index === -1 ? false : restoreGraphSnapshot(index, storeApi);
1386
+ return getGraphDevtoolsCompatibilityDelegate(storeApi)?.restoreByCursor(seq) ?? false;
2184
1387
  }
2185
1388
  function stepTimeTravel(delta, storeApi = graphStore) {
2186
- const base = cursor ?? ring.length - 1;
2187
- const target = Math.max(0, Math.min(ring.length - 1, base + delta));
2188
- return restoreGraphSnapshot(target, storeApi);
1389
+ return getGraphDevtoolsCompatibilityDelegate(storeApi)?.step(delta) ?? false;
2189
1390
  }
2190
- function getTimeTravelState() {
2191
- return {
2192
- snapshots: ring.map(({ data: _data, ...meta }) => meta),
2193
- cursor,
2194
- capacity
1391
+ function getTimeTravelState(storeApi = graphStore) {
1392
+ return getGraphDevtoolsCompatibilityDelegate(storeApi)?.getState() ?? {
1393
+ snapshots: [],
1394
+ cursor: null,
1395
+ capacity: 50
2195
1396
  };
2196
1397
  }
2197
- function subscribeTimeTravel(cb) {
2198
- listeners.add(cb);
2199
- return () => listeners.delete(cb);
1398
+ function subscribeTimeTravel(cb, storeApi = graphStore) {
1399
+ return subscribeGraphDevtoolsCompatibility(storeApi, cb);
2200
1400
  }
2201
1401
 
2202
1402
  // src/view/incremental.ts
@@ -2291,78 +1491,6 @@ var IncrementalView = class {
2291
1491
  }
2292
1492
  };
2293
1493
 
2294
- // src/crud/relations.ts
2295
- var schemaRegistry2 = /* @__PURE__ */ new Map();
2296
- function registerSchema(schema) {
2297
- schemaRegistry2.set(schema.type, schema);
2298
- }
2299
- function getSchema(type) {
2300
- return schemaRegistry2.get(type) ?? null;
2301
- }
2302
- function cascadeInvalidation(ctx, storeApi = graphStore) {
2303
- const schema = schemaRegistry2.get(ctx.type);
2304
- if (!schema) return;
2305
- const store = storeApi.getState();
2306
- if (schema.globalListKeys) for (const key of schema.globalListKeys) store.invalidateLists(key);
2307
- if (!schema.relations) return;
2308
- for (const [, relation] of Object.entries(schema.relations)) {
2309
- switch (relation.cardinality) {
2310
- case "belongsTo": {
2311
- const prevFk = ctx.previous?.[relation.foreignKey];
2312
- const nextFk = ctx.next?.[relation.foreignKey];
2313
- if (prevFk && prevFk !== nextFk && relation.invalidateTargetLists) for (const kp of relation.invalidateTargetLists) store.invalidateLists((k) => k.startsWith(kp) && k.includes(prevFk));
2314
- if (nextFk && relation.invalidateTargetLists) for (const kp of relation.invalidateTargetLists) store.invalidateLists((k) => k.startsWith(kp) && k.includes(nextFk));
2315
- if (prevFk) store.invalidateEntity(relation.targetType, prevFk);
2316
- if (nextFk) store.invalidateEntity(relation.targetType, nextFk);
2317
- break;
2318
- }
2319
- case "hasMany":
2320
- store.invalidateLists(serializeKey(relation.listKeyPrefix(ctx.id)));
2321
- break;
2322
- case "manyToMany": {
2323
- const prevIds = ctx.previous?.[relation.localArrayField ?? ""];
2324
- const nextIds = ctx.next?.[relation.localArrayField ?? ""];
2325
- for (const relatedId of /* @__PURE__ */ new Set([...prevIds ?? [], ...nextIds ?? []])) store.invalidateLists(serializeKey(relation.listKeyPrefix(relatedId)));
2326
- break;
2327
- }
2328
- }
2329
- }
2330
- for (const [, otherSchema] of schemaRegistry2) {
2331
- if (!otherSchema.relations) continue;
2332
- for (const [, rel] of Object.entries(otherSchema.relations)) {
2333
- if (rel.targetType !== ctx.type) continue;
2334
- if (rel.cardinality === "hasMany") store.invalidateLists(serializeKey(rel.listKeyPrefix(ctx.id)));
2335
- }
2336
- }
2337
- }
2338
- function readRelations(type, entity, storeApi = graphStore) {
2339
- const schema = schemaRegistry2.get(type);
2340
- if (!schema?.relations) return {};
2341
- const store = storeApi.getState();
2342
- const result = {};
2343
- for (const [name, relation] of Object.entries(schema.relations)) {
2344
- switch (relation.cardinality) {
2345
- case "belongsTo": {
2346
- const fkValue = entity[relation.foreignKey];
2347
- result[name] = fkValue ? store.readEntity(relation.targetType, fkValue) : null;
2348
- break;
2349
- }
2350
- case "hasMany": {
2351
- const listKey = serializeKey(relation.listKeyPrefix(entity.id));
2352
- const listState = store.lists[listKey];
2353
- result[name] = listState ? listState.ids.map((id) => store.readEntity(relation.targetType, id)).filter(Boolean) : [];
2354
- break;
2355
- }
2356
- case "manyToMany": {
2357
- const ids = entity[relation.localArrayField ?? ""];
2358
- result[name] = ids ? ids.map((id) => store.readEntity(relation.targetType, id)).filter(Boolean) : [];
2359
- break;
2360
- }
2361
- }
2362
- }
2363
- return result;
2364
- }
2365
-
2366
1494
  // src/agent/json-patch.ts
2367
1495
  function unescape(token) {
2368
1496
  return token.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -2900,10 +2028,10 @@ function createGraphQLSubscriptionAdapter(opts) {
2900
2028
  subscribe(_cfg, handler) {
2901
2029
  const unsubs = [];
2902
2030
  for (const sub of subscriptions) {
2903
- const { type, document: document2, variables, getPayload } = sub;
2031
+ const { type, document, variables, getPayload } = sub;
2904
2032
  unsubs.push(
2905
2033
  client.subscribe(
2906
- { query: document2, variables },
2034
+ { query: document, variables },
2907
2035
  {
2908
2036
  next: ({ data }) => {
2909
2037
  const raw = getPayload(data);
@@ -4035,6 +3163,6 @@ function getFacetedRowModel(preFilteredRowModel, columnId, allFilteredRowModel)
4035
3163
  return preFilteredRowModel;
4036
3164
  }
4037
3165
 
4038
- export { EMPTY_ENTITY_STATE, EMPTY_IDS, EMPTY_LIST_STATE, EMPTY_SYNC_METADATA, IncrementalView, RealtimeManager, TerminalError, TransientError, __resetActiveGraphStore, __resetEntityTransports, __resetStoreRegistry, applyAgUiDelta, applyAgUiSnapshot, applyJsonPatch, applyView, attachGlobalListeners, buildTenantWhere, cascadeInvalidation, checkCompleteness, collectDirtyPaths, compareEntities, configureEngine, configureTimeTravel, createConvexAdapter, createDevtoolsEventBus, createElectricAdapter, createFlintAdapter, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphStore, createGraphTool, createGraphTransaction, createLoroMergeStrategy, createPGlitePersistenceAdapter, createRow, createSchemaGraphTool, createSupabaseRealtimeAdapter, createSurrealLiveAdapter, createTauriSqlPersistenceAdapter, createTenantScopedElectricAdapter, createWebSocketAdapter, dedupe, escapeHtml, exportGraphSnapshot, exportGraphSnapshotWithSchemas, fetchEntity, fetchList, findInsertionIndex, flattenClauses, getActiveSubscriberCount, getCoreRowModel, getRealtimeManager as getElectricRealtimeManager, getEngineOptions, getEntityJsonSchema, getEntityTransport, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGraphSyncStatus, getGroupedRowModel, getMergeStrategy, getPaginatedRowModel, getRealtimeManager, getRegisteredEntityTypes, getRegisteredStores, getSchema, getSelectedRowModel, getSortedRowModel, getTimeTravelState, getValueAtPath, graphStore, graphSyncStatusStore, hasCustomPredicates, hasMergeStrategy, humanizeFieldName, hydrateGraphFromStorage, inferSchemaFieldType, lwwStrategy, makeRestTransport, matchesFilter, matchesSearch, parseCreateTable, persistGraphToStorage, prepareGraphStoreScope, publishFlintMutation, queryOnce, readRelations, recordGraphSnapshot, registerEntityFromSql, registerEntityJsonSchema, registerEntityTransport, registerMergeStrategy, registerRuntimeSchema, registerSchema, registerStore, registerSubscriber, registryKey, renderMarkdownToHtml, replayActionWithRetry, resetRealtimeManager, resolveActiveGraphStore, restoreGraphSnapshot, restoreGraphSnapshotBySeq, runWithGraphStore, selectGraph, serializeKey, setActiveGraphStore, setDefaultMergeStrategy, setValueAtPath, sqlTypeToJsonSchema, startGarbageCollector, startLocalFirstGraph, stepTimeTravel, stopGarbageCollector, subscribeDevtoolsEvent, subscribeSubscriberStats, subscribeTimeTravel, toEntityError, toGraphQLVariables, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses, unregisterSubscriber, useGraphStore };
3166
+ export { IncrementalView, RealtimeManager, TerminalError, TransientError, __resetActiveGraphStore, __resetEntityTransports, __resetStoreRegistry, applyAgUiDelta, applyAgUiSnapshot, applyJsonPatch, buildTenantWhere, collectDirtyPaths, configureTimeTravel, createConvexAdapter, createDevtoolsEventBus, createElectricAdapter, createFlintAdapter, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphTool, createGraphTransaction, createLoroMergeStrategy, createPGlitePersistenceAdapter, createRow, createSchemaGraphTool, createSupabaseRealtimeAdapter, createSurrealLiveAdapter, createTauriSqlPersistenceAdapter, createTenantScopedElectricAdapter, createWebSocketAdapter, escapeHtml, exportGraphSnapshot, exportGraphSnapshotWithSchemas, flattenClauses, getCoreRowModel, getRealtimeManager as getElectricRealtimeManager, getEntityJsonSchema, getEntityTransport, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGraphSyncStatus, getGroupedRowModel, getPaginatedRowModel, getRealtimeManager, getRegisteredEntityTypes, getRegisteredStores, getSelectedRowModel, getSortedRowModel, getTimeTravelState, getValueAtPath, graphSyncStatusStore, hasCustomPredicates, humanizeFieldName, hydrateGraphFromStorage, inferSchemaFieldType, makeRestTransport, parseCreateTable, persistGraphToStorage, prepareGraphStoreScope, publishFlintMutation, queryOnce, recordGraphSnapshot, registerEntityFromSql, registerEntityJsonSchema, registerEntityTransport, registerRuntimeSchema, registerStore, registryKey, renderMarkdownToHtml, replayActionWithRetry, resetRealtimeManager, resolveActiveGraphStore, restoreGraphSnapshot, restoreGraphSnapshotBySeq, runWithGraphStore, selectGraph, setActiveGraphStore, setValueAtPath, sqlTypeToJsonSchema, startLocalFirstGraph, stepTimeTravel, subscribeTimeTravel, toEntityError, toGraphQLVariables, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses };
4039
3167
  //# sourceMappingURL=index.mjs.map
4040
3168
  //# sourceMappingURL=index.mjs.map