@mmstack/primitives 20.14.2 → 20.14.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
|
@@ -766,7 +766,8 @@ const profile = persistedStore({ first: '', last: '' }, {
|
|
|
766
766
|
`persistedStore` is `store()` + `persist()`. Reach for `persist(store, opt)` directly to add durability to a store you already have — one you also `meshSync`, or a worker-owned store's replica. Persistence is a reader over the op-log, so it composes with the other readers on the same store.
|
|
767
767
|
|
|
768
768
|
```typescript
|
|
769
|
-
import { store, persist
|
|
769
|
+
import { store, persist } from '@mmstack/primitives';
|
|
770
|
+
import { meshSync } from '@mmstack/mesh';
|
|
770
771
|
|
|
771
772
|
const doc = store({ title: '', body: '' });
|
|
772
773
|
persist(doc, { key: 'draft', store: idbKeyval }); // durable to IndexedDB
|
|
@@ -1741,8 +1741,7 @@ function createImmutableObjectUpdater(source, key, vivifyFn) {
|
|
|
1741
1741
|
return { ...vivified, [key]: next };
|
|
1742
1742
|
});
|
|
1743
1743
|
}
|
|
1744
|
-
function
|
|
1745
|
-
const sample = untracked(source);
|
|
1744
|
+
function createUpdaterFromSample(source, key, vivify, sample) {
|
|
1746
1745
|
// fast path for when vivification is off
|
|
1747
1746
|
if (!vivify) {
|
|
1748
1747
|
if (Array.isArray(sample) && typeof key === 'number') {
|
|
@@ -1790,6 +1789,19 @@ function createUpdater(source, key, vivify) {
|
|
|
1790
1789
|
? createMutableObjectUpdater(source, key, vivifyFn)
|
|
1791
1790
|
: createImmutableObjectUpdater(source, key, vivifyFn);
|
|
1792
1791
|
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Selects the property updater once, on the first actual write. Construction must not sample the
|
|
1794
|
+
* source: a writable derivation may currently throw, and reads still need a child producer that can
|
|
1795
|
+
* subscribe and recover. The routing sample remains deliberately untracked, so deferring it adds no
|
|
1796
|
+
* dependency to the caller.
|
|
1797
|
+
*/
|
|
1798
|
+
function createUpdater(source, key, vivify) {
|
|
1799
|
+
let update;
|
|
1800
|
+
return (next) => {
|
|
1801
|
+
update ??= createUpdaterFromSample(source, key, vivify, untracked(source));
|
|
1802
|
+
update(next);
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1793
1805
|
function derived(source, optOrKey, opt) {
|
|
1794
1806
|
const vivify = typeof optOrKey === 'object' ? false : (opt?.vivify ?? false);
|
|
1795
1807
|
// With vivification the source may legitimately be null/undefined
|
|
@@ -4481,14 +4493,19 @@ function alwaysFalse() {
|
|
|
4481
4493
|
function markAsLeaf(sig, value, vivifyEnabled, noUnionLeaves) {
|
|
4482
4494
|
if (typeof sig[LEAF] !== 'function') {
|
|
4483
4495
|
let memo;
|
|
4496
|
+
let initialClassification;
|
|
4484
4497
|
const probe = () => {
|
|
4485
4498
|
if (memo)
|
|
4486
4499
|
return memo();
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4500
|
+
if (noUnionLeaves) {
|
|
4501
|
+
initialClassification ??= computed(() => isLeafValue(value(), vivifyEnabled));
|
|
4502
|
+
const result = initialClassification();
|
|
4503
|
+
memo = result ? alwaysTrue : alwaysFalse;
|
|
4504
|
+
initialClassification = undefined;
|
|
4505
|
+
}
|
|
4506
|
+
else {
|
|
4507
|
+
memo = computed(() => isLeafValue(value(), vivifyEnabled));
|
|
4508
|
+
}
|
|
4492
4509
|
return memo();
|
|
4493
4510
|
};
|
|
4494
4511
|
Object.defineProperty(sig, LEAF, {
|
|
@@ -4562,21 +4579,19 @@ function mutableChildEqual(a, b) {
|
|
|
4562
4579
|
* correct after it. The only place a child node is constructed — shared by every container kind.
|
|
4563
4580
|
*/
|
|
4564
4581
|
function buildChildNode(target, prop, isMutableSource, options) {
|
|
4565
|
-
|
|
4566
|
-
const
|
|
4567
|
-
const
|
|
4568
|
-
const equalFn = isMutableSource && (isRecord$1(value) || Array.isArray(value))
|
|
4569
|
-
? mutableChildEqual
|
|
4570
|
-
: undefined;
|
|
4582
|
+
let vivifyFn = options.vivify === false ? createVivify(false) : undefined;
|
|
4583
|
+
const resolveVivifyFn = (sample) => (vivifyFn ??= createVivify(resolveVivify(sample, options.vivify)));
|
|
4584
|
+
const lazyVivify = (value, key) => resolveVivifyFn(value)(value, key);
|
|
4571
4585
|
const computation = derived(target, {
|
|
4572
|
-
from: (v) =>
|
|
4573
|
-
|
|
4574
|
-
|
|
4586
|
+
from: (v) => {
|
|
4587
|
+
resolveVivifyFn(v);
|
|
4588
|
+
return v?.[prop];
|
|
4589
|
+
},
|
|
4590
|
+
onChange: createFallbackOnChange(target, prop, lazyVivify, isMutableSource),
|
|
4591
|
+
equal: isMutableSource ? mutableChildEqual : undefined,
|
|
4575
4592
|
});
|
|
4576
|
-
const childSample = untracked(computation);
|
|
4577
|
-
const childVivify = resolveVivify(childSample, options.vivify);
|
|
4578
4593
|
const proxy = toStore(computation, options);
|
|
4579
|
-
markAsLeaf(proxy, computation,
|
|
4594
|
+
markAsLeaf(proxy, computation, options.vivify !== false, options.noUnionLeaves);
|
|
4580
4595
|
return proxy;
|
|
4581
4596
|
}
|
|
4582
4597
|
/**
|
|
@@ -4714,7 +4729,16 @@ function toStore(source, { injector, vivify = false, noUnionLeaves = false, ...r
|
|
|
4714
4729
|
if ((typeof prop === 'symbol' && prop !== Symbol.iterator) ||
|
|
4715
4730
|
(typeof prop === 'string' && SIGNAL_FN_PROP.has(prop)))
|
|
4716
4731
|
return target[prop];
|
|
4717
|
-
const
|
|
4732
|
+
const child = (key) => getCachedChild(target, prop, () => buildChildNode(target, key, isMutableSource, STORE_OPTIONS), STORE_OPTIONS[STORE_SHARED_GLOBALS].cache, STORE_OPTIONS[STORE_SHARED_GLOBALS].registry);
|
|
4733
|
+
let k;
|
|
4734
|
+
try {
|
|
4735
|
+
k = untracked(kind);
|
|
4736
|
+
}
|
|
4737
|
+
catch (cause) {
|
|
4738
|
+
if (typeof prop === 'string' && prop !== 'extend')
|
|
4739
|
+
return child(isIndexProp(prop) ? +prop : prop);
|
|
4740
|
+
throw cause;
|
|
4741
|
+
}
|
|
4718
4742
|
if (prop === 'extend' && k !== 'array')
|
|
4719
4743
|
return (seed) => scopedStore(s, seed, isMutableSource
|
|
4720
4744
|
? 'mutable'
|
|
@@ -4733,7 +4757,7 @@ function toStore(source, { injector, vivify = false, noUnionLeaves = false, ...r
|
|
|
4733
4757
|
}
|
|
4734
4758
|
if (k === 'array' && !isIndexProp(prop))
|
|
4735
4759
|
return Reflect.get(target, prop, receiver);
|
|
4736
|
-
return
|
|
4760
|
+
return child(k === 'array' ? +prop : prop);
|
|
4737
4761
|
},
|
|
4738
4762
|
});
|
|
4739
4763
|
return s;
|