valdres 0.2.0-pre.15 → 0.2.0-pre.17

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.js CHANGED
@@ -278,7 +278,7 @@ function getState(state, data, initializedAtomsSet, circularDependencySet) {
278
278
  const closestData = findClosestStoreWithAtomInitialized(state, data);
279
279
  return getState(state, closestData, initializedAtomsSet, circularDependencySet);
280
280
  }
281
- data.values.set(state, new FamilyIndex(state, data).toArray());
281
+ data.values.set(state, renderAtomFamilyIndex(createAtomFamilyIndex()));
282
282
  initializedAtomsSet.add(state);
283
283
  return data.values.get(state);
284
284
  }
@@ -422,74 +422,75 @@ var addSetToSet = (fromSet, toSet) => {
422
422
  }
423
423
  }
424
424
  };
425
- class FamilyIndex {
426
- map;
427
- family;
428
- data;
429
- parentIndex;
430
- constructor(family, data, parentIndex, map) {
431
- this.family = family;
432
- this.data = data;
433
- this.parentIndex = parentIndex;
434
- this.map = new Map(map);
435
- }
436
- add(atoms) {
437
- atoms.forEach((atom) => {
438
- this.map.set(atom, true);
439
- });
440
- }
441
- delete(atoms) {
442
- atoms.forEach((atom) => {
443
- this.map.set(atom, false);
444
- });
445
- }
446
- has(atom) {
447
- return this.map.has(atom);
448
- }
449
- clone() {
450
- return new FamilyIndex(this.family, this.data, this.parentIndex, this.map);
451
- }
452
- toSet() {
453
- let set;
454
- if (this.parentIndex) {
455
- set = new Set(this.parentIndex.toSet());
456
- } else {
457
- set = new Set;
458
- }
459
- for (const [key, value] of this.map) {
460
- if (value === true)
461
- set.add(key);
462
- if (value === false)
463
- set.delete(key);
464
- }
465
- return set;
425
+ var getAtomFamilyRenderedMap = (index) => {
426
+ if (index.rendered)
427
+ return index.rendered;
428
+ const result = new Map(index.parentIndex ? getAtomFamilyRenderedMap(index.parentIndex) : undefined);
429
+ for (const [atom, timestamp] of index.created) {
430
+ result.set(atom, timestamp);
466
431
  }
467
- toArray() {
468
- const arr = [...this.toSet()];
469
- arr.__index = this;
470
- return arr;
432
+ for (const [atom, timestamp] of index.deleted) {
433
+ result.delete(atom, timestamp);
471
434
  }
472
- }
473
- var deleteFamilyAtomsFromSet = (family, familyAtoms, data) => {
435
+ index.rendered = result;
436
+ return result;
437
+ };
438
+ var getSortedKeysByValues = (map) => {
439
+ return Array.from(map.entries()).sort((a, b) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0).map((entry) => entry[0]);
440
+ };
441
+ var renderAtomFamilyIndex = (index) => {
442
+ if (index.renderedArray) {
443
+ console.log("Using cached rendered array");
444
+ return index.renderedArray;
445
+ }
446
+ const renderedMap = getAtomFamilyRenderedMap(index);
447
+ const array = getSortedKeysByValues(renderedMap);
448
+ array.__index = index;
449
+ index.renderedArray = array;
450
+ return array;
451
+ };
452
+ var cloneAtomFamilyIndex = (index, parentIndexOverride) => {
453
+ return {
454
+ created: new Map(index.created),
455
+ deleted: new Map(index.deleted),
456
+ rendered: null,
457
+ renderedArray: null,
458
+ parentIndex: parentIndexOverride || index.parentIndex
459
+ };
460
+ };
461
+ var createAtomFamilyIndex = (parentIndex) => {
462
+ return {
463
+ created: new Map,
464
+ deleted: new Map,
465
+ rendered: null,
466
+ renderedArray: null,
467
+ parentIndex
468
+ };
469
+ };
470
+ var deleteFamilyAtomsFromSet = (family, familyAtoms, data, timestamp) => {
471
+ if (familyAtoms.size === 0)
472
+ return;
474
473
  const index = findFamilyIndex(family, data);
475
- index.delete(familyAtoms);
476
- data.values.set(family, index.toArray());
474
+ for (const atom of familyAtoms) {
475
+ index.deleted.set(atom, timestamp);
476
+ }
477
+ index.rendered = null;
478
+ index.renderedArray = null;
479
+ data.values.set(family, renderAtomFamilyIndex(index));
477
480
  recursivlyUpdateIndexes(data, family);
478
481
  };
479
482
  var initFamilyIndex = (family, data) => {
480
483
  if (data.values.has(family))
481
- return;
484
+ return data.values.get(family).__index;
485
+ let parentIndex;
482
486
  if ("parent" in data) {
483
- initFamilyIndex(family, data.parent);
484
- const parentIndex = data.parent.values.get(family).__index;
487
+ parentIndex = initFamilyIndex(family, data.parent);
485
488
  if (!parentIndex)
486
489
  throw new Error("Parent index is missing");
487
- const index = new FamilyIndex(family, data, parentIndex);
488
- data.values.set(family, index.toArray());
489
- } else {
490
- const index = new FamilyIndex(family, data);
491
- data.values.set(family, index.toArray());
492
490
  }
491
+ const index = createAtomFamilyIndex(parentIndex);
492
+ data.values.set(family, renderAtomFamilyIndex(index));
493
+ return index;
493
494
  };
494
495
  var findFamilyIndex = (family, data) => {
495
496
  if (!data.values.has(family)) {
@@ -507,19 +508,31 @@ var recursivlyUpdateIndexes = (data, family) => {
507
508
  const scopedData = data.scopes[scopeKey];
508
509
  if (scopeKey) {
509
510
  if (scopedData.values.has(family)) {
510
- scopedData.values.set(family, scopedData.values.get(family).__index.toArray());
511
+ const index = scopedData.values.get(family).__index;
512
+ index.rendered = null;
513
+ index.renderedArray = null;
514
+ scopedData.values.set(family, renderAtomFamilyIndex(index));
511
515
  }
512
516
  recursivlyUpdateIndexes(scopedData, family);
513
517
  }
514
518
  });
515
519
  };
516
- var addFamilyAtomsToSet = (family, familyAtoms, data) => {
520
+ var addFamilyAtomsToSet = (family, familyAtoms, data, timestamp) => {
521
+ if (familyAtoms.size === 0)
522
+ return;
517
523
  const index = findFamilyIndex(family, data);
518
- index.add(familyAtoms);
519
- data.values.set(family, index.toArray());
524
+ if (!index)
525
+ throw new Error("index not found");
526
+ for (const atom of familyAtoms) {
527
+ index.created.set(atom, timestamp);
528
+ index.deleted.delete(atom);
529
+ }
530
+ index.rendered = null;
531
+ index.renderedArray = null;
532
+ data.values.set(family, renderAtomFamilyIndex(index));
520
533
  recursivlyUpdateIndexes(data, family);
521
534
  };
522
- var propagateDeletedAtoms = (atoms, data, subscriptions = new Set, families = new Map) => {
535
+ var propagateDeletedAtoms = (atoms, data, subscriptions = new Set, families = new Map, timestamp = performance.now()) => {
523
536
  const selectors = new Set;
524
537
  for (const atom of atoms) {
525
538
  addSetToSet(data.stateDependents.get(atom), selectors);
@@ -537,12 +550,12 @@ var propagateDeletedAtoms = (atoms, data, subscriptions = new Set, families = ne
537
550
  addSetToSet(data.subscriptions.get(family), subscriptions);
538
551
  if (familyAtoms.size === 0)
539
552
  throw new Error("Should not be possible");
540
- deleteFamilyAtomsFromSet(family, familyAtoms, data);
553
+ deleteFamilyAtomsFromSet(family, familyAtoms, data, timestamp);
541
554
  }
542
555
  }
543
556
  propagateDirtySelectors(atoms, selectors, data, subscriptions, families);
544
557
  };
545
- var propagateUpdatedAtoms = (atoms, data, subscriptions = new Set, families = new Map, isRecursive = false) => {
558
+ var propagateUpdatedAtoms = (atoms, data, subscriptions = new Set, families = new Map, isRecursive = false, timestamp = performance.now()) => {
546
559
  const selectors = new Set;
547
560
  for (const atom of atoms) {
548
561
  addSetToSet(data.stateDependents.get(atom), selectors);
@@ -560,7 +573,7 @@ var propagateUpdatedAtoms = (atoms, data, subscriptions = new Set, families = ne
560
573
  addSetToSet(data.subscriptions.get(family), subscriptions);
561
574
  if (familyAtoms.size === 0)
562
575
  throw new Error("Should not be possible");
563
- addFamilyAtomsToSet(family, familyAtoms, data);
576
+ addFamilyAtomsToSet(family, familyAtoms, data, timestamp);
564
577
  }
565
578
  }
566
579
  if (!isRecursive) {
@@ -833,10 +846,15 @@ class Transaction {
833
846
  _selectorDependencies;
834
847
  _selectorCache;
835
848
  _atomMap;
836
- constructor(data, parentTransaction) {
849
+ constructor(data, parentTransaction, childTransaction) {
837
850
  this.data = data;
838
851
  this.parentTransaction = parentTransaction;
839
852
  this.dirty = false;
853
+ if (childTransaction) {
854
+ this._scopedTransactions = new Map([
855
+ [childTransaction.data.id, childTransaction]
856
+ ]);
857
+ }
840
858
  }
841
859
  valueFromTxnOrData = (state) => {
842
860
  if (this.atomMap.has(state)) {
@@ -890,20 +908,47 @@ class Transaction {
890
908
  if (!this.dirty)
891
909
  this.dirty = true;
892
910
  if (isFamilyAtom(atom)) {
893
- const currentFamilyList = this.get(atom.family);
894
- if (currentFamilyList && !currentFamilyList.__index.has(atom)) {
895
- const index = currentFamilyList ? currentFamilyList.__index.clone() : new FamilyIndex(atom.family, this.data);
896
- index.add([atom]);
897
- this.atomMap.set(atom.family, index.toArray());
911
+ if (!this.atomMap.has(atom.family)) {
912
+ this.cloneFamilyIntoTxn(atom.family);
898
913
  }
914
+ const index = this.atomMap.get(atom.family).__index;
915
+ index.created.set(atom, performance.now());
916
+ index.deleted.delete(atom);
917
+ index.rendered = null;
918
+ index.renderedArray = null;
919
+ this.recursivlyUpdateAtomFamilyIndexes(atom.family);
899
920
  }
900
921
  return value;
901
922
  };
923
+ batchSetFamilyAtoms(family, pairs) {
924
+ if (!this.atomMap.has(family)) {
925
+ this.cloneFamilyIntoTxn(family);
926
+ }
927
+ const index = this.atomMap.get(family).__index;
928
+ for (const [atom, value] of pairs) {
929
+ if (atom.family !== family) {
930
+ throw new Error("Atom does not belong to the provided family");
931
+ }
932
+ index.created.set(atom, performance.now());
933
+ if (index.deleted.has(atom))
934
+ index.deleted.delete(atom);
935
+ this.atomMap.set(atom, value);
936
+ }
937
+ index.rendered = null;
938
+ index.renderedArray = null;
939
+ this.recursivlyUpdateAtomFamilyIndexes(family);
940
+ }
902
941
  del = (atom) => {
903
- const index = this.get(atom.family).__index;
904
- const cloned = index.clone();
905
- cloned.delete([atom]);
906
- this.atomMap.set(atom.family, cloned.toArray());
942
+ if (!this.atomMap.has(atom.family)) {
943
+ this.cloneFamilyIntoTxn(atom.family);
944
+ }
945
+ const index = this.atomMap.get(atom.family).__index;
946
+ index.created.delete(atom);
947
+ index.deleted.set(atom, performance.now());
948
+ index.rendered = null;
949
+ index.renderedArray = null;
950
+ this.atomMap.set(atom.family, renderAtomFamilyIndex(index));
951
+ this.recursivlyUpdateAtomFamilyIndexes(atom.family);
907
952
  if (this.data.values.has(atom)) {
908
953
  this.deleteSet.add(atom);
909
954
  }
@@ -919,10 +964,10 @@ class Transaction {
919
964
  }
920
965
  };
921
966
  parentScope = (callback) => {
922
- if (!this._parentTransaction) {
923
- this._parentTransaction = new Transaction(this.data.parent);
967
+ if (!this.parentTransaction) {
968
+ this.parentTransaction = new Transaction(this.data.parent, undefined, this);
924
969
  }
925
- return this._parentTransaction.execute(callback, false);
970
+ return this.parentTransaction.execute(callback, false);
926
971
  };
927
972
  reset = (atom) => {
928
973
  const value = getAtomInitValue(atom, this.data, this.initializedAtomsSet);
@@ -932,9 +977,16 @@ class Transaction {
932
977
  execute = (callback, autoCommit = true) => {
933
978
  const result = callback(this);
934
979
  if (autoCommit)
935
- this.commit();
980
+ this.txnCommit();
936
981
  return result;
937
982
  };
983
+ txnCommit = () => {
984
+ if (this.parentTransaction) {
985
+ this.parentTransaction.txnCommit();
986
+ } else {
987
+ this.commit();
988
+ }
989
+ };
938
990
  commit = () => {
939
991
  const initializedAtomsSet = new Set;
940
992
  setAtoms(this.atomMap, this.data, initializedAtomsSet);
@@ -942,13 +994,10 @@ class Transaction {
942
994
  deleteAtomFamilyAtoms(this.deleteSet, this.data);
943
995
  }
944
996
  if (this._scopedTransactions) {
945
- for (const scopedTxn of Object.values(this._scopedTransactions)) {
997
+ for (const [, scopedTxn] of this._scopedTransactions) {
946
998
  scopedTxn.commit();
947
999
  }
948
1000
  }
949
- if (this._parentTransaction) {
950
- this._parentTransaction.commit();
951
- }
952
1001
  };
953
1002
  get atomMap() {
954
1003
  if (!this._atomMap)
@@ -977,13 +1026,37 @@ class Transaction {
977
1026
  }
978
1027
  scopedTransaction(scopeId) {
979
1028
  if (!this._scopedTransactions)
980
- this._scopedTransactions = {};
981
- if (!this._scopedTransactions[scopeId]) {
1029
+ this._scopedTransactions = new Map;
1030
+ if (!this._scopedTransactions.has(scopeId)) {
982
1031
  const scopedData = this.data.scopes[scopeId];
983
1032
  const scopedTransaction = new Transaction(scopedData, this);
984
- this._scopedTransactions[scopeId] = scopedTransaction;
1033
+ this._scopedTransactions.set(scopeId, scopedTransaction);
1034
+ }
1035
+ return this._scopedTransactions.get(scopeId);
1036
+ }
1037
+ cloneFamilyIntoTxn(family, parentIndex, moveUpIfParent = true) {
1038
+ if (moveUpIfParent && this.parentTransaction)
1039
+ return this.parentTransaction.cloneFamilyIntoTxn(family, parentIndex, moveUpIfParent);
1040
+ const currentFamilyList = this.get(family);
1041
+ const clonedIndex = cloneAtomFamilyIndex(currentFamilyList.__index, parentIndex);
1042
+ if (this._scopedTransactions?.size) {
1043
+ for (const [, scopedTxn] of this._scopedTransactions) {
1044
+ scopedTxn.cloneFamilyIntoTxn(family, clonedIndex, false);
1045
+ }
1046
+ }
1047
+ this.atomMap.set(family, renderAtomFamilyIndex(clonedIndex));
1048
+ }
1049
+ recursivlyUpdateAtomFamilyIndexes(atomFamily) {
1050
+ const currentIndex = this.atomMap.get(atomFamily).__index;
1051
+ currentIndex.rendered = null;
1052
+ currentIndex.renderedArray = null;
1053
+ const updatedValue = renderAtomFamilyIndex(currentIndex);
1054
+ this.atomMap.set(atomFamily, updatedValue);
1055
+ if (this._scopedTransactions?.size) {
1056
+ for (const [, scopedTxn] of this._scopedTransactions) {
1057
+ scopedTxn.recursivlyUpdateAtomFamilyIndexes(atomFamily);
1058
+ }
985
1059
  }
986
- return this._scopedTransactions[scopeId];
987
1060
  }
988
1061
  }
989
1062
  var transaction = (callback, data) => {
@@ -1031,7 +1104,10 @@ function storeFromStoreData(data, detach) {
1031
1104
  scopedStoreData.scopeConsumers.delete(detach2);
1032
1105
  if (scopedStoreData.scopeConsumers.size === 0) {
1033
1106
  delete data.scopes[scopeId];
1107
+ return true;
1034
1108
  }
1109
+ console.warn(`Scope still has ${scopedStoreData.scopeConsumers.size} consumers, will not detach`);
1110
+ return false;
1035
1111
  };
1036
1112
  scopedStoreData.scopeConsumers.add(detach2);
1037
1113
  const newStore = storeFromStoreData(data.scopes[scopeId], detach2);
@@ -1394,9 +1470,9 @@ var isFamilySelector = (state) => isFamilyState(state) && isSelector(state);
1394
1470
 
1395
1471
  // src/index.ts
1396
1472
  if (globalThis.__valdres__) {
1397
- throw new Error(`Error! An instance of valdres is already loaded. Loaded: ${globalThis.__valdres__}. Attempted to load: ${"0.2.0-pre.15"}`);
1473
+ throw new Error(`Error! An instance of valdres is already loaded. Loaded: ${globalThis.__valdres__}. Attempted to load: ${"0.2.0-pre.17"}`);
1398
1474
  } else {
1399
- globalThis.__valdres__ = "0.2.0-pre.15";
1475
+ globalThis.__valdres__ = "0.2.0-pre.17";
1400
1476
  }
1401
1477
  export {
1402
1478
  store,
@@ -5,21 +5,21 @@ import type { Family } from "../types/Family";
5
5
  import type { Selector } from "../types/Selector";
6
6
  import type { StoreData } from "../types/StoreData";
7
7
  import type { Subscription } from "../types/Subscription";
8
- export declare class FamilyIndex {
9
- map: Map<AtomFamilyAtom<any>, boolean>;
10
- family: Family<any>;
11
- data: StoreData;
12
- parentIndex: FamilyIndex | undefined;
13
- constructor(family: Family<any>, data: StoreData, parentIndex?: FamilyIndex, map?: Map<AtomFamilyAtom<any>, boolean>);
14
- add(atoms: AtomFamilyAtom<any>[]): void;
15
- delete(atoms: AtomFamilyAtom<any>[]): void;
16
- has(atom: AtomFamilyAtom<any>): boolean;
17
- clone(): FamilyIndex;
18
- toSet(): Set<AtomFamilyAtom<any>>;
19
- toArray(): AtomFamilyAtom<any>[];
20
- }
21
- export declare const deleteFamilyAtomsFromSet: (family: Family<any>, familyAtoms: Set<AtomFamilyAtom<any>>, data: StoreData) => void;
22
- export declare const addFamilyAtomsToSet: (family: Family<any>, familyAtoms: Set<AtomFamilyAtom<any>>, data: StoreData) => void;
23
- export declare const propagateDeletedAtoms: (atoms: AtomFamilyAtom<any, any>[], data: StoreData, subscriptions?: Set<Subscription>, families?: Map<AtomFamily<any>, Set<AtomFamilyAtom<any>>>) => void;
24
- export declare const propagateUpdatedAtoms: (atoms: (Atom<any> | AtomFamilyAtom<any, any> | AtomFamily<any, any>)[], data: StoreData, subscriptions?: Set<Subscription>, families?: Map<AtomFamily<any>, Set<AtomFamilyAtom<any>>>, isRecursive?: boolean) => void;
8
+ export declare const renderAtomFamilyIndex: (index: AtomFamilyIndex) => unknown[];
9
+ type AtomFamilyIndex = {
10
+ created: Map<AtomFamilyAtom<any, any>, Number>;
11
+ deleted: Map<AtomFamilyAtom<any, any>, Number>;
12
+ rendered: Map<AtomFamilyAtom<any, any>, Number> | null;
13
+ renderedArray: (AtomFamilyAtom<any, any>[] & {
14
+ __index: AtomFamilyIndex;
15
+ }) | null;
16
+ parentIndex?: AtomFamilyIndex;
17
+ };
18
+ export declare const cloneAtomFamilyIndex: (index: AtomFamilyIndex, parentIndexOverride?: AtomFamilyIndex) => AtomFamilyIndex;
19
+ export declare const createAtomFamilyIndex: (parentIndex?: AtomFamilyIndex) => AtomFamilyIndex;
20
+ export declare const deleteFamilyAtomsFromSet: (family: Family<any>, familyAtoms: Set<AtomFamilyAtom<any>>, data: StoreData, timestamp: number) => void;
21
+ export declare const addFamilyAtomsToSet: (family: Family<any>, familyAtoms: Set<AtomFamilyAtom<any>>, data: StoreData, timestamp: Number) => void;
22
+ export declare const propagateDeletedAtoms: (atoms: AtomFamilyAtom<any, any>[], data: StoreData, subscriptions?: Set<Subscription>, families?: Map<AtomFamily<any>, Set<AtomFamilyAtom<any>>>, timestamp?: number) => void;
23
+ export declare const propagateUpdatedAtoms: (atoms: (Atom<any> | AtomFamilyAtom<any, any> | AtomFamily<any, any>)[], data: StoreData, subscriptions?: Set<Subscription>, families?: Map<AtomFamily<any>, Set<AtomFamilyAtom<any>>>, isRecursive?: boolean, timestamp?: number) => void;
25
24
  export declare const propagateDirtySelectors: (updatedAtoms: Atom[], selectors: Set<Selector>, data: StoreData, subscriptions: Set<Subscription>, families: Map<AtomFamily<any>, Set<AtomFamilyAtom<any>>>) => void;
25
+ export {};
@@ -13,15 +13,17 @@ export declare class Transaction {
13
13
  private _selectorDependencies;
14
14
  private _selectorCache;
15
15
  private _atomMap;
16
- constructor(data: StoreData, parentTransaction?: Transaction);
16
+ constructor(data: StoreData, parentTransaction?: Transaction, childTransaction?: Transaction);
17
17
  private valueFromTxnOrData;
18
18
  get: GetValue;
19
19
  set: <V>(atom: Atom<V>, value: V | ((currentValue: V) => V)) => V;
20
+ batchSetFamilyAtoms(family: any, pairs: any): void;
20
21
  del: (atom: AtomFamilyAtom<any, any>) => void;
21
22
  scope: (scopeId: string, callback: (txn: Transaction) => any) => any;
22
23
  parentScope: (callback: (txn: Transaction) => any) => any;
23
24
  reset: (atom: Atom) => any;
24
25
  execute: (callback: TransactionFn, autoCommit?: boolean) => any;
26
+ private txnCommit;
25
27
  commit: () => void;
26
28
  private get atomMap();
27
29
  private get selectorCache();
@@ -29,5 +31,7 @@ export declare class Transaction {
29
31
  private get deleteSet();
30
32
  private get initializedAtomsSet();
31
33
  private scopedTransaction;
34
+ private cloneFamilyIntoTxn;
35
+ private recursivlyUpdateAtomFamilyIndexes;
32
36
  }
33
37
  export declare const transaction: (callback: TransactionFn, data: StoreData) => any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valdres",
3
- "version": "0.2.0-pre.15",
3
+ "version": "0.2.0-pre.17",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Eigil Sagafos"