@legendapp/state 3.0.0-alpha.1 → 3.0.0-alpha.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/.DS_Store +0 -0
- package/CHANGELOG.md +1 -831
- package/LICENSE +1 -21
- package/README.md +1 -141
- package/as/arrayAsRecord.d.mts +5 -0
- package/as/arrayAsRecord.d.ts +5 -0
- package/as/arrayAsRecord.js +28 -0
- package/as/arrayAsRecord.mjs +26 -0
- package/as/arrayAsSet.d.mts +5 -0
- package/as/arrayAsSet.d.ts +5 -0
- package/as/arrayAsSet.js +13 -0
- package/as/arrayAsSet.mjs +11 -0
- package/as/arrayAsString.d.mts +5 -0
- package/as/arrayAsString.d.ts +5 -0
- package/as/arrayAsString.js +13 -0
- package/as/arrayAsString.mjs +11 -0
- package/as/numberAsString.d.mts +5 -0
- package/as/numberAsString.d.ts +5 -0
- package/as/numberAsString.js +13 -0
- package/as/numberAsString.mjs +11 -0
- package/as/recordAsArray.d.mts +5 -0
- package/as/recordAsArray.d.ts +5 -0
- package/as/recordAsArray.js +25 -0
- package/as/recordAsArray.mjs +23 -0
- package/as/recordAsString.d.mts +5 -0
- package/as/recordAsString.d.ts +5 -0
- package/as/recordAsString.js +13 -0
- package/as/recordAsString.mjs +11 -0
- package/as/setAsArray.d.mts +5 -0
- package/as/setAsArray.d.ts +5 -0
- package/as/setAsArray.js +13 -0
- package/as/setAsArray.mjs +11 -0
- package/as/setAsString.d.mts +5 -0
- package/as/setAsString.d.ts +5 -0
- package/as/setAsString.js +13 -0
- package/as/setAsString.mjs +11 -0
- package/as/stringAsArray.d.mts +5 -0
- package/as/stringAsArray.d.ts +5 -0
- package/as/stringAsArray.js +13 -0
- package/as/stringAsArray.mjs +11 -0
- package/as/stringAsNumber.d.mts +5 -0
- package/as/stringAsNumber.d.ts +5 -0
- package/as/stringAsNumber.js +16 -0
- package/as/stringAsNumber.mjs +14 -0
- package/as/stringAsRecord.d.mts +5 -0
- package/as/stringAsRecord.d.ts +5 -0
- package/as/stringAsRecord.js +15 -0
- package/as/stringAsRecord.mjs +13 -0
- package/as/stringAsSet.d.mts +5 -0
- package/as/stringAsSet.d.ts +5 -0
- package/as/stringAsSet.js +13 -0
- package/as/stringAsSet.mjs +11 -0
- package/babel.d.mts +21 -0
- package/babel.d.ts +21 -2
- package/babel.js +57 -53
- package/babel.mjs +65 -0
- package/config/enable$GetSet.js +13 -14
- package/config/enable$GetSet.mjs +13 -14
- package/config/enableReactComponents.d.mts +9 -0
- package/config/enableReactComponents.d.ts +4 -2
- package/config/enableReactComponents.js +13 -10
- package/config/enableReactComponents.mjs +13 -10
- package/config/enableReactNativeComponents.d.mts +22 -0
- package/config/enableReactNativeComponents.d.ts +6 -4
- package/config/enableReactNativeComponents.js +43 -47
- package/config/enableReactNativeComponents.mjs +43 -47
- package/config/enableReactTracking.d.mts +7 -0
- package/config/enableReactTracking.d.ts +3 -2
- package/config/enableReactTracking.js +33 -38
- package/config/enableReactTracking.mjs +33 -38
- package/config/enableReactUse.d.mts +10 -0
- package/config/enableReactUse.d.ts +4 -1
- package/config/enableReactUse.js +15 -14
- package/config/enableReactUse.mjs +15 -14
- package/config/{enable$GetSet.d.ts → enable_GetSet.d.mts} +4 -2
- package/config/enable_GetSet.d.ts +10 -0
- package/config/enable_PeekAssign.d.mts +10 -0
- package/config/enable_PeekAssign.d.ts +4 -2
- package/config/enable_PeekAssign.js +13 -14
- package/config/enable_PeekAssign.mjs +13 -14
- package/helpers/pageHash.d.mts +9 -0
- package/helpers/pageHash.d.ts +2 -0
- package/helpers/pageHash.js +25 -30
- package/helpers/pageHash.mjs +25 -30
- package/helpers/pageHashParams.d.mts +9 -0
- package/helpers/pageHashParams.d.ts +2 -0
- package/helpers/pageHashParams.js +34 -37
- package/helpers/pageHashParams.mjs +34 -37
- package/helpers/time.d.mts +6 -0
- package/helpers/time.d.ts +6 -3
- package/helpers/time.js +17 -17
- package/helpers/time.mjs +17 -17
- package/helpers/trackHistory.d.mts +6 -0
- package/helpers/trackHistory.d.ts +4 -2
- package/helpers/trackHistory.js +13 -16
- package/helpers/trackHistory.mjs +13 -16
- package/helpers/undoRedo.d.mts +37 -0
- package/helpers/undoRedo.d.ts +5 -3
- package/helpers/undoRedo.js +59 -94
- package/helpers/undoRedo.mjs +59 -94
- package/index.d.mts +404 -0
- package/index.d.ts +371 -28
- package/index.js +2015 -2166
- package/index.mjs +2015 -2166
- package/package.json +254 -195
- package/persist-plugins/async-storage.d.mts +18 -0
- package/persist-plugins/async-storage.d.ts +6 -3
- package/persist-plugins/async-storage.js +79 -86
- package/persist-plugins/async-storage.mjs +79 -86
- package/persist-plugins/indexeddb.d.mts +29 -0
- package/persist-plugins/indexeddb.d.ts +6 -3
- package/persist-plugins/indexeddb.js +331 -352
- package/persist-plugins/indexeddb.mjs +331 -352
- package/persist-plugins/local-storage.d.mts +23 -0
- package/persist-plugins/local-storage.d.ts +8 -5
- package/persist-plugins/local-storage.js +74 -76
- package/persist-plugins/local-storage.mjs +74 -76
- package/persist-plugins/mmkv.d.mts +18 -0
- package/persist-plugins/mmkv.d.ts +6 -3
- package/persist-plugins/mmkv.js +82 -86
- package/persist-plugins/mmkv.mjs +82 -86
- package/react-hooks/createObservableHook.d.mts +5 -0
- package/react-hooks/createObservableHook.d.ts +4 -1
- package/react-hooks/createObservableHook.js +29 -30
- package/react-hooks/createObservableHook.mjs +25 -30
- package/react-hooks/useHover.d.mts +5 -0
- package/react-hooks/useHover.d.ts +5 -3
- package/react-hooks/useHover.js +29 -29
- package/react-hooks/useHover.mjs +29 -29
- package/react-hooks/useMeasure.d.mts +9 -0
- package/react-hooks/useMeasure.d.ts +5 -2
- package/react-hooks/useMeasure.js +30 -32
- package/react-hooks/useMeasure.mjs +30 -32
- package/react-hooks/useObservableNextRouter.d.mts +35 -0
- package/react-hooks/useObservableNextRouter.d.ts +9 -7
- package/react-hooks/useObservableNextRouter.js +64 -77
- package/react-hooks/useObservableNextRouter.mjs +60 -77
- package/react.d.mts +157 -0
- package/react.d.ts +157 -21
- package/react.js +458 -749
- package/react.mjs +457 -752
- package/sync-plugins/crud.d.mts +54 -0
- package/sync-plugins/crud.d.ts +12 -10
- package/sync-plugins/crud.js +253 -270
- package/sync-plugins/crud.mjs +253 -270
- package/sync-plugins/fetch.d.mts +21 -0
- package/sync-plugins/fetch.d.ts +7 -4
- package/sync-plugins/fetch.js +50 -37
- package/sync-plugins/fetch.mjs +50 -37
- package/sync-plugins/keel.d.mts +108 -0
- package/sync-plugins/keel.d.ts +17 -15
- package/sync-plugins/keel.js +229 -462
- package/sync-plugins/keel.mjs +227 -464
- package/sync-plugins/supabase.d.mts +39 -0
- package/sync-plugins/supabase.d.ts +16 -14
- package/sync-plugins/supabase.js +128 -128
- package/sync-plugins/supabase.mjs +128 -128
- package/sync-plugins/tanstack-query.d.mts +14 -0
- package/sync-plugins/tanstack-query.d.ts +7 -4
- package/sync-plugins/tanstack-query.js +51 -57
- package/sync-plugins/tanstack-query.mjs +51 -57
- package/sync-plugins/tanstack-react-query.d.mts +8 -0
- package/sync-plugins/tanstack-react-query.d.ts +6 -1
- package/sync-plugins/tanstack-react-query.js +2 -2
- package/sync-plugins/tanstack-react-query.mjs +2 -2
- package/sync.d.mts +351 -0
- package/sync.d.ts +349 -9
- package/sync.js +910 -964
- package/sync.mjs +920 -974
- package/trace.d.mts +9 -0
- package/trace.d.ts +9 -4
- package/trace.js +72 -62
- package/trace.mjs +72 -62
- package/types/babel.d.ts +1 -12
- package/babel.js.map +0 -1
- package/config/enable$GetSet.js.map +0 -1
- package/config/enable$GetSet.mjs.map +0 -1
- package/config/enableReactComponents.js.map +0 -1
- package/config/enableReactComponents.mjs.map +0 -1
- package/config/enableReactNativeComponents.js.map +0 -1
- package/config/enableReactNativeComponents.mjs.map +0 -1
- package/config/enableReactTracking.js.map +0 -1
- package/config/enableReactTracking.mjs.map +0 -1
- package/config/enableReactUse.js.map +0 -1
- package/config/enableReactUse.mjs.map +0 -1
- package/config/enable_PeekAssign.js.map +0 -1
- package/config/enable_PeekAssign.mjs.map +0 -1
- package/helpers/pageHash.js.map +0 -1
- package/helpers/pageHash.mjs.map +0 -1
- package/helpers/pageHashParams.js.map +0 -1
- package/helpers/pageHashParams.mjs.map +0 -1
- package/helpers/time.js.map +0 -1
- package/helpers/time.mjs.map +0 -1
- package/helpers/trackHistory.js.map +0 -1
- package/helpers/trackHistory.mjs.map +0 -1
- package/helpers/undoRedo.js.map +0 -1
- package/helpers/undoRedo.mjs.map +0 -1
- package/history.d.ts +0 -1
- package/history.js +0 -24
- package/history.js.map +0 -1
- package/history.mjs +0 -22
- package/history.mjs.map +0 -1
- package/index.js.map +0 -1
- package/index.mjs.map +0 -1
- package/persist-plugins/async-storage.js.map +0 -1
- package/persist-plugins/async-storage.mjs.map +0 -1
- package/persist-plugins/indexeddb.js.map +0 -1
- package/persist-plugins/indexeddb.mjs.map +0 -1
- package/persist-plugins/local-storage.js.map +0 -1
- package/persist-plugins/local-storage.mjs.map +0 -1
- package/persist-plugins/mmkv.js.map +0 -1
- package/persist-plugins/mmkv.mjs.map +0 -1
- package/react-hooks/createObservableHook.js.map +0 -1
- package/react-hooks/createObservableHook.mjs.map +0 -1
- package/react-hooks/useHover.js.map +0 -1
- package/react-hooks/useHover.mjs.map +0 -1
- package/react-hooks/useMeasure.js.map +0 -1
- package/react-hooks/useMeasure.mjs.map +0 -1
- package/react-hooks/useObservableNextRouter.js.map +0 -1
- package/react-hooks/useObservableNextRouter.mjs.map +0 -1
- package/react.js.map +0 -1
- package/react.mjs.map +0 -1
- package/src/ObservableObject.ts +0 -1350
- package/src/ObservablePrimitive.ts +0 -62
- package/src/babel/index.ts +0 -83
- package/src/batching.ts +0 -357
- package/src/computed.ts +0 -18
- package/src/config/enable$GetSet.ts +0 -30
- package/src/config/enableReactComponents.ts +0 -26
- package/src/config/enableReactNativeComponents.ts +0 -102
- package/src/config/enableReactTracking.ts +0 -62
- package/src/config/enableReactUse.ts +0 -32
- package/src/config/enable_PeekAssign.ts +0 -31
- package/src/config.ts +0 -47
- package/src/createObservable.ts +0 -47
- package/src/event.ts +0 -26
- package/src/globals.ts +0 -235
- package/src/helpers/pageHash.ts +0 -41
- package/src/helpers/pageHashParams.ts +0 -55
- package/src/helpers/time.ts +0 -30
- package/src/helpers/trackHistory.ts +0 -29
- package/src/helpers/undoRedo.ts +0 -111
- package/src/helpers.ts +0 -231
- package/src/is.ts +0 -63
- package/src/linked.ts +0 -17
- package/src/observable.ts +0 -32
- package/src/observableInterfaces.ts +0 -151
- package/src/observableTypes.ts +0 -232
- package/src/observe.ts +0 -89
- package/src/old-plugins/firebase.ts +0 -1053
- package/src/onChange.ts +0 -146
- package/src/persist/configureObservablePersistence.ts +0 -7
- package/src/persist/fieldTransformer.ts +0 -149
- package/src/persist/observablePersistRemoteFunctionsAdapter.ts +0 -39
- package/src/persist/persistObservable.ts +0 -1034
- package/src/persist-plugins/async-storage.ts +0 -99
- package/src/persist-plugins/indexeddb.ts +0 -439
- package/src/persist-plugins/local-storage.ts +0 -86
- package/src/persist-plugins/mmkv.ts +0 -91
- package/src/proxy.ts +0 -28
- package/src/react/Computed.tsx +0 -8
- package/src/react/For.tsx +0 -116
- package/src/react/Memo.tsx +0 -4
- package/src/react/Reactive.tsx +0 -53
- package/src/react/Show.tsx +0 -33
- package/src/react/Switch.tsx +0 -43
- package/src/react/react-globals.ts +0 -3
- package/src/react/reactInterfaces.ts +0 -32
- package/src/react/reactive-observer.tsx +0 -210
- package/src/react/useComputed.ts +0 -36
- package/src/react/useEffectOnce.ts +0 -41
- package/src/react/useIsMounted.ts +0 -16
- package/src/react/useMount.ts +0 -15
- package/src/react/useObservable.ts +0 -24
- package/src/react/useObservableReducer.ts +0 -52
- package/src/react/useObservableState.ts +0 -30
- package/src/react/useObserve.ts +0 -54
- package/src/react/useObserveEffect.ts +0 -40
- package/src/react/usePauseProvider.tsx +0 -16
- package/src/react/useSelector.ts +0 -167
- package/src/react/useUnmount.ts +0 -8
- package/src/react/useWhen.ts +0 -9
- package/src/react-hooks/createObservableHook.ts +0 -53
- package/src/react-hooks/useHover.ts +0 -40
- package/src/react-hooks/useMeasure.ts +0 -48
- package/src/react-hooks/useObservableNextRouter.ts +0 -137
- package/src/retry.ts +0 -71
- package/src/setupTracking.ts +0 -26
- package/src/sync/activateSyncedNode.ts +0 -128
- package/src/sync/configureObservableSync.ts +0 -7
- package/src/sync/persistTypes.ts +0 -216
- package/src/sync/syncHelpers.ts +0 -180
- package/src/sync/syncObservable.ts +0 -1056
- package/src/sync/syncObservableAdapter.ts +0 -31
- package/src/sync/syncTypes.ts +0 -189
- package/src/sync/synced.ts +0 -21
- package/src/sync-plugins/crud.ts +0 -412
- package/src/sync-plugins/fetch.ts +0 -80
- package/src/sync-plugins/keel.ts +0 -495
- package/src/sync-plugins/supabase.ts +0 -249
- package/src/sync-plugins/tanstack-query.ts +0 -113
- package/src/sync-plugins/tanstack-react-query.ts +0 -12
- package/src/trace/traceHelpers.ts +0 -11
- package/src/trace/useTraceListeners.ts +0 -34
- package/src/trace/useTraceUpdates.ts +0 -24
- package/src/trace/useVerifyNotTracking.ts +0 -33
- package/src/trace/useVerifyOneRender.ts +0 -10
- package/src/trackSelector.ts +0 -52
- package/src/tracking.ts +0 -43
- package/src/types/babel.d.ts +0 -12
- package/src/when.ts +0 -75
- package/sync-plugins/crud.js.map +0 -1
- package/sync-plugins/crud.mjs.map +0 -1
- package/sync-plugins/fetch.js.map +0 -1
- package/sync-plugins/fetch.mjs.map +0 -1
- package/sync-plugins/keel.js.map +0 -1
- package/sync-plugins/keel.mjs.map +0 -1
- package/sync-plugins/supabase.js.map +0 -1
- package/sync-plugins/supabase.mjs.map +0 -1
- package/sync-plugins/tanstack-query.js.map +0 -1
- package/sync-plugins/tanstack-query.mjs.map +0 -1
- package/sync-plugins/tanstack-react-query.js.map +0 -1
- package/sync-plugins/tanstack-react-query.mjs.map +0 -1
- package/sync.js.map +0 -1
- package/sync.mjs.map +0 -1
- package/trace.js.map +0 -1
- package/trace.mjs.map +0 -1
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type GetOptions,
|
|
3
|
-
configureLegendState,
|
|
4
|
-
internal,
|
|
5
|
-
isObject,
|
|
6
|
-
tracking,
|
|
7
|
-
type NodeValue,
|
|
8
|
-
type TrackingType,
|
|
9
|
-
} from '@legendapp/state';
|
|
10
|
-
import { UseSelectorOptions, useSelector } from '@legendapp/state/react';
|
|
11
|
-
import { createContext, useContext } from 'react';
|
|
12
|
-
// @ts-expect-error Internals
|
|
13
|
-
import { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as ReactInternals } from 'react';
|
|
14
|
-
|
|
15
|
-
interface ReactTrackingOptions {
|
|
16
|
-
auto?: boolean; // Make all get() calls act as useSelector() hooks
|
|
17
|
-
warnUnobserved?: boolean; // Warn if get() is used outside of an observer
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function enableReactTracking({ auto, warnUnobserved }: ReactTrackingOptions) {
|
|
21
|
-
const { get } = internal;
|
|
22
|
-
|
|
23
|
-
if (auto || (process.env.NODE_ENV === 'development' && warnUnobserved)) {
|
|
24
|
-
const ReactRenderContext = createContext(0);
|
|
25
|
-
|
|
26
|
-
const needsSelector = () => {
|
|
27
|
-
// If we're already tracking then we definitely don't need useSelector
|
|
28
|
-
if (!tracking.current) {
|
|
29
|
-
try {
|
|
30
|
-
// If there's no dispatcher we're definitely not in React
|
|
31
|
-
// This is an optimization to not need to run useContext. If in a future React version
|
|
32
|
-
// this works differently we can change it or just remove it.
|
|
33
|
-
const dispatcher = ReactInternals.ReactCurrentDispatcher.current;
|
|
34
|
-
if (dispatcher) {
|
|
35
|
-
// If there's a dispatcher then we may be inside of a hook.
|
|
36
|
-
// Attempt a useContext hook, which will throw an error if outside of render.
|
|
37
|
-
useContext(ReactRenderContext);
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
} catch {} // eslint-disable-line no-empty
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
configureLegendState({
|
|
46
|
-
observableFunctions: {
|
|
47
|
-
get: (node: NodeValue, options?: TrackingType | (GetOptions & UseSelectorOptions)) => {
|
|
48
|
-
if (needsSelector()) {
|
|
49
|
-
if (auto) {
|
|
50
|
-
return useSelector(() => get(node, options), isObject(options) ? options : undefined);
|
|
51
|
-
} else if (process.env.NODE_ENV === 'development' && warnUnobserved) {
|
|
52
|
-
console.warn(
|
|
53
|
-
'[legend-state] Detected a `get()` call in an unobserved component. You may want to wrap it in observer: https://legendapp.com/open-source/state/react-api/#observer-hoc',
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return get(node, options);
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { configureLegendState, internal, NodeValue } from '@legendapp/state';
|
|
2
|
-
import { useSelector, UseSelectorOptions } from '@legendapp/state/react';
|
|
3
|
-
|
|
4
|
-
// TODO: Deprecated, remove in v4
|
|
5
|
-
let didWarn = false;
|
|
6
|
-
|
|
7
|
-
export function enableReactUse() {
|
|
8
|
-
configureLegendState({
|
|
9
|
-
observableFunctions: {
|
|
10
|
-
use: (node: NodeValue, options?: UseSelectorOptions) => {
|
|
11
|
-
if (process.env.NODE_ENV === 'development' && !didWarn) {
|
|
12
|
-
didWarn = true;
|
|
13
|
-
console.warn(
|
|
14
|
-
'[legend-state] enableReactUse() is deprecated. Please switch to using get() with observer, which is safer and more efficient. See https://legendapp.com/open-source/state/v3/react/react-api/',
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
return useSelector(internal.getProxy(node), options);
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Types:
|
|
24
|
-
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
-
import type { ImmutableObservableBase } from '@legendapp/state';
|
|
27
|
-
|
|
28
|
-
declare module '@legendapp/state' {
|
|
29
|
-
interface ImmutableObservableBase<T> {
|
|
30
|
-
use(options?: UseSelectorOptions): T;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { configureLegendState, internal } from '@legendapp/state';
|
|
2
|
-
|
|
3
|
-
export function enable_PeekAssign() {
|
|
4
|
-
configureLegendState({
|
|
5
|
-
observableProperties: {
|
|
6
|
-
_: {
|
|
7
|
-
get(node) {
|
|
8
|
-
return internal.peek(node);
|
|
9
|
-
},
|
|
10
|
-
set(node, value) {
|
|
11
|
-
internal.setNodeValue(node, value);
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// TODOv4 deprecate
|
|
19
|
-
export const enableDirectAccess = enable_PeekAssign;
|
|
20
|
-
|
|
21
|
-
// Types:
|
|
22
|
-
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
24
|
-
import type { ImmutableObservableBase } from '@legendapp/state';
|
|
25
|
-
|
|
26
|
-
declare module '@legendapp/state' {
|
|
27
|
-
interface ImmutableObservableBase<T> {
|
|
28
|
-
get _(): T;
|
|
29
|
-
set _(value: T | null | undefined);
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/config.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { globalState } from './globals';
|
|
2
|
-
import { observableProperties as _observableProperties, observableFns } from './ObservableObject';
|
|
3
|
-
import { ObservablePrimitiveClass } from './ObservablePrimitive';
|
|
4
|
-
import type { NodeValue } from './observableInterfaces';
|
|
5
|
-
|
|
6
|
-
export function configureLegendState({
|
|
7
|
-
observableFunctions,
|
|
8
|
-
observableProperties,
|
|
9
|
-
jsonReplacer,
|
|
10
|
-
jsonReviver,
|
|
11
|
-
}: {
|
|
12
|
-
observableFunctions?: Record<string, (node: NodeValue, ...args: any[]) => any>;
|
|
13
|
-
observableProperties?: Record<string, { get: (node: NodeValue) => any; set: (node: NodeValue, value: any) => any }>;
|
|
14
|
-
jsonReplacer?: (this: any, key: string, value: any) => any;
|
|
15
|
-
jsonReviver?: (this: any, key: string, value: any) => any;
|
|
16
|
-
}) {
|
|
17
|
-
if (observableFunctions) {
|
|
18
|
-
for (const key in observableFunctions) {
|
|
19
|
-
const fn = observableFunctions[key];
|
|
20
|
-
observableFns.set(key, fn);
|
|
21
|
-
ObservablePrimitiveClass.prototype[key] = function (...args: any[]) {
|
|
22
|
-
return fn.call(this, this._node, ...args);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (observableProperties) {
|
|
27
|
-
for (const key in observableProperties) {
|
|
28
|
-
const fns = observableProperties[key];
|
|
29
|
-
_observableProperties.set(key, fns);
|
|
30
|
-
Object.defineProperty(ObservablePrimitiveClass.prototype, key, {
|
|
31
|
-
configurable: true,
|
|
32
|
-
get() {
|
|
33
|
-
return fns.get.call(this, this._node);
|
|
34
|
-
},
|
|
35
|
-
set(value: any) {
|
|
36
|
-
return fns.set.call(this, this._node, value);
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (jsonReplacer) {
|
|
42
|
-
globalState.replacer = jsonReplacer;
|
|
43
|
-
}
|
|
44
|
-
if (jsonReviver) {
|
|
45
|
-
globalState.reviver = jsonReviver;
|
|
46
|
-
}
|
|
47
|
-
}
|
package/src/createObservable.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { isObservable, setNodeValue } from './globals';
|
|
2
|
-
import { isActualPrimitive, isFunction, isPromise } from './is';
|
|
3
|
-
import type { ClassConstructor, ObservableRoot } from './observableInterfaces';
|
|
4
|
-
import { NodeValue } from './observableInterfaces';
|
|
5
|
-
import { Observable, ObservablePrimitive } from './observableTypes';
|
|
6
|
-
|
|
7
|
-
export function createObservable<T>(
|
|
8
|
-
value: T | undefined,
|
|
9
|
-
makePrimitive: boolean,
|
|
10
|
-
extractPromise: Function,
|
|
11
|
-
createObject: Function,
|
|
12
|
-
createPrimitive?: Function,
|
|
13
|
-
): Observable<T> {
|
|
14
|
-
if (isObservable(value)) {
|
|
15
|
-
return value as Observable<T>;
|
|
16
|
-
}
|
|
17
|
-
const valueIsPromise = isPromise<T>(value);
|
|
18
|
-
const valueIsFunction = isFunction(value);
|
|
19
|
-
|
|
20
|
-
const root: ObservableRoot = {
|
|
21
|
-
_: value,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
let node: NodeValue = {
|
|
25
|
-
root,
|
|
26
|
-
lazy: true,
|
|
27
|
-
numListenersRecursive: 0,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
if (valueIsFunction) {
|
|
31
|
-
node = Object.assign(() => {}, node);
|
|
32
|
-
node.lazyFn = value;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const prim = makePrimitive || isActualPrimitive(value);
|
|
36
|
-
|
|
37
|
-
const obs = prim
|
|
38
|
-
? (new (createPrimitive as ClassConstructor<T>)(node) as ObservablePrimitive<T>)
|
|
39
|
-
: (createObject(node) as Observable<T>);
|
|
40
|
-
|
|
41
|
-
if (valueIsPromise) {
|
|
42
|
-
setNodeValue(node, undefined);
|
|
43
|
-
extractPromise(node, value);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return obs as any;
|
|
47
|
-
}
|
package/src/event.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { getNode, symbolGetNode } from './globals';
|
|
2
|
-
import { observable } from './observable';
|
|
3
|
-
import type { ObservableEvent } from './observableInterfaces';
|
|
4
|
-
|
|
5
|
-
export function event(): ObservableEvent {
|
|
6
|
-
// event simply wraps around a number observable
|
|
7
|
-
// which increments its value to dispatch change events
|
|
8
|
-
const obs = observable(0);
|
|
9
|
-
const node = getNode(obs);
|
|
10
|
-
node.isEvent = true;
|
|
11
|
-
return {
|
|
12
|
-
fire: function () {
|
|
13
|
-
// Notify increments the value so that the observable changes
|
|
14
|
-
obs.set((v) => v + 1);
|
|
15
|
-
},
|
|
16
|
-
on: function (cb: () => void) {
|
|
17
|
-
return obs.onChange(cb);
|
|
18
|
-
},
|
|
19
|
-
get: function () {
|
|
20
|
-
// Return the value so that when will be truthy
|
|
21
|
-
return obs.get();
|
|
22
|
-
},
|
|
23
|
-
// @ts-expect-error eslint doesn't like adding symbols to the object but this does work
|
|
24
|
-
[symbolGetNode]: node,
|
|
25
|
-
};
|
|
26
|
-
}
|
package/src/globals.ts
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { isArray, isChildNodeValue, isDate, isFunction, isMap, isNullOrUndefined, isObject } from './is';
|
|
2
|
-
import type { NodeValue, ObservableEvent, TypeAtPath, UpdateFn } from './observableInterfaces';
|
|
3
|
-
import type { Observable, ObservableParam } from './observableTypes';
|
|
4
|
-
|
|
5
|
-
export const symbolToPrimitive = Symbol.toPrimitive;
|
|
6
|
-
export const symbolGetNode = Symbol('getNode');
|
|
7
|
-
export const symbolDelete = /* @__PURE__ */ Symbol('delete');
|
|
8
|
-
export const symbolOpaque = Symbol('opaque');
|
|
9
|
-
export const optimized = Symbol('optimized');
|
|
10
|
-
export const symbolLinked = Symbol('linked');
|
|
11
|
-
|
|
12
|
-
export const globalState = {
|
|
13
|
-
isLoadingLocal: false,
|
|
14
|
-
isMerging: false,
|
|
15
|
-
isLoadingRemote: false,
|
|
16
|
-
activateSyncedNode: undefined as unknown as (node: NodeValue, newValue: any) => { update: UpdateFn; value: any },
|
|
17
|
-
pendingNodes: new Map<NodeValue, () => void>(),
|
|
18
|
-
dirtyNodes: new Set<NodeValue>(),
|
|
19
|
-
replacer: undefined as undefined | ((this: any, key: string, value: any) => any),
|
|
20
|
-
reviver: undefined as undefined | ((this: any, key: string, value: any) => any),
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export function getPathType(value: any): TypeAtPath {
|
|
24
|
-
return isArray(value) ? 'array' : isMap(value) ? 'map' : value instanceof Set ? 'set' : 'object';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function replacer(key: string, value: any) {
|
|
28
|
-
if (isMap(value)) {
|
|
29
|
-
return {
|
|
30
|
-
__LSType: 'Map',
|
|
31
|
-
value: Array.from(value.entries()), // or with spread: value: [...value]
|
|
32
|
-
};
|
|
33
|
-
} else if (value instanceof Set) {
|
|
34
|
-
return {
|
|
35
|
-
__LSType: 'Set',
|
|
36
|
-
value: Array.from(value), // or with spread: value: [...value]
|
|
37
|
-
};
|
|
38
|
-
} else if (globalState.replacer) {
|
|
39
|
-
value = globalState.replacer(key, value);
|
|
40
|
-
}
|
|
41
|
-
return value;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
|
|
45
|
-
function reviver(key: string, value: any) {
|
|
46
|
-
if (value) {
|
|
47
|
-
if (typeof value === 'string' && ISO8601.test(value)) {
|
|
48
|
-
return new Date(value);
|
|
49
|
-
}
|
|
50
|
-
if (typeof value === 'object') {
|
|
51
|
-
if (value.__LSType === 'Map') {
|
|
52
|
-
return new Map(value.value);
|
|
53
|
-
} else if (value.__LSType === 'Set') {
|
|
54
|
-
return new Set(value.value);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (globalState.reviver) {
|
|
58
|
-
value = globalState.reviver(key, value);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return value;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function safeStringify(value: any) {
|
|
65
|
-
return JSON.stringify(value, replacer);
|
|
66
|
-
}
|
|
67
|
-
export function safeParse(value: any) {
|
|
68
|
-
return JSON.parse(value, reviver);
|
|
69
|
-
}
|
|
70
|
-
export function clone<T>(value: T) {
|
|
71
|
-
return safeParse(safeStringify(value));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function isObservable(value$: any): value$ is Observable {
|
|
75
|
-
return !!value$ && !!value$[symbolGetNode as any];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function getNode(value$: ObservableParam): NodeValue {
|
|
79
|
-
return value$ && (value$ as any)[symbolGetNode];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function isEvent(value$: any): value$ is ObservableEvent {
|
|
83
|
-
return value$ && (value$[symbolGetNode as any] as NodeValue)?.isEvent;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function setNodeValue(node: NodeValue, newValue: any) {
|
|
87
|
-
const parentNode = node.parent ?? node;
|
|
88
|
-
const key = node.parent ? node.key : '_';
|
|
89
|
-
|
|
90
|
-
const isDelete = newValue === symbolDelete;
|
|
91
|
-
if (isDelete) newValue = undefined;
|
|
92
|
-
|
|
93
|
-
// Get the value of the parent
|
|
94
|
-
const parentValue = node.parent ? ensureNodeValue(parentNode) : parentNode.root;
|
|
95
|
-
|
|
96
|
-
// Save the previous value first
|
|
97
|
-
const prevValue = parentValue[key];
|
|
98
|
-
|
|
99
|
-
const isFunc = isFunction(newValue);
|
|
100
|
-
|
|
101
|
-
// Compute newValue if newValue is a function or an observable
|
|
102
|
-
newValue = !parentNode.isAssigning && isFunc && !isFunction(prevValue) ? newValue(prevValue) : newValue;
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
!globalState.isMerging ||
|
|
106
|
-
isNullOrUndefined(prevValue) ||
|
|
107
|
-
isFunction(prevValue) ||
|
|
108
|
-
!node.parent?.functions?.get(key)
|
|
109
|
-
) {
|
|
110
|
-
try {
|
|
111
|
-
parentNode.isSetting = (parentNode.isSetting || 0) + 1;
|
|
112
|
-
|
|
113
|
-
const useMapFn = isMap(parentValue);
|
|
114
|
-
// Save the new value
|
|
115
|
-
if (isDelete) {
|
|
116
|
-
if (useMapFn) {
|
|
117
|
-
parentValue.delete(key);
|
|
118
|
-
} else {
|
|
119
|
-
delete parentValue[key];
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
const useMapFn = isMap(parentValue);
|
|
123
|
-
if (useMapFn) {
|
|
124
|
-
parentValue.set(key, newValue);
|
|
125
|
-
} else {
|
|
126
|
-
parentValue[key] = newValue;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
} finally {
|
|
130
|
-
parentNode.isSetting!--;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return { prevValue, newValue };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const arrNodeKeys: string[] = [];
|
|
138
|
-
export function getNodeValue(node: NodeValue): any {
|
|
139
|
-
let count = 0;
|
|
140
|
-
let n: NodeValue = node;
|
|
141
|
-
while (isChildNodeValue(n)) {
|
|
142
|
-
arrNodeKeys[count++] = n.key;
|
|
143
|
-
n = n.parent;
|
|
144
|
-
}
|
|
145
|
-
let child = node.root._;
|
|
146
|
-
for (let i = count - 1; child && i >= 0; i--) {
|
|
147
|
-
const key = arrNodeKeys[i] as any;
|
|
148
|
-
child = key !== 'size' && (isMap(child) || child instanceof WeakMap) ? child.get(key) : child[key];
|
|
149
|
-
}
|
|
150
|
-
return child;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export function getChildNode(node: NodeValue, key: string, asFunction?: Function): NodeValue {
|
|
154
|
-
// Get the child by key
|
|
155
|
-
let child = node.children?.get(key);
|
|
156
|
-
|
|
157
|
-
// Create the child node if it doesn't already exist
|
|
158
|
-
if (!child) {
|
|
159
|
-
child = {
|
|
160
|
-
root: node.root,
|
|
161
|
-
parent: node,
|
|
162
|
-
key,
|
|
163
|
-
lazy: true,
|
|
164
|
-
numListenersRecursive: 0,
|
|
165
|
-
};
|
|
166
|
-
// Lookup functions are bound with the child key
|
|
167
|
-
if (node.lazyFn?.length === 1) {
|
|
168
|
-
asFunction = node.lazyFn.bind(node, key);
|
|
169
|
-
}
|
|
170
|
-
if (isFunction(asFunction)) {
|
|
171
|
-
child = Object.assign(() => {}, child);
|
|
172
|
-
child.lazyFn = asFunction;
|
|
173
|
-
}
|
|
174
|
-
if (!node.children) {
|
|
175
|
-
node.children = new Map();
|
|
176
|
-
}
|
|
177
|
-
node.children.set(key, child);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return child;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function ensureNodeValue(node: NodeValue) {
|
|
184
|
-
let value = getNodeValue(node);
|
|
185
|
-
if (!value || isFunction(value)) {
|
|
186
|
-
if (isChildNodeValue(node)) {
|
|
187
|
-
const parent = ensureNodeValue(node.parent);
|
|
188
|
-
value = parent[node.key] = {};
|
|
189
|
-
} else {
|
|
190
|
-
value = node.root._ = {};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return value;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function findIDKey(obj: unknown | undefined, node: NodeValue): string | ((value: any) => string) | undefined {
|
|
197
|
-
let idKey: string | ((value: any) => string) | undefined = isObservable(obj)
|
|
198
|
-
? undefined
|
|
199
|
-
: isObject(obj)
|
|
200
|
-
? 'id' in obj
|
|
201
|
-
? 'id'
|
|
202
|
-
: 'key' in obj
|
|
203
|
-
? 'key'
|
|
204
|
-
: '_id' in obj
|
|
205
|
-
? '_id'
|
|
206
|
-
: '__id' in obj
|
|
207
|
-
? '__id'
|
|
208
|
-
: undefined
|
|
209
|
-
: undefined;
|
|
210
|
-
|
|
211
|
-
if (!idKey && node.parent) {
|
|
212
|
-
const k = node.key + '_keyExtractor';
|
|
213
|
-
const keyExtractor =
|
|
214
|
-
(node.functions?.get(k) as (value: any) => string) ??
|
|
215
|
-
(getNodeValue(node.parent)[node.key + '_keyExtractor'] as (value: any) => string);
|
|
216
|
-
if (keyExtractor && isFunction(keyExtractor)) {
|
|
217
|
-
idKey = keyExtractor;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return idKey;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function extractFunction(node: NodeValue, key: string, fnOrComputed: Function): void;
|
|
225
|
-
export function extractFunction(node: NodeValue, key: string, fnOrComputed: Observable): void;
|
|
226
|
-
export function extractFunction(node: NodeValue, key: string, fnOrComputed: Function | Observable): void {
|
|
227
|
-
if (!node.functions) {
|
|
228
|
-
node.functions = new Map();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
node.functions.set(key, fnOrComputed);
|
|
232
|
-
}
|
|
233
|
-
export function equals(a: unknown, b: unknown) {
|
|
234
|
-
return a === b || (isDate(a) && isDate(b) && +a === +b);
|
|
235
|
-
}
|
package/src/helpers/pageHash.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { observable, Observable } from '@legendapp/state';
|
|
2
|
-
|
|
3
|
-
interface Options {
|
|
4
|
-
setter: 'pushState' | 'replaceState' | 'hash';
|
|
5
|
-
}
|
|
6
|
-
let _options: Options = { setter: 'hash' };
|
|
7
|
-
|
|
8
|
-
function configurePageHash(options: Options) {
|
|
9
|
-
_options = options;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const hasWindow = typeof window !== 'undefined';
|
|
13
|
-
const pageHash: Observable<string> = observable(hasWindow ? window.location.hash.slice(1) : '');
|
|
14
|
-
|
|
15
|
-
if (hasWindow) {
|
|
16
|
-
let isSetting = false;
|
|
17
|
-
// Set the page hash when the observable changes
|
|
18
|
-
pageHash.onChange(({ value }) => {
|
|
19
|
-
if (!isSetting) {
|
|
20
|
-
const hash = '#' + value;
|
|
21
|
-
const setter = _options?.setter || 'hash';
|
|
22
|
-
if (setter === 'pushState') {
|
|
23
|
-
history.pushState(null, null as any, hash);
|
|
24
|
-
} else if (setter === 'replaceState') {
|
|
25
|
-
history.replaceState(null, null as any, hash);
|
|
26
|
-
} else {
|
|
27
|
-
location.hash = hash;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
// Update the observable whenever the hash changes
|
|
32
|
-
const cb = () => {
|
|
33
|
-
isSetting = true;
|
|
34
|
-
pageHash.set(window.location.hash.slice(1));
|
|
35
|
-
isSetting = false;
|
|
36
|
-
};
|
|
37
|
-
// Subscribe to window hashChange event
|
|
38
|
-
window.addEventListener('hashchange', cb);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { configurePageHash, pageHash };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { observable, Observable } from '@legendapp/state';
|
|
2
|
-
|
|
3
|
-
interface Options {
|
|
4
|
-
setter: 'pushState' | 'replaceState' | 'hash';
|
|
5
|
-
}
|
|
6
|
-
let _options: Options = { setter: 'hash' };
|
|
7
|
-
|
|
8
|
-
function configurePageHashParams(options: Options) {
|
|
9
|
-
_options = options;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function toParams(str: string) {
|
|
13
|
-
const ret: Record<string, string> = {};
|
|
14
|
-
const searchParams = new URLSearchParams(str);
|
|
15
|
-
for (const [key, value] of searchParams) {
|
|
16
|
-
ret[key] = value;
|
|
17
|
-
}
|
|
18
|
-
return ret;
|
|
19
|
-
}
|
|
20
|
-
function toString(params: Record<string, string>) {
|
|
21
|
-
return new URLSearchParams(params).toString().replace(/=$/, '');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const hasWindow = typeof window !== 'undefined';
|
|
25
|
-
const pageHashParams: Observable<Record<string, string>> = observable(
|
|
26
|
-
hasWindow ? toParams(window.location.hash.slice(1)) : {},
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
if (hasWindow) {
|
|
30
|
-
let isSetting = false;
|
|
31
|
-
// Set the page hash when the observable changes
|
|
32
|
-
pageHashParams.onChange(({ value }) => {
|
|
33
|
-
if (!isSetting) {
|
|
34
|
-
const hash = '#' + toString(value);
|
|
35
|
-
const setter = _options?.setter || 'hash';
|
|
36
|
-
if (setter === 'pushState') {
|
|
37
|
-
history.pushState(null, null as any, hash);
|
|
38
|
-
} else if (setter === 'replaceState') {
|
|
39
|
-
history.replaceState(null, null as any, hash);
|
|
40
|
-
} else {
|
|
41
|
-
location.hash = hash;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
// Update the observable whenever the hash changes
|
|
46
|
-
const cb = () => {
|
|
47
|
-
isSetting = true;
|
|
48
|
-
pageHashParams.set(toParams(window.location.hash.slice(1)));
|
|
49
|
-
isSetting = false;
|
|
50
|
-
};
|
|
51
|
-
// Subscribe to window hashChange event
|
|
52
|
-
window.addEventListener('hashchange', cb);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export { configurePageHashParams, pageHashParams };
|
package/src/helpers/time.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { observable } from '@legendapp/state';
|
|
2
|
-
|
|
3
|
-
const MSPerMinute = 60000;
|
|
4
|
-
|
|
5
|
-
function clearTime(date: Date | number) {
|
|
6
|
-
date = new Date(date);
|
|
7
|
-
date.setHours(0, 0, 0, 0);
|
|
8
|
-
return date;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let time = new Date();
|
|
12
|
-
const currentTime = observable(time);
|
|
13
|
-
const currentDay = observable(clearTime(time));
|
|
14
|
-
const timeToSecond = (60 - time.getSeconds() + 1) * 1000;
|
|
15
|
-
function update() {
|
|
16
|
-
const now = new Date();
|
|
17
|
-
currentTime.set(now);
|
|
18
|
-
|
|
19
|
-
if (now.getDate() !== time.getDate()) {
|
|
20
|
-
currentDay.set(clearTime(now));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
time = now;
|
|
24
|
-
}
|
|
25
|
-
setTimeout(() => {
|
|
26
|
-
update();
|
|
27
|
-
setInterval(update, MSPerMinute);
|
|
28
|
-
}, timeToSecond);
|
|
29
|
-
|
|
30
|
-
export { currentTime, currentDay };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { ObservableParam, constructObjectWithPath, mergeIntoObservable, observable } from '@legendapp/state';
|
|
2
|
-
|
|
3
|
-
// This type is purely for documentation.
|
|
4
|
-
type TimestampAsString = string;
|
|
5
|
-
|
|
6
|
-
export function trackHistory<T>(
|
|
7
|
-
value$: ObservableParam<T>,
|
|
8
|
-
targetObservable?: ObservableParam<Record<TimestampAsString, Partial<T>>>,
|
|
9
|
-
): ObservableParam<Record<TimestampAsString, any>> {
|
|
10
|
-
const history = targetObservable ?? observable<Record<TimestampAsString, Partial<T>>>();
|
|
11
|
-
|
|
12
|
-
value$.onChange(({ loading, remote, changes }) => {
|
|
13
|
-
// Don't save history if this is a remote change.
|
|
14
|
-
// History will be saved remotely by the client making the local change.
|
|
15
|
-
if (!loading && !remote) {
|
|
16
|
-
const time: TimestampAsString = Date.now().toString();
|
|
17
|
-
|
|
18
|
-
// Save to history observable by date, with the previous value
|
|
19
|
-
for (let i = 0; i < changes.length; i++) {
|
|
20
|
-
const { path, prevAtPath, pathTypes } = changes[i];
|
|
21
|
-
|
|
22
|
-
const obj = constructObjectWithPath(path, pathTypes, prevAtPath);
|
|
23
|
-
mergeIntoObservable((history as any)[time], obj);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
return history as any;
|
|
29
|
-
}
|