@legendapp/state 2.2.0-next.0 → 2.2.0-next.3
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/index.d.ts +1 -6
- package/index.js +120 -106
- package/index.js.map +1 -1
- package/index.mjs +120 -106
- package/index.mjs.map +1 -1
- package/package.json +1 -1
- package/persist-plugins/firebase.js +3 -3
- package/persist-plugins/firebase.js.map +1 -1
- package/persist-plugins/firebase.mjs +3 -3
- package/persist-plugins/firebase.mjs.map +1 -1
- package/persist.js +105 -61
- package/persist.js.map +1 -1
- package/persist.mjs +106 -62
- package/persist.mjs.map +1 -1
- package/src/globals.d.ts +2 -7
- package/src/observable.d.ts +6 -6
- package/src/observableInterfaces.d.ts +38 -12
- package/src/persist/persistObservable.d.ts +10 -1
package/index.d.ts
CHANGED
|
@@ -24,12 +24,7 @@ export declare const internal: {
|
|
|
24
24
|
isLoadingLocal: boolean;
|
|
25
25
|
isMerging: boolean;
|
|
26
26
|
isLoadingRemote$: import("./src/observableInterfaces").ObservablePrimitiveBaseFns<boolean> & import("./src/observableInterfaces").ObservablePrimitiveBooleanFns<boolean>;
|
|
27
|
-
|
|
28
|
-
activateNode: (node: import("./src/observableInterfaces").NodeValue, newValue: any, setter: (value: any) => void, subscriber: (params: {
|
|
29
|
-
update: any;
|
|
30
|
-
}) => void, cacheOptions: import("./src/observableInterfaces").CacheOptions<any>) => {
|
|
31
|
-
update: any;
|
|
32
|
-
};
|
|
27
|
+
activateNode: (node: import("./src/observableInterfaces").NodeValue, refresh: () => void, newValue: any) => void;
|
|
33
28
|
};
|
|
34
29
|
observableFns: Map<string, (node: import("./src/observableInterfaces").NodeValue, ...args: any[]) => any>;
|
|
35
30
|
optimized: symbol;
|
package/index.js
CHANGED
|
@@ -62,7 +62,6 @@ const globalState = {
|
|
|
62
62
|
isLoadingLocal: false,
|
|
63
63
|
isMerging: false,
|
|
64
64
|
isLoadingRemote$: undefined,
|
|
65
|
-
onChangeRemote: undefined,
|
|
66
65
|
activateNode: undefined,
|
|
67
66
|
};
|
|
68
67
|
function isObservable(obs) {
|
|
@@ -1472,7 +1471,9 @@ function extractPromise(node, value) {
|
|
|
1472
1471
|
}
|
|
1473
1472
|
function extractFunctionOrComputed(node, obj, k, v) {
|
|
1474
1473
|
if (isPromise(v)) {
|
|
1475
|
-
|
|
1474
|
+
const childNode = getChildNode(node, k);
|
|
1475
|
+
extractPromise(childNode, v);
|
|
1476
|
+
setNodeValue(childNode, undefined);
|
|
1476
1477
|
}
|
|
1477
1478
|
else if (typeof v === 'function') {
|
|
1478
1479
|
extractFunction(node, k, v);
|
|
@@ -1516,26 +1517,36 @@ function peek(node) {
|
|
|
1516
1517
|
checkActivate(node);
|
|
1517
1518
|
return value;
|
|
1518
1519
|
}
|
|
1519
|
-
function
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1520
|
+
function createNodeActivationParams(node) {
|
|
1521
|
+
node.activationState = {
|
|
1522
|
+
lastSync: {},
|
|
1523
|
+
};
|
|
1524
|
+
const state = node.activationState;
|
|
1525
|
+
// The onSet function handles the observable being set
|
|
1526
|
+
// and forwards the set elsewhere
|
|
1527
|
+
const onSet = (onSetFnParam) => {
|
|
1528
|
+
state.onSetFn = onSetFnParam;
|
|
1529
|
+
};
|
|
1524
1530
|
// The onSet function handles the observable being set
|
|
1525
1531
|
// and forwards the set elsewhere
|
|
1526
|
-
const
|
|
1527
|
-
|
|
1532
|
+
const updateLastSync = (fn) => {
|
|
1533
|
+
state.lastSync.value = fn;
|
|
1528
1534
|
};
|
|
1529
1535
|
// The subscribe function runs a function that listens to
|
|
1530
1536
|
// a data source and sends updates into the observable
|
|
1531
1537
|
const subscribe = (fn) => {
|
|
1532
|
-
if (!subscriber) {
|
|
1533
|
-
subscriber = fn;
|
|
1538
|
+
if (!state.subscriber) {
|
|
1539
|
+
state.subscriber = fn;
|
|
1534
1540
|
}
|
|
1535
1541
|
};
|
|
1536
1542
|
const cache = (fn) => {
|
|
1537
|
-
if (!cacheOptions) {
|
|
1538
|
-
cacheOptions = isFunction(fn) ? fn() : fn;
|
|
1543
|
+
if (!state.cacheOptions) {
|
|
1544
|
+
state.cacheOptions = isFunction(fn) ? fn() : fn;
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
const retry = (params) => {
|
|
1548
|
+
if (!state.retryOptions) {
|
|
1549
|
+
state.retryOptions = params;
|
|
1539
1550
|
}
|
|
1540
1551
|
};
|
|
1541
1552
|
// The proxy function simply marks the node as a proxy with this function
|
|
@@ -1544,20 +1555,31 @@ function activateNodeFunction(node, lazyFn) {
|
|
|
1544
1555
|
const proxy = (fn) => {
|
|
1545
1556
|
node.proxyFn2 = fn;
|
|
1546
1557
|
};
|
|
1558
|
+
return {
|
|
1559
|
+
onSet,
|
|
1560
|
+
proxy,
|
|
1561
|
+
cache,
|
|
1562
|
+
retry,
|
|
1563
|
+
subscribe,
|
|
1564
|
+
updateLastSync,
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
function activateNodeFunction(node, lazyFn) {
|
|
1547
1568
|
let prevTarget$;
|
|
1548
1569
|
let curTarget$;
|
|
1549
1570
|
const activator = (isFunction(node) ? node : lazyFn);
|
|
1550
1571
|
let wasPromise;
|
|
1551
|
-
|
|
1572
|
+
const refresh = () => node.state.refreshNum.set((v) => v + 1);
|
|
1552
1573
|
observe(() => {
|
|
1574
|
+
const params = createNodeActivationParams(node);
|
|
1553
1575
|
// Run the function at this node
|
|
1554
|
-
let value = activator(
|
|
1576
|
+
let value = activator(params);
|
|
1555
1577
|
// If target is an observable, get() it to make sure we listen to its changes
|
|
1556
1578
|
// and set up an onSet to write changes back to it
|
|
1557
1579
|
if (isObservable(value)) {
|
|
1558
1580
|
prevTarget$ = curTarget$;
|
|
1559
1581
|
curTarget$ = value;
|
|
1560
|
-
onSet(({ value: newValue, getPrevious }) => {
|
|
1582
|
+
params.onSet(({ value: newValue, getPrevious }) => {
|
|
1561
1583
|
// Don't set the target observable if the target has changed since the last run
|
|
1562
1584
|
if (!prevTarget$ || curTarget$ === prevTarget$) {
|
|
1563
1585
|
// Set the node value back to what it was before before setting it.
|
|
@@ -1574,25 +1596,28 @@ function activateNodeFunction(node, lazyFn) {
|
|
|
1574
1596
|
// for the effect.
|
|
1575
1597
|
value = value.get();
|
|
1576
1598
|
}
|
|
1577
|
-
|
|
1599
|
+
else {
|
|
1600
|
+
wasPromise = isPromise(value) ? value : undefined;
|
|
1601
|
+
}
|
|
1602
|
+
// Activate this node if not activated already (may be called recursively)
|
|
1603
|
+
// TODO: Is calling recursively bad? If so can it be fixed?
|
|
1578
1604
|
if (!node.activated) {
|
|
1579
1605
|
node.activated = true;
|
|
1580
1606
|
const activateNodeFn = wasPromise ? globalState.activateNode : activateNodeBase;
|
|
1581
|
-
|
|
1582
|
-
}
|
|
1583
|
-
if (wasPromise) {
|
|
1584
|
-
value = undefined;
|
|
1607
|
+
activateNodeFn(node, refresh, value);
|
|
1585
1608
|
}
|
|
1609
|
+
node.state.refreshNum.get();
|
|
1586
1610
|
return value;
|
|
1587
1611
|
}, ({ value }) => {
|
|
1588
1612
|
if (!globalState.isLoadingRemote$.peek()) {
|
|
1589
1613
|
if (wasPromise) {
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1614
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1615
|
+
extractPromise(node, value);
|
|
1616
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1617
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1618
|
+
// cache or a previous run
|
|
1619
|
+
if (isFunction(getNodeValue(node))) {
|
|
1620
|
+
setNodeValue(node, undefined);
|
|
1596
1621
|
}
|
|
1597
1622
|
}
|
|
1598
1623
|
else {
|
|
@@ -1600,24 +1625,23 @@ function activateNodeFunction(node, lazyFn) {
|
|
|
1600
1625
|
node.state.isLoaded.set(true);
|
|
1601
1626
|
}
|
|
1602
1627
|
}
|
|
1603
|
-
isInitial = false;
|
|
1604
1628
|
}, { immediate: true, fromComputed: true });
|
|
1605
1629
|
}
|
|
1606
|
-
const activateNodeBase = (globalState.activateNode = function activateNodeBase(node,
|
|
1630
|
+
const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, refresh) {
|
|
1631
|
+
const { onSetFn, subscriber } = node.activationState;
|
|
1607
1632
|
let isSetting = false;
|
|
1608
1633
|
if (!node.state) {
|
|
1609
1634
|
node.state = createObservable({
|
|
1610
1635
|
isLoaded: false,
|
|
1611
1636
|
}, false, extractPromise, getProxy);
|
|
1612
1637
|
}
|
|
1613
|
-
if (
|
|
1638
|
+
if (onSetFn) {
|
|
1614
1639
|
const doSet = (params) => {
|
|
1615
1640
|
// Don't call the set if this is the first value coming in
|
|
1616
1641
|
if (!isSetting) {
|
|
1617
1642
|
if (params.changes.length > 1 || !isFunction(params.changes[0].prevAtPath)) {
|
|
1618
1643
|
isSetting = true;
|
|
1619
|
-
|
|
1620
|
-
batch(() => setter(params), () => {
|
|
1644
|
+
batch(() => onSetFn(params), () => {
|
|
1621
1645
|
isSetting = false;
|
|
1622
1646
|
});
|
|
1623
1647
|
}
|
|
@@ -1625,25 +1649,24 @@ const activateNodeBase = (globalState.activateNode = function activateNodeBase(n
|
|
|
1625
1649
|
};
|
|
1626
1650
|
onChange(node, doSet, { immediate: true });
|
|
1627
1651
|
}
|
|
1628
|
-
if (process.env.NODE_ENV === 'development' && cacheOptions) {
|
|
1652
|
+
if (process.env.NODE_ENV === 'development' && node.activationState.cacheOptions) {
|
|
1653
|
+
// TODO Better message
|
|
1654
|
+
console.log('[legend-state] Using cacheOptions without setting up persistence first');
|
|
1655
|
+
}
|
|
1656
|
+
if (process.env.NODE_ENV === 'development' && node.activationState.retryOptions) {
|
|
1629
1657
|
// TODO Better message
|
|
1630
|
-
console.log('[legend-state] Using
|
|
1658
|
+
console.log('[legend-state] Using retryOptions without setting up persistence first');
|
|
1631
1659
|
}
|
|
1632
1660
|
const update = ({ value }) => {
|
|
1661
|
+
// TODO: This isSetting might not be necessary? Tests still work if removing it.
|
|
1662
|
+
// Write tests that would break it if removed? I'd guess a combination of subscribe and
|
|
1633
1663
|
if (!isSetting) {
|
|
1634
|
-
|
|
1635
|
-
set(node, value);
|
|
1636
|
-
});
|
|
1664
|
+
set(node, value);
|
|
1637
1665
|
}
|
|
1638
1666
|
};
|
|
1639
|
-
const isProm = isPromise(newValue);
|
|
1640
|
-
if (isProm) {
|
|
1641
|
-
extractPromise(node, newValue);
|
|
1642
|
-
}
|
|
1643
1667
|
if (subscriber) {
|
|
1644
|
-
subscriber({ update });
|
|
1668
|
+
subscriber({ update, refresh });
|
|
1645
1669
|
}
|
|
1646
|
-
return { update };
|
|
1647
1670
|
});
|
|
1648
1671
|
|
|
1649
1672
|
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
@@ -1687,60 +1710,6 @@ ObservablePrimitiveClass.prototype.delete = function () {
|
|
|
1687
1710
|
return this;
|
|
1688
1711
|
};
|
|
1689
1712
|
|
|
1690
|
-
function _when(predicate, effect, checkReady) {
|
|
1691
|
-
// If predicate is a regular Promise skip all the observable stuff
|
|
1692
|
-
if (isPromise(predicate)) {
|
|
1693
|
-
return effect ? predicate.then(effect) : predicate;
|
|
1694
|
-
}
|
|
1695
|
-
let value;
|
|
1696
|
-
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1697
|
-
function run(e) {
|
|
1698
|
-
const ret = computeSelector(predicate);
|
|
1699
|
-
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1700
|
-
value = ret;
|
|
1701
|
-
// Set cancel so that observe does not track anymore
|
|
1702
|
-
e.cancel = true;
|
|
1703
|
-
}
|
|
1704
|
-
return value;
|
|
1705
|
-
}
|
|
1706
|
-
function doEffect() {
|
|
1707
|
-
// If value is truthy then run the effect
|
|
1708
|
-
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1709
|
-
}
|
|
1710
|
-
// Run in an observe
|
|
1711
|
-
observe(run, doEffect);
|
|
1712
|
-
// If first run resulted in a truthy value just return it.
|
|
1713
|
-
// It will have set e.cancel so no need to dispose
|
|
1714
|
-
if (isPromise(value)) {
|
|
1715
|
-
return effect ? value.then(effect) : value;
|
|
1716
|
-
}
|
|
1717
|
-
else if (value !== undefined) {
|
|
1718
|
-
return Promise.resolve(value);
|
|
1719
|
-
}
|
|
1720
|
-
else {
|
|
1721
|
-
// Wrap it in a promise
|
|
1722
|
-
const promise = new Promise((resolve) => {
|
|
1723
|
-
if (effect) {
|
|
1724
|
-
const originalEffect = effect;
|
|
1725
|
-
effect = (value) => {
|
|
1726
|
-
const effectValue = originalEffect(value);
|
|
1727
|
-
resolve(effectValue);
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
else {
|
|
1731
|
-
effect = resolve;
|
|
1732
|
-
}
|
|
1733
|
-
});
|
|
1734
|
-
return promise;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
function when(predicate, effect) {
|
|
1738
|
-
return _when(predicate, effect, false);
|
|
1739
|
-
}
|
|
1740
|
-
function whenReady(predicate, effect) {
|
|
1741
|
-
return _when(predicate, effect, true);
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
1713
|
function observable(value) {
|
|
1745
1714
|
return createObservable(value, false, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1746
1715
|
}
|
|
@@ -1748,15 +1717,6 @@ function observablePrimitive(value) {
|
|
|
1748
1717
|
return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1749
1718
|
}
|
|
1750
1719
|
globalState.isLoadingRemote$ = observable(false);
|
|
1751
|
-
globalState.onChangeRemote = function onChangeRemote(cb) {
|
|
1752
|
-
when(() => !globalState.isLoadingRemote$.get(), () => {
|
|
1753
|
-
// Remote changes should only update local state
|
|
1754
|
-
globalState.isLoadingRemote$.set(true);
|
|
1755
|
-
batch(cb, () => {
|
|
1756
|
-
globalState.isLoadingRemote$.set(false);
|
|
1757
|
-
});
|
|
1758
|
-
});
|
|
1759
|
-
};
|
|
1760
1720
|
|
|
1761
1721
|
function computed(compute, set$1) {
|
|
1762
1722
|
// Create an observable for this computed variable
|
|
@@ -1920,6 +1880,60 @@ function proxy(get, set) {
|
|
|
1920
1880
|
return obs;
|
|
1921
1881
|
}
|
|
1922
1882
|
|
|
1883
|
+
function _when(predicate, effect, checkReady) {
|
|
1884
|
+
// If predicate is a regular Promise skip all the observable stuff
|
|
1885
|
+
if (isPromise(predicate)) {
|
|
1886
|
+
return effect ? predicate.then(effect) : predicate;
|
|
1887
|
+
}
|
|
1888
|
+
let value;
|
|
1889
|
+
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1890
|
+
function run(e) {
|
|
1891
|
+
const ret = computeSelector(predicate);
|
|
1892
|
+
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1893
|
+
value = ret;
|
|
1894
|
+
// Set cancel so that observe does not track anymore
|
|
1895
|
+
e.cancel = true;
|
|
1896
|
+
}
|
|
1897
|
+
return value;
|
|
1898
|
+
}
|
|
1899
|
+
function doEffect() {
|
|
1900
|
+
// If value is truthy then run the effect
|
|
1901
|
+
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1902
|
+
}
|
|
1903
|
+
// Run in an observe
|
|
1904
|
+
observe(run, doEffect);
|
|
1905
|
+
// If first run resulted in a truthy value just return it.
|
|
1906
|
+
// It will have set e.cancel so no need to dispose
|
|
1907
|
+
if (isPromise(value)) {
|
|
1908
|
+
return effect ? value.then(effect) : value;
|
|
1909
|
+
}
|
|
1910
|
+
else if (value !== undefined) {
|
|
1911
|
+
return Promise.resolve(value);
|
|
1912
|
+
}
|
|
1913
|
+
else {
|
|
1914
|
+
// Wrap it in a promise
|
|
1915
|
+
const promise = new Promise((resolve) => {
|
|
1916
|
+
if (effect) {
|
|
1917
|
+
const originalEffect = effect;
|
|
1918
|
+
effect = (value) => {
|
|
1919
|
+
const effectValue = originalEffect(value);
|
|
1920
|
+
resolve(effectValue);
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
else {
|
|
1924
|
+
effect = resolve;
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
return promise;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
function when(predicate, effect) {
|
|
1931
|
+
return _when(predicate, effect, false);
|
|
1932
|
+
}
|
|
1933
|
+
function whenReady(predicate, effect) {
|
|
1934
|
+
return _when(predicate, effect, true);
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1923
1937
|
const internal = {
|
|
1924
1938
|
ensureNodeValue,
|
|
1925
1939
|
findIDKey,
|