valdres 0.2.0-alpha.8 → 0.2.0-pre.1
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 +1096 -350
- package/dist/types/src/atom.d.ts +16 -0
- package/dist/types/src/atomFamily.d.ts +3 -0
- package/dist/types/src/errors/SelectorCircularDependencyError.d.ts +5 -0
- package/dist/types/src/errors/SelectorEvaluationError.d.ts +7 -0
- package/dist/types/src/errors/lib/generateSelectorTrace.d.ts +2 -0
- package/dist/types/src/globalStore.d.ts +4 -0
- package/dist/types/src/index.d.ts +36 -0
- package/dist/types/src/indexConstructor.d.ts +5 -0
- package/dist/types/src/lib/atomFamilyAtom.d.ts +8 -0
- package/dist/types/src/lib/createAtomFamily.d.ts +4 -0
- package/dist/types/src/lib/createGlobalAtomFamily.d.ts +4 -0
- package/dist/types/src/lib/createStoreData.d.ts +3 -0
- package/dist/types/src/lib/deleteFamilyAtom.d.ts +3 -0
- package/dist/types/src/lib/equal.d.ts +1 -0
- package/dist/types/src/lib/getState.d.ts +8 -0
- package/dist/types/src/lib/globalAtom.d.ts +4 -0
- package/dist/types/src/lib/initAtom.d.ts +5 -0
- package/dist/types/src/lib/initSelector.d.ts +10 -0
- package/dist/types/src/lib/isFunction.d.ts +1 -0
- package/dist/types/src/lib/isProd.d.ts +1 -0
- package/dist/types/src/lib/propagateUpdatedAtoms.d.ts +10 -0
- package/dist/types/src/lib/setAtom.d.ts +3 -0
- package/dist/{src → types/src}/lib/setAtoms.d.ts +1 -1
- package/dist/types/src/lib/setValueInData.d.ts +4 -0
- package/dist/types/src/lib/storeFromStoreData.d.ts +4 -0
- package/dist/types/src/lib/stringifyFamilyArgs.d.ts +1 -0
- package/dist/{src → types/src}/lib/subscribe.d.ts +1 -1
- package/dist/types/src/lib/transaction.d.ts +8 -0
- package/dist/{src → types/src}/lib/unsubscribe.d.ts +1 -1
- package/dist/types/src/selector.d.ts +4 -0
- package/dist/types/src/selectorFamily.d.ts +4 -0
- package/dist/types/src/store.d.ts +1 -0
- package/dist/types/src/types/Atom.d.ts +14 -0
- package/dist/types/src/types/AtomDefaultValue.d.ts +2 -0
- package/dist/types/src/types/AtomFamily.d.ts +9 -0
- package/dist/types/src/types/AtomFamilyAtom.d.ts +7 -0
- package/dist/types/src/types/AtomFamilyDefaultValue.d.ts +5 -0
- package/dist/types/src/types/AtomFamilyGlobalAtom.d.ts +3 -0
- package/dist/types/src/types/AtomFamilySelector.d.ts +6 -0
- package/dist/types/src/types/AtomOnInit.d.ts +2 -0
- package/dist/types/src/types/AtomOnSet.d.ts +2 -0
- package/dist/types/src/types/AtomOptions.d.ts +13 -0
- package/dist/types/src/types/EqualFunc.d.ts +3 -0
- package/dist/types/src/types/Family.d.ts +3 -0
- package/dist/types/src/types/FamilyKey.d.ts +3 -0
- package/dist/types/src/types/GetValue.d.ts +9 -0
- package/dist/types/src/types/GlobalAtom.d.ts +11 -0
- package/dist/types/src/types/GlobalAtomGetSelfFunc.d.ts +1 -0
- package/dist/types/src/types/GlobalAtomResetSelfFunc.d.ts +1 -0
- package/dist/types/src/types/GlobalAtomSetSelfFunc.d.ts +1 -0
- package/dist/types/src/types/Selector.d.ts +11 -0
- package/dist/types/src/types/SelectorFamily.d.ts +5 -0
- package/dist/types/src/types/SelectorOptions.d.ts +5 -0
- package/dist/{src → types/src}/types/SetAtom.d.ts +3 -1
- package/dist/types/src/types/SetAtomValue.d.ts +1 -0
- package/dist/types/src/types/State.d.ts +4 -0
- package/dist/types/src/types/Store.d.ts +26 -0
- package/dist/types/src/types/StoreData.d.ts +18 -0
- package/dist/types/src/types/SubscribeFn.d.ts +9 -0
- package/dist/types/src/types/Subscription.d.ts +11 -0
- package/dist/types/src/types/TransactionFn.d.ts +2 -0
- package/dist/types/src/types/TransactionInterface.d.ts +19 -0
- package/dist/types/src/utils/deepFreeze.d.ts +1 -0
- package/dist/types/src/utils/isAtom.d.ts +2 -0
- package/dist/types/src/utils/isAtomFamily.d.ts +2 -0
- package/dist/types/src/utils/isFamily.d.ts +1 -0
- package/dist/types/src/utils/isFamilyAtom.d.ts +2 -0
- package/dist/types/src/utils/isFamilySelector.d.ts +2 -0
- package/dist/types/src/utils/isFamilyState.d.ts +3 -0
- package/dist/types/src/utils/isSelector.d.ts +2 -0
- package/dist/types/src/utils/isSelectorFamily.d.ts +2 -0
- package/package.json +7 -22
- package/dist/index.d.ts +0 -21
- package/dist/src/atom.d.ts +0 -8
- package/dist/src/atomFamily.d.ts +0 -4
- package/dist/src/createStore.d.ts +0 -2
- package/dist/src/getDefaultStore.d.ts +0 -2
- package/dist/src/lib/createStoreData.d.ts +0 -2
- package/dist/src/lib/getState.d.ts +0 -7
- package/dist/src/lib/initAtom.d.ts +0 -4
- package/dist/src/lib/initSelector.d.ts +0 -4
- package/dist/src/lib/propagateUpdatedAtoms.d.ts +0 -3
- package/dist/src/lib/setAtom.d.ts +0 -3
- package/dist/src/lib/storeFromStoreData.d.ts +0 -3
- package/dist/src/lib/transaction.d.ts +0 -9
- package/dist/src/lib/updateSelectorSubscribers.d.ts +0 -3
- package/dist/src/lib/updateStateSubscribers.d.ts +0 -3
- package/dist/src/selector.d.ts +0 -3
- package/dist/src/selectorFamily.d.ts +0 -2
- package/dist/src/types/Atom.d.ts +0 -9
- package/dist/src/types/AtomFamily.d.ts +0 -5
- package/dist/src/types/Family.d.ts +0 -3
- package/dist/src/types/GetValue.d.ts +0 -8
- package/dist/src/types/Selector.d.ts +0 -9
- package/dist/src/types/SelectorFamily.d.ts +0 -5
- package/dist/src/types/SetAtomValue.d.ts +0 -1
- package/dist/src/types/State.d.ts +0 -3
- package/dist/src/types/Store.d.ts +0 -14
- package/dist/src/types/StoreData.d.ts +0 -9
- package/dist/src/types/SubscribeFn.d.ts +0 -2
- package/dist/src/types/Subscription.d.ts +0 -1
- package/dist/src/types/TransactionFn.d.ts +0 -4
- package/dist/src/utils/isAtom.d.ts +0 -2
- package/dist/src/utils/isFamily.d.ts +0 -1
- package/dist/src/utils/isSelector.d.ts +0 -2
- /package/dist/{src → types/src}/createStoreWithSelectorSet.d.ts +0 -0
- /package/dist/{src → types/src}/lib/resetAtom.d.ts +0 -0
- /package/dist/{src → types/src}/lib/stableStringify.d.ts +0 -0
- /package/dist/{src → types/src}/types/ResetAtom.d.ts +0 -0
- /package/dist/{src → types/src}/utils/isPromiseLike.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,132 +1,308 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { version } from "../package.json";
|
|
3
|
+
|
|
4
|
+
// src/lib/equal.ts
|
|
5
|
+
var hasElementType = typeof Element !== "undefined";
|
|
6
|
+
var hasMap = typeof Map === "function";
|
|
7
|
+
var hasSet = typeof Set === "function";
|
|
8
|
+
var hasArrayBuffer = typeof ArrayBuffer === "function" && !!ArrayBuffer.isView;
|
|
9
|
+
var deepEqualFn = (a, b, updatedAtomsSet) => {
|
|
10
|
+
if (updatedAtomsSet) {
|
|
11
|
+
if (updatedAtomsSet.has(a) || updatedAtomsSet.has(b))
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (a === b)
|
|
15
|
+
return true;
|
|
16
|
+
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
17
|
+
if (a.constructor !== b.constructor)
|
|
18
|
+
return false;
|
|
19
|
+
var length, i, keys;
|
|
20
|
+
if (Array.isArray(a)) {
|
|
21
|
+
length = a.length;
|
|
22
|
+
if (length != b.length)
|
|
23
|
+
return false;
|
|
24
|
+
for (i = length;i-- !== 0; )
|
|
25
|
+
if (!deepEqualFn(a[i], b[i], updatedAtomsSet))
|
|
26
|
+
return false;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
var it;
|
|
30
|
+
if (hasMap && a instanceof Map && b instanceof Map) {
|
|
31
|
+
if (a.size !== b.size)
|
|
32
|
+
return false;
|
|
33
|
+
it = a.entries();
|
|
34
|
+
while (!(i = it.next()).done)
|
|
35
|
+
if (!b.has(i.value[0]))
|
|
36
|
+
return false;
|
|
37
|
+
it = a.entries();
|
|
38
|
+
while (!(i = it.next()).done)
|
|
39
|
+
if (!deepEqualFn(i.value[1], b.get(i.value[0]), updatedAtomsSet))
|
|
40
|
+
return false;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (hasSet && a instanceof Set && b instanceof Set) {
|
|
44
|
+
if (a.size !== b.size)
|
|
45
|
+
return false;
|
|
46
|
+
it = a.entries();
|
|
47
|
+
while (!(i = it.next()).done) {
|
|
48
|
+
if (!b.has(i.value[0]))
|
|
49
|
+
return false;
|
|
50
|
+
if (updatedAtomsSet?.has(i.value[0]))
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (hasArrayBuffer && ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
56
|
+
length = a.length;
|
|
57
|
+
if (length != b.length)
|
|
58
|
+
return false;
|
|
59
|
+
for (i = length;i-- !== 0; )
|
|
60
|
+
if (a[i] !== b[i])
|
|
61
|
+
return false;
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (a.constructor === RegExp)
|
|
65
|
+
return a.source === b.source && a.flags === b.flags;
|
|
66
|
+
if (a.valueOf !== Object.prototype.valueOf && typeof a.valueOf === "function" && typeof b.valueOf === "function")
|
|
67
|
+
return a.valueOf() === b.valueOf();
|
|
68
|
+
if (a.toString !== Object.prototype.toString && typeof a.toString === "function" && typeof b.toString === "function")
|
|
69
|
+
return a.toString() === b.toString();
|
|
70
|
+
keys = Object.keys(a);
|
|
71
|
+
length = keys.length;
|
|
72
|
+
if (length !== Object.keys(b).length)
|
|
73
|
+
return false;
|
|
74
|
+
for (i = length;i-- !== 0; )
|
|
75
|
+
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
|
|
76
|
+
return false;
|
|
77
|
+
if (hasElementType && a instanceof Element)
|
|
78
|
+
return false;
|
|
79
|
+
for (i = length;i-- !== 0; ) {
|
|
80
|
+
if ((keys[i] === "_owner" || keys[i] === "__v" || keys[i] === "__o") && a.$$typeof) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (!deepEqualFn(a[keys[i]], b[keys[i]], updatedAtomsSet))
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return a !== a && b !== b;
|
|
89
|
+
};
|
|
90
|
+
var equal = (a, b, updatedAtomsSet) => {
|
|
91
|
+
try {
|
|
92
|
+
return deepEqualFn(a, b, updatedAtomsSet);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if ((error.message || "").match(/stack|recursion/i)) {
|
|
95
|
+
console.warn("react-fast-compare cannot handle circular refs");
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
9
100
|
};
|
|
101
|
+
|
|
102
|
+
// src/utils/isAtom.ts
|
|
103
|
+
var isAtom = (state) => Object.hasOwn(state, "defaultValue");
|
|
104
|
+
|
|
105
|
+
// src/utils/isFamilyState.ts
|
|
106
|
+
var isFamilyState = (state) => state && Object.hasOwn(state, "family");
|
|
107
|
+
|
|
108
|
+
// src/utils/isFamilyAtom.ts
|
|
109
|
+
var isFamilyAtom = (state) => isFamilyState(state) && isAtom(state);
|
|
110
|
+
|
|
10
111
|
// src/utils/isPromiseLike.ts
|
|
11
112
|
var isPromiseLike = (object) => {
|
|
12
113
|
return object && object.then && typeof object.then === "function";
|
|
13
114
|
};
|
|
14
115
|
|
|
15
|
-
// src/lib/
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
116
|
+
// src/errors/lib/generateSelectorTrace.ts
|
|
117
|
+
var generateSelectorTrace = (selectors) => {
|
|
118
|
+
const lastIndex = selectors.length - 1;
|
|
119
|
+
return [...selectors].reverse().map((selector, index) => {
|
|
120
|
+
const name = selector.name ?? "Anonymous Selector";
|
|
121
|
+
if (index === 0) {
|
|
122
|
+
return `[START] ${name}`;
|
|
123
|
+
} else if (index === lastIndex) {
|
|
124
|
+
return `[CRASH] ${name}`;
|
|
125
|
+
} else {
|
|
126
|
+
return ` ${" ".repeat(index)}${name}`;
|
|
127
|
+
}
|
|
128
|
+
}).join(`
|
|
129
|
+
`);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// src/errors/SelectorEvaluationError.ts
|
|
133
|
+
class SelectorEvaluationError extends Error {
|
|
134
|
+
selectors;
|
|
135
|
+
constructor(cause) {
|
|
136
|
+
super();
|
|
137
|
+
this.cause = cause;
|
|
138
|
+
this.selectors = [];
|
|
32
139
|
}
|
|
33
|
-
|
|
34
|
-
|
|
140
|
+
track(selector) {
|
|
141
|
+
this.selectors.push(selector);
|
|
35
142
|
}
|
|
36
|
-
|
|
37
|
-
|
|
143
|
+
get message() {
|
|
144
|
+
const firstSelectorName = this.selectors[0].name ?? "Anonymous Selector";
|
|
145
|
+
return `Selector eval crashed in '${firstSelectorName}'
|
|
146
|
+
${generateSelectorTrace(this.selectors)}`;
|
|
38
147
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/utils/isAtomFamily.ts
|
|
151
|
+
var isAtomFamily = (state) => state && Object.hasOwn(state, "__valdresAtomFamilyMap");
|
|
152
|
+
|
|
153
|
+
// src/utils/isSelector.ts
|
|
154
|
+
var isSelector = (state) => state && Object.hasOwn(state, "get");
|
|
155
|
+
|
|
156
|
+
// src/utils/isSelectorFamily.ts
|
|
157
|
+
var isSelectorFamily = (state) => state && Object.hasOwn(state, "__valdresSelectorFamilyMap");
|
|
158
|
+
|
|
159
|
+
// src/lib/isFunction.ts
|
|
160
|
+
var isFunction = (value) => typeof value === "function";
|
|
161
|
+
|
|
162
|
+
// src/utils/deepFreeze.ts
|
|
163
|
+
var deepFreeze = (obj, seen = new WeakSet) => {
|
|
164
|
+
if (obj === null || obj === undefined || seen.has(obj))
|
|
165
|
+
return obj;
|
|
166
|
+
if (obj && typeof obj === "object")
|
|
167
|
+
seen.add(obj);
|
|
168
|
+
if (Array.isArray(obj)) {
|
|
169
|
+
for (const item of obj) {
|
|
170
|
+
if (item && typeof item === "object") {
|
|
171
|
+
deepFreeze(item, seen);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
176
|
+
for (const name of propNames) {
|
|
177
|
+
const value = obj[name];
|
|
178
|
+
if (value && typeof value === "object") {
|
|
179
|
+
deepFreeze(value, seen);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
44
182
|
}
|
|
45
|
-
|
|
46
|
-
|
|
183
|
+
return Object.freeze(obj);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/lib/isProd.ts
|
|
187
|
+
var isProd = () => {
|
|
188
|
+
return false;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// src/lib/setValueInData.ts
|
|
192
|
+
var setValueInData = (atom, value, data) => {
|
|
193
|
+
if (isProd()) {
|
|
194
|
+
data.values.set(atom, value);
|
|
195
|
+
return value;
|
|
196
|
+
} else {
|
|
197
|
+
const frozenValue = deepFreeze(value);
|
|
198
|
+
data.values.set(atom, frozenValue);
|
|
199
|
+
return frozenValue;
|
|
47
200
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/lib/setAtom.ts
|
|
204
|
+
var setAtom = (atom, newValue, data, skipOnSet = false) => {
|
|
205
|
+
const initializedAtomsSet = new Set;
|
|
206
|
+
const currentValue = getState(atom, data, initializedAtomsSet);
|
|
207
|
+
if (isFunction(newValue)) {
|
|
208
|
+
newValue = newValue(currentValue);
|
|
209
|
+
if (isPromiseLike(newValue) || isPromiseLike(currentValue))
|
|
210
|
+
throw new Error("Todo, how should we handle this?");
|
|
54
211
|
}
|
|
55
|
-
if (
|
|
56
|
-
return
|
|
212
|
+
if (atom.equal(currentValue, newValue))
|
|
213
|
+
return newValue;
|
|
214
|
+
newValue = setValueInData(atom, newValue, data);
|
|
215
|
+
if (atom.onSet && !skipOnSet)
|
|
216
|
+
atom.onSet(newValue, data);
|
|
217
|
+
if (currentValue?.__isEmptyAtomPromise__) {
|
|
218
|
+
currentValue.__resolveEmptyAtomPromise__(newValue);
|
|
57
219
|
}
|
|
58
|
-
if (
|
|
59
|
-
|
|
220
|
+
if (initializedAtomsSet.size > 0) {
|
|
221
|
+
const all = new Set([...initializedAtomsSet, atom]);
|
|
222
|
+
propagateUpdatedAtoms([...all], data);
|
|
223
|
+
} else {
|
|
224
|
+
propagateUpdatedAtoms([atom], data);
|
|
60
225
|
}
|
|
61
|
-
return
|
|
62
|
-
};
|
|
63
|
-
var stableStringify = (x) => {
|
|
64
|
-
if (typeof x === "string" || typeof x === "boolean" || typeof x === "number")
|
|
65
|
-
return x;
|
|
66
|
-
return stableStringifyRecurse(x);
|
|
226
|
+
return newValue;
|
|
67
227
|
};
|
|
68
228
|
|
|
69
|
-
// src/
|
|
70
|
-
var
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
return map.get(keyStringified);
|
|
76
|
-
}
|
|
77
|
-
const atomDebugLabel = debugLabel && debugLabel + "_" + keyStringified;
|
|
78
|
-
const newAtom = atom(typeof defaultValue === "function" ? () => defaultValue(key) : defaultValue, {
|
|
79
|
-
label: atomDebugLabel
|
|
229
|
+
// src/lib/initAtom.ts
|
|
230
|
+
var getAtomInitValue = (atom, data, initializedAtomsSet) => {
|
|
231
|
+
if (atom.defaultValue === undefined) {
|
|
232
|
+
let promiseResolve;
|
|
233
|
+
const promise = new Promise((resolve) => {
|
|
234
|
+
promiseResolve = resolve;
|
|
80
235
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
236
|
+
promise.__isEmptyAtomPromise__ = true;
|
|
237
|
+
promise.__resolveEmptyAtomPromise__ = promiseResolve;
|
|
238
|
+
return promise;
|
|
239
|
+
} else if (typeof atom.defaultValue === "function") {
|
|
240
|
+
const value = atom.defaultValue();
|
|
241
|
+
if (isPromiseLike(value)) {
|
|
242
|
+
value.then((resolvedValue) => {
|
|
243
|
+
setValueInData(atom, resolvedValue, data);
|
|
244
|
+
propagateUpdatedAtoms([atom], data);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return value;
|
|
248
|
+
} else if (isSelector(atom.defaultValue)) {
|
|
249
|
+
return getState(atom.defaultValue, data, initializedAtomsSet);
|
|
250
|
+
} else {
|
|
251
|
+
return atom.defaultValue;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
var initAtom = (atom, data, initializedAtomsSet) => {
|
|
255
|
+
const tmpVal = getAtomInitValue(atom, data, initializedAtomsSet);
|
|
256
|
+
let value = setValueInData(atom, tmpVal, data);
|
|
257
|
+
if (atom.onInit)
|
|
258
|
+
atom.onInit((newVal) => {
|
|
259
|
+
value = newVal;
|
|
260
|
+
setAtom(atom, newVal, data, true);
|
|
261
|
+
}, data);
|
|
88
262
|
};
|
|
89
|
-
// src/lib/createStoreData.ts
|
|
90
|
-
var generateId = () => (Math.random() + 1).toString(36).substring(7);
|
|
91
|
-
var createStoreData = (id = generateId()) => ({
|
|
92
|
-
id,
|
|
93
|
-
values: new WeakMap,
|
|
94
|
-
expiredValues: new WeakMap,
|
|
95
|
-
subscriptions: new WeakMap,
|
|
96
|
-
subscriptionsRequireEqualCheck: new WeakMap,
|
|
97
|
-
stateConsumers: new WeakMap,
|
|
98
|
-
stateDependencies: new WeakMap
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// src/utils/isAtom.ts
|
|
102
|
-
var isAtom = (state) => Object.hasOwn(state, "defaultValue");
|
|
103
263
|
|
|
104
264
|
// src/lib/getState.ts
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
265
|
+
function getState(state, data, initializedAtomsSet, circularDependencySet) {
|
|
266
|
+
if (data.values.has(state))
|
|
267
|
+
return data.values.get(state);
|
|
268
|
+
if (isAtom(state)) {
|
|
269
|
+
if ("parent" in data)
|
|
270
|
+
return getState(state, data.parent, initializedAtomsSet, circularDependencySet);
|
|
271
|
+
initAtom(state, data, initializedAtomsSet);
|
|
272
|
+
initializedAtomsSet.add(state);
|
|
273
|
+
return data.values.get(state);
|
|
114
274
|
}
|
|
115
|
-
if (state
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
275
|
+
if (isSelector(state)) {
|
|
276
|
+
initSelector(state, data, initializedAtomsSet, circularDependencySet);
|
|
277
|
+
return data.values.get(state);
|
|
278
|
+
}
|
|
279
|
+
if (isAtomFamily(state)) {
|
|
280
|
+
if ("parent" in data) {
|
|
281
|
+
const closestData = findClosestStoreWithAtomInitialized(state, data);
|
|
282
|
+
return getState(state, closestData, initializedAtomsSet, circularDependencySet);
|
|
121
283
|
}
|
|
284
|
+
data.values.set(state, []);
|
|
285
|
+
initializedAtomsSet.add(state);
|
|
286
|
+
return data.values.get(state);
|
|
122
287
|
}
|
|
288
|
+
if (isSelectorFamily(state)) {
|
|
289
|
+
const array = Array.from(state.__valdresSelectorFamilyMap.keys());
|
|
290
|
+
if (equal(array, state._keyArray))
|
|
291
|
+
return state._keyArray;
|
|
292
|
+
state._keyArray = array;
|
|
293
|
+
return array;
|
|
294
|
+
}
|
|
295
|
+
throw new Error("Invalid object passed to get");
|
|
296
|
+
}
|
|
297
|
+
var findClosestStoreWithAtomInitialized = (atom, data) => {
|
|
298
|
+
if ("parent" in data === false)
|
|
299
|
+
return data;
|
|
300
|
+
if (data.values.has(atom))
|
|
301
|
+
return data;
|
|
302
|
+
return findClosestStoreWithAtomInitialized(atom, data.parent);
|
|
123
303
|
};
|
|
124
304
|
|
|
125
|
-
// src/lib/updateSelectorSubscribers.ts
|
|
126
|
-
import equal2 from "fast-deep-equal";
|
|
127
|
-
|
|
128
305
|
// src/lib/initSelector.ts
|
|
129
|
-
import equal from "fast-deep-equal";
|
|
130
306
|
class SuspendAndWaitForResolveError extends Error {
|
|
131
307
|
promise;
|
|
132
308
|
constructor(promise) {
|
|
@@ -134,41 +310,45 @@ class SuspendAndWaitForResolveError extends Error {
|
|
|
134
310
|
this.promise = promise;
|
|
135
311
|
}
|
|
136
312
|
}
|
|
137
|
-
var
|
|
138
|
-
const set = data.
|
|
313
|
+
var getOrInitDependentsSet = (state, data) => {
|
|
314
|
+
const set = data.stateDependents.get(state);
|
|
139
315
|
if (set)
|
|
140
316
|
return set;
|
|
141
317
|
const newSet = new Set;
|
|
142
|
-
data.
|
|
318
|
+
data.stateDependents.set(state, newSet);
|
|
143
319
|
return newSet;
|
|
144
320
|
};
|
|
145
|
-
var evaluateSelector = (selector, data) => {
|
|
146
|
-
const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
|
|
321
|
+
var evaluateSelector = (selector, data, initializedAtomsSet, circularDependencySet = new WeakSet) => {
|
|
147
322
|
const updatedDependencies = new Set;
|
|
323
|
+
if (circularDependencySet.has(selector)) {}
|
|
324
|
+
circularDependencySet.add(selector);
|
|
148
325
|
let result;
|
|
149
326
|
try {
|
|
150
327
|
result = selector.get((state) => {
|
|
151
|
-
const value = getState(state, data);
|
|
328
|
+
const value = getState(state, data, initializedAtomsSet, circularDependencySet);
|
|
152
329
|
updatedDependencies.add(state);
|
|
153
330
|
if (isPromiseLike(value))
|
|
154
331
|
throw new SuspendAndWaitForResolveError(value);
|
|
155
332
|
return value;
|
|
156
|
-
});
|
|
333
|
+
}, data.id);
|
|
157
334
|
} catch (error) {
|
|
158
335
|
if (error instanceof SuspendAndWaitForResolveError) {
|
|
159
336
|
result = error;
|
|
160
|
-
} else {
|
|
337
|
+
} else if (error instanceof SelectorEvaluationError) {
|
|
161
338
|
throw error;
|
|
339
|
+
} else {
|
|
340
|
+
throw new SelectorEvaluationError(error);
|
|
162
341
|
}
|
|
163
342
|
}
|
|
343
|
+
const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
|
|
164
344
|
const added = updatedDependencies?.difference(currentDependencies);
|
|
165
345
|
const removed = currentDependencies?.difference(updatedDependencies);
|
|
166
346
|
for (const state of added) {
|
|
167
|
-
const set =
|
|
347
|
+
const set = getOrInitDependentsSet(state, data);
|
|
168
348
|
set.add(selector);
|
|
169
349
|
}
|
|
170
350
|
for (const state of removed) {
|
|
171
|
-
const set =
|
|
351
|
+
const set = getOrInitDependentsSet(state, data);
|
|
172
352
|
set.delete(selector);
|
|
173
353
|
}
|
|
174
354
|
data.stateDependencies.set(selector, updatedDependencies);
|
|
@@ -176,183 +356,259 @@ var evaluateSelector = (selector, data) => {
|
|
|
176
356
|
};
|
|
177
357
|
var handleSelectorResult = (value, selector, data) => {
|
|
178
358
|
if (value instanceof SuspendAndWaitForResolveError) {
|
|
179
|
-
value.promise.then(() =>
|
|
359
|
+
value.promise.then(() => {
|
|
360
|
+
const initializedAtomsSet = new Set;
|
|
361
|
+
const res = initSelector(selector, data, initializedAtomsSet);
|
|
362
|
+
if (initializedAtomsSet.size > 0) {
|
|
363
|
+
propagateUpdatedAtoms([...initializedAtomsSet], data);
|
|
364
|
+
}
|
|
365
|
+
return res;
|
|
366
|
+
});
|
|
180
367
|
return value.promise;
|
|
181
368
|
} else if (isPromiseLike(value)) {
|
|
182
369
|
value.then((resolved) => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
370
|
+
setValueInData(selector, resolved, data);
|
|
371
|
+
const dependents = data.stateDependents.get(selector);
|
|
372
|
+
const subs = data.subscriptions.get(selector);
|
|
373
|
+
if (subs && subs.size > 0 || dependents && dependents.size > 0) {
|
|
374
|
+
propagateDirtySelectors([], new Set(dependents), data, new Set(subs), new Map);
|
|
375
|
+
}
|
|
186
376
|
});
|
|
187
377
|
return value;
|
|
188
378
|
} else {
|
|
189
379
|
return value;
|
|
190
380
|
}
|
|
191
381
|
};
|
|
192
|
-
var initSelector = (selector, data) => {
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
382
|
+
var initSelector = (selector, data, initializedAtomsSet, circularDependencySet = new WeakSet) => {
|
|
383
|
+
const existingValue = data.values.get(selector);
|
|
384
|
+
const udpatedValue = evaluate(selector, data, initializedAtomsSet, circularDependencySet);
|
|
385
|
+
if (selector.equal(existingValue, udpatedValue)) {
|
|
386
|
+
return false;
|
|
387
|
+
} else {
|
|
388
|
+
setValueInData(selector, udpatedValue, data);
|
|
389
|
+
return true;
|
|
201
390
|
}
|
|
202
|
-
data.values.set(selector, value);
|
|
203
|
-
return value;
|
|
204
391
|
};
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
const oldValue = data.expiredValues.get(selector);
|
|
215
|
-
const newValue = initSelector(selector, data);
|
|
216
|
-
if (equal2(newValue, oldValue))
|
|
217
|
-
return;
|
|
218
|
-
} catch (e) {
|
|
219
|
-
}
|
|
392
|
+
var evaluate = (selector, data, initializedAtomsSet, circularDependencySet) => {
|
|
393
|
+
let tmpValue;
|
|
394
|
+
try {
|
|
395
|
+
tmpValue = evaluateSelector(selector, data, initializedAtomsSet, circularDependencySet);
|
|
396
|
+
} catch (e) {
|
|
397
|
+
if (e instanceof SelectorEvaluationError)
|
|
398
|
+
e.track(selector);
|
|
399
|
+
throw e;
|
|
220
400
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
401
|
+
return handleSelectorResult(tmpValue, selector, data);
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// src/lib/propagateUpdatedAtoms.ts
|
|
405
|
+
var reEvaluteSelector = (selector, data, updatedAtoms) => {
|
|
406
|
+
const existingValue = data.values.get(selector);
|
|
407
|
+
try {
|
|
408
|
+
const udpatedValue = evaluateSelector(selector, data, updatedAtoms);
|
|
409
|
+
if (selector.equal(existingValue, udpatedValue, updatedAtoms)) {
|
|
410
|
+
return [false, false];
|
|
411
|
+
} else {
|
|
412
|
+
setValueInData(selector, udpatedValue, data);
|
|
413
|
+
return [true, false];
|
|
224
414
|
}
|
|
415
|
+
} catch (error) {
|
|
416
|
+
data.expiredValues.set(selector, data.values.get(selector));
|
|
417
|
+
data.values.delete(selector);
|
|
418
|
+
return [true, true, error];
|
|
225
419
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
420
|
+
};
|
|
421
|
+
var addSetToSet = (fromSet, toSet) => {
|
|
422
|
+
if (fromSet && fromSet.size > 0) {
|
|
423
|
+
for (const item of fromSet) {
|
|
424
|
+
toSet.add(item);
|
|
229
425
|
}
|
|
230
426
|
}
|
|
231
427
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
428
|
+
var findClosestStoreWithAtomInitialized2 = (atom, data) => {
|
|
429
|
+
if ("parent" in data === false)
|
|
430
|
+
return data;
|
|
431
|
+
if (data.values.has(atom))
|
|
432
|
+
return data;
|
|
433
|
+
return findClosestStoreWithAtomInitialized2(atom, data.parent);
|
|
434
|
+
};
|
|
435
|
+
var findInClosestStore = (state, data) => {
|
|
436
|
+
const store = findClosestStoreWithAtomInitialized2(state, data);
|
|
437
|
+
return store.values.get(state);
|
|
438
|
+
};
|
|
439
|
+
var addFamilyAtomsToSet = (family, familyAtoms, data) => {
|
|
440
|
+
const currentAtoms = findInClosestStore(family, data) || [];
|
|
441
|
+
const atomsToAdd = [];
|
|
442
|
+
for (const familyAtom of familyAtoms) {
|
|
443
|
+
if (!currentAtoms.includes(familyAtom)) {
|
|
444
|
+
atomsToAdd.push(familyAtom);
|
|
244
445
|
}
|
|
245
446
|
}
|
|
447
|
+
if (atomsToAdd.length > 0) {
|
|
448
|
+
data.values.set(family, [...currentAtoms, ...atomsToAdd]);
|
|
449
|
+
}
|
|
246
450
|
};
|
|
247
|
-
var propagateUpdatedAtoms = (atoms, data) => {
|
|
248
|
-
const
|
|
249
|
-
for (const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const consumersFamily = data.stateConsumers.get(atom2.family);
|
|
256
|
-
if (consumersFamily?.size) {
|
|
257
|
-
recursivlyResetSelectorTree(consumersFamily, data, clearedSelectors);
|
|
451
|
+
var propagateUpdatedAtoms = (atoms, data, subscriptions = new Set, families = new Map, isRecursive = false) => {
|
|
452
|
+
const selectors = new Set;
|
|
453
|
+
for (const atom of atoms) {
|
|
454
|
+
addSetToSet(data.stateDependents.get(atom), selectors);
|
|
455
|
+
addSetToSet(data.subscriptions.get(atom), subscriptions);
|
|
456
|
+
if (isFamilyAtom(atom)) {
|
|
457
|
+
if (!families.has(atom.family)) {
|
|
458
|
+
families.set(atom.family, new Set);
|
|
258
459
|
}
|
|
460
|
+
families.get(atom.family).add(atom);
|
|
259
461
|
}
|
|
260
462
|
}
|
|
261
|
-
|
|
262
|
-
|
|
463
|
+
if (families.size > 0) {
|
|
464
|
+
for (const [family, familyAtoms] of families) {
|
|
465
|
+
addSetToSet(data.stateDependents.get(family), selectors);
|
|
466
|
+
addSetToSet(data.subscriptions.get(family), subscriptions);
|
|
467
|
+
if (familyAtoms.size === 0)
|
|
468
|
+
throw new Error("Should not be possible");
|
|
469
|
+
addFamilyAtomsToSet(family, familyAtoms, data);
|
|
470
|
+
}
|
|
263
471
|
}
|
|
264
|
-
|
|
265
|
-
|
|
472
|
+
if (!isRecursive) {
|
|
473
|
+
propagateDirtySelectors(atoms, selectors, data, subscriptions, families);
|
|
266
474
|
}
|
|
267
475
|
};
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (typeof newValue === "function") {
|
|
274
|
-
newValue = newValue(currentValue);
|
|
275
|
-
if (isPromiseLike(newValue) || isPromiseLike(currentValue))
|
|
276
|
-
throw new Error("Todo, how should we handle this?");
|
|
476
|
+
var propagateDirtySelectors = (updatedAtoms, selectors, data, subscriptions, families) => {
|
|
477
|
+
const initialUpdatedAtoms = new Set(updatedAtoms);
|
|
478
|
+
const updatedInitializedAtoms = new Set(initialUpdatedAtoms);
|
|
479
|
+
if (selectors.size > 0) {
|
|
480
|
+
recursivlyHandleSelectorUpdates(selectors, data, subscriptions, updatedInitializedAtoms);
|
|
277
481
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
482
|
+
const addedAtoms = initialUpdatedAtoms.symmetricDifference(updatedInitializedAtoms);
|
|
483
|
+
if (addedAtoms.size) {
|
|
484
|
+
console.log("addedAtoms", addedAtoms);
|
|
485
|
+
console.log("Valdres TODO: Support this case with new atoms added");
|
|
486
|
+
}
|
|
487
|
+
if (subscriptions.size > 0) {
|
|
488
|
+
for (const subscription of subscriptions) {
|
|
489
|
+
if ("state" in subscription) {
|
|
490
|
+
const updatedFamilyAtoms = families.get(subscription.state);
|
|
491
|
+
if (updatedFamilyAtoms) {
|
|
492
|
+
for (const atom of updatedFamilyAtoms) {
|
|
493
|
+
subscription.callback(...atom.familyArgs);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
subscription.callback();
|
|
498
|
+
}
|
|
499
|
+
}
|
|
283
500
|
}
|
|
284
|
-
propagateUpdatedAtoms([atom2], data);
|
|
285
501
|
};
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
promise.__isEmptyAtomPromise__ = true;
|
|
295
|
-
promise.__resolveEmptyAtomPromise__ = promiseResolve;
|
|
296
|
-
return promise;
|
|
297
|
-
} else if (typeof atom2.defaultValue === "function") {
|
|
298
|
-
const value = atom2.defaultValue();
|
|
299
|
-
if (isPromiseLike(value)) {
|
|
300
|
-
value.then((resolvedValue) => {
|
|
301
|
-
data.values.set(atom2, resolvedValue);
|
|
302
|
-
propagateUpdatedAtoms([atom2], data);
|
|
303
|
-
});
|
|
502
|
+
var findAllDependents = (selector, data, depsRes = new Set, subsRes = new Set) => {
|
|
503
|
+
const dependents = data.stateDependents.get(selector);
|
|
504
|
+
const subscriptions = data.subscriptions.get(selector);
|
|
505
|
+
addSetToSet(dependents, depsRes);
|
|
506
|
+
addSetToSet(subscriptions, subsRes);
|
|
507
|
+
if (dependents && dependents.size > 0) {
|
|
508
|
+
for (const dependent of dependents) {
|
|
509
|
+
findAllDependents(dependent, data, depsRes, subsRes);
|
|
304
510
|
}
|
|
305
|
-
return value;
|
|
306
|
-
} else {
|
|
307
|
-
return atom2.defaultValue;
|
|
308
511
|
}
|
|
512
|
+
return [depsRes, subsRes];
|
|
309
513
|
};
|
|
310
|
-
var
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
514
|
+
var recursivlyHandleSelectorUpdates = (selectors, data, collectedSubscribers, updatedInitializedAtoms, seen = new Set) => {
|
|
515
|
+
const selectorsForNextPass = new Set;
|
|
516
|
+
for (const selector of selectors) {
|
|
517
|
+
const currentValue = data.values.get(selector);
|
|
518
|
+
if (isPromiseLike(currentValue)) {
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
seen.add(selector);
|
|
522
|
+
const dependents = data.stateDependents.get(selector);
|
|
523
|
+
const subscribers = data.subscriptions.get(selector);
|
|
524
|
+
if ((!dependents || dependents.size === 0) && (!subscribers || subscribers.size === 0)) {
|
|
525
|
+
data.expiredValues.set(selector, data.values.get(selector));
|
|
526
|
+
data.values.delete(selector);
|
|
527
|
+
} else {
|
|
528
|
+
const [wasValueUpdated, didEvalCrash, error] = reEvaluteSelector(selector, data, updatedInitializedAtoms);
|
|
529
|
+
if (didEvalCrash) {
|
|
530
|
+
const [deps, subs] = findAllDependents(selector, data);
|
|
531
|
+
if (deps.size > 0) {
|
|
532
|
+
for (const dep of deps) {
|
|
533
|
+
data.expiredValues.set(dep, data.values.get(dep));
|
|
534
|
+
data.values.delete(dep);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (subs.size > 0) {
|
|
538
|
+
addSetToSet(subs, collectedSubscribers);
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
if (!wasValueUpdated)
|
|
542
|
+
continue;
|
|
543
|
+
addSetToSet(data.stateDependents.get(selector), selectorsForNextPass);
|
|
544
|
+
addSetToSet(subscribers, collectedSubscribers);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (selectorsForNextPass.size > 0) {
|
|
549
|
+
recursivlyHandleSelectorUpdates(selectorsForNextPass, data, collectedSubscribers, updatedInitializedAtoms, seen);
|
|
550
|
+
}
|
|
319
551
|
};
|
|
320
552
|
|
|
321
|
-
// src/
|
|
322
|
-
var
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
553
|
+
// src/lib/createStoreData.ts
|
|
554
|
+
var generateId = () => (Math.random() + 1).toString(36).substring(7);
|
|
555
|
+
var generateStoreData = (id = generateId()) => {
|
|
556
|
+
return {
|
|
557
|
+
id,
|
|
558
|
+
values: new WeakMap,
|
|
559
|
+
expiredValues: new WeakMap,
|
|
560
|
+
subscriptions: new WeakMap,
|
|
561
|
+
subscriptionsRequireEqualCheck: new WeakMap,
|
|
562
|
+
stateDependents: new WeakMap,
|
|
563
|
+
stateDependencies: new WeakMap,
|
|
564
|
+
scopes: {}
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
function createStoreData(id, parent) {
|
|
568
|
+
if (parent) {
|
|
569
|
+
return {
|
|
570
|
+
...generateStoreData(id),
|
|
571
|
+
parent,
|
|
572
|
+
scopeConsumers: parent ? new Set : undefined
|
|
573
|
+
};
|
|
574
|
+
} else {
|
|
575
|
+
return generateStoreData(id);
|
|
341
576
|
}
|
|
342
|
-
throw new Error("Invalid object passed to get");
|
|
343
577
|
}
|
|
344
578
|
|
|
579
|
+
// src/lib/deleteFamilyAtom.ts
|
|
580
|
+
var deleteFamilyAtom = (atom, data) => {
|
|
581
|
+
const array = data.values.get(atom.family);
|
|
582
|
+
const index = array.indexOf(atom);
|
|
583
|
+
const newArray = [
|
|
584
|
+
...array.slice(0, index),
|
|
585
|
+
...array.slice(index + 1)
|
|
586
|
+
];
|
|
587
|
+
data.values.delete(atom);
|
|
588
|
+
propagateUpdatedAtoms([atom], data);
|
|
589
|
+
setValueInData(atom.family, newArray, data);
|
|
590
|
+
propagateUpdatedAtoms([atom.family], data);
|
|
591
|
+
};
|
|
592
|
+
|
|
345
593
|
// src/lib/resetAtom.ts
|
|
346
|
-
var resetAtom = (
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
594
|
+
var resetAtom = (atom, data) => {
|
|
595
|
+
const initializedAtomsSet = new Set;
|
|
596
|
+
let value = getAtomInitValue(atom, data, initializedAtomsSet);
|
|
597
|
+
setValueInData(atom, value, data);
|
|
598
|
+
if (!isPromiseLike(value)) {
|
|
599
|
+
propagateUpdatedAtoms([atom], data);
|
|
600
|
+
}
|
|
601
|
+
if (initializedAtomsSet.size > 0) {
|
|
602
|
+
throw new Error("Todo - propagateUpdatedAtoms on reset");
|
|
350
603
|
}
|
|
351
|
-
return
|
|
604
|
+
return value;
|
|
352
605
|
};
|
|
353
606
|
|
|
607
|
+
// src/utils/isFamily.ts
|
|
608
|
+
var isFamily = (state) => isAtomFamily(state) || isSelectorFamily(state);
|
|
609
|
+
|
|
354
610
|
// src/lib/unsubscribe.ts
|
|
355
|
-
var unsubscribe = (state, subscription, data, mount) => {
|
|
611
|
+
var unsubscribe = (state, subscription, data, mount, maxAgeCleanup) => {
|
|
356
612
|
const subscribers = data.subscriptions.get(state);
|
|
357
613
|
if (subscribers) {
|
|
358
614
|
subscribers.delete(subscription);
|
|
@@ -368,6 +624,11 @@ var unsubscribe = (state, subscription, data, mount) => {
|
|
|
368
624
|
data.subscriptionsRequireEqualCheck.delete(state);
|
|
369
625
|
}
|
|
370
626
|
}
|
|
627
|
+
if (subscribers.size === 0) {
|
|
628
|
+
if (maxAgeCleanup)
|
|
629
|
+
maxAgeCleanup();
|
|
630
|
+
data.subscriptions.delete(state);
|
|
631
|
+
}
|
|
371
632
|
if (mount) {
|
|
372
633
|
if (subscribers.size === mount.mountSubscriptions.size) {
|
|
373
634
|
if (typeof mount.onUnmount === "function") {
|
|
@@ -385,12 +646,33 @@ var initSubscribers = (state, data) => {
|
|
|
385
646
|
return set;
|
|
386
647
|
};
|
|
387
648
|
var subscribe = (state, callback, requireDeepEqualCheckBeforeCallback, data) => {
|
|
388
|
-
|
|
649
|
+
let parentUnsubscribe;
|
|
650
|
+
if ("parent" in data && (!data.values.has(state) && isAtom(state) || isAtomFamily(state))) {
|
|
651
|
+
const originalCallback = callback;
|
|
652
|
+
parentUnsubscribe = subscribe(state, originalCallback, requireDeepEqualCheckBeforeCallback, data.parent);
|
|
653
|
+
callback = (arg) => {
|
|
654
|
+
if (parentUnsubscribe) {
|
|
655
|
+
parentUnsubscribe();
|
|
656
|
+
parentUnsubscribe = undefined;
|
|
657
|
+
}
|
|
658
|
+
originalCallback(arg);
|
|
659
|
+
};
|
|
660
|
+
} else if (!data.values.has(state) && isAtom(state)) {
|
|
661
|
+
const initializedAtomsSet = new Set;
|
|
662
|
+
initAtom(state, data, initializedAtomsSet);
|
|
663
|
+
if (initializedAtomsSet.size) {
|
|
664
|
+
throw new Error("This should not be possible");
|
|
665
|
+
}
|
|
666
|
+
}
|
|
389
667
|
if (isSelector(state) && !data.values.has(state)) {
|
|
390
|
-
initSelector(state, data);
|
|
668
|
+
initSelector(state, data, new Set, new WeakSet);
|
|
391
669
|
}
|
|
670
|
+
const subscribers = data.subscriptions.get(state) || initSubscribers(state, data);
|
|
392
671
|
let subscription;
|
|
393
672
|
if (isFamily(state)) {
|
|
673
|
+
if (isSelectorFamily(state)) {
|
|
674
|
+
throw new Error("Subscribe to selectorFammily is currently not supported");
|
|
675
|
+
}
|
|
394
676
|
subscription = {
|
|
395
677
|
callback,
|
|
396
678
|
state,
|
|
@@ -404,47 +686,83 @@ var subscribe = (state, callback, requireDeepEqualCheckBeforeCallback, data) =>
|
|
|
404
686
|
}
|
|
405
687
|
subscribers.add(subscription);
|
|
406
688
|
let mount;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
689
|
+
let maxAgeCleanup;
|
|
690
|
+
if (subscribers.size === 1) {
|
|
691
|
+
if (isAtom(state) && state.maxAge) {
|
|
692
|
+
let timeout;
|
|
693
|
+
const interval = setInterval(() => {
|
|
694
|
+
let value = getAtomInitValue(state, data);
|
|
695
|
+
if (isPromiseLike(value)) {
|
|
696
|
+
if (state.staleWhileRevalidate) {
|
|
697
|
+
const oldValue = data.values.get(state);
|
|
698
|
+
timeout = setTimeout(() => {
|
|
699
|
+
const nowValue = data.values.get(state);
|
|
700
|
+
console.log("todo", oldValue);
|
|
701
|
+
}, state.staleWhileRevalidate);
|
|
702
|
+
value.then((res) => clearTimeout(timeout));
|
|
703
|
+
}
|
|
704
|
+
} else {
|
|
705
|
+
setValueInData(state, value, data);
|
|
706
|
+
propagateUpdatedAtoms([state], data);
|
|
707
|
+
}
|
|
708
|
+
}, state.maxAge);
|
|
709
|
+
maxAgeCleanup = () => {
|
|
710
|
+
clearInterval(interval);
|
|
711
|
+
if (timeout)
|
|
712
|
+
clearTimeout(timeout);
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
if (state.onMount) {
|
|
716
|
+
const store = storeFromStoreData(data);
|
|
717
|
+
const mountSubscriptions = new Set;
|
|
718
|
+
const originalSub = store.sub;
|
|
719
|
+
store.sub = (state2, callback2) => {
|
|
720
|
+
mountSubscriptions.add(callback2);
|
|
721
|
+
return originalSub(state2, callback2);
|
|
722
|
+
};
|
|
723
|
+
mount = {
|
|
724
|
+
onUnmount: state.onMount(store, state),
|
|
725
|
+
mountSubscriptions
|
|
726
|
+
};
|
|
727
|
+
}
|
|
419
728
|
}
|
|
420
729
|
if (requireDeepEqualCheckBeforeCallback && data.subscriptionsRequireEqualCheck.get(state) !== true) {
|
|
421
730
|
data.subscriptionsRequireEqualCheck.set(state, true);
|
|
422
731
|
}
|
|
423
|
-
return () =>
|
|
732
|
+
return () => {
|
|
733
|
+
if (parentUnsubscribe) {
|
|
734
|
+
parentUnsubscribe();
|
|
735
|
+
}
|
|
736
|
+
unsubscribe(state, subscription, data, mount, maxAgeCleanup);
|
|
737
|
+
};
|
|
424
738
|
};
|
|
425
739
|
|
|
426
740
|
// src/lib/setAtoms.ts
|
|
427
|
-
|
|
428
|
-
var setAtoms = (pairs, data) => {
|
|
741
|
+
var setAtoms = (pairs, data, initializedAtomsSet) => {
|
|
429
742
|
const updatedAtoms = [];
|
|
430
|
-
for (let [
|
|
431
|
-
const currentValue = getState(
|
|
432
|
-
if (!
|
|
433
|
-
updatedAtoms.push(
|
|
434
|
-
|
|
743
|
+
for (let [atom, value] of pairs) {
|
|
744
|
+
const currentValue = getState(atom, data, initializedAtomsSet);
|
|
745
|
+
if (!atom.equal(currentValue, value)) {
|
|
746
|
+
updatedAtoms.push(atom);
|
|
747
|
+
value = setValueInData(atom, value, data);
|
|
748
|
+
if (atom.onSet)
|
|
749
|
+
atom.onSet(value, data);
|
|
435
750
|
}
|
|
436
751
|
}
|
|
437
|
-
|
|
752
|
+
const result = new Set([...updatedAtoms, ...initializedAtomsSet]);
|
|
753
|
+
if (result.size > 0) {
|
|
754
|
+
propagateUpdatedAtoms([...result], data);
|
|
755
|
+
}
|
|
438
756
|
};
|
|
439
757
|
|
|
440
758
|
// src/lib/transaction.ts
|
|
441
759
|
var findDependencies = (state, data, result = new Set) => {
|
|
442
|
-
const
|
|
443
|
-
if (
|
|
444
|
-
for (const
|
|
445
|
-
if (!result.has(
|
|
446
|
-
result.add(
|
|
447
|
-
findDependencies(
|
|
760
|
+
const dependents = data.stateDependents.get(state);
|
|
761
|
+
if (dependents?.size) {
|
|
762
|
+
for (const dependent of dependents) {
|
|
763
|
+
if (!result.has(dependent)) {
|
|
764
|
+
result.add(dependent);
|
|
765
|
+
findDependencies(dependent, data, result);
|
|
448
766
|
}
|
|
449
767
|
}
|
|
450
768
|
}
|
|
@@ -458,14 +776,43 @@ var recursivlyResetTxnSelectorCache = (state, txnSubscribers, txnSelectorCache)
|
|
|
458
776
|
}
|
|
459
777
|
}
|
|
460
778
|
};
|
|
461
|
-
var
|
|
462
|
-
let
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
779
|
+
var captureScopedTransaction = (scopedData, parentGetInTxnOrData) => {
|
|
780
|
+
let txn;
|
|
781
|
+
transaction((scopedTxn) => {
|
|
782
|
+
txn = scopedTxn;
|
|
783
|
+
}, scopedData, false, parentGetInTxnOrData);
|
|
784
|
+
return txn;
|
|
785
|
+
};
|
|
786
|
+
var deleteAtomFamilyAtoms = (set, data) => {
|
|
787
|
+
set.forEach((atom) => {
|
|
788
|
+
data.values.delete(atom);
|
|
789
|
+
});
|
|
790
|
+
};
|
|
791
|
+
var transaction = (callback, data, autoCommit = true, parentGetInTxnOrData) => {
|
|
792
|
+
const txnAtomMap = new Map;
|
|
793
|
+
const txnAtomDeleteSet = new Set;
|
|
794
|
+
const txnSelectorCache = new Map;
|
|
795
|
+
const txnSubscribers = new Map;
|
|
796
|
+
const dirtySelectors = new Set;
|
|
797
|
+
let scopedTransactions;
|
|
798
|
+
const getInTxnOrData = (state) => {
|
|
799
|
+
if (txnAtomMap.has(state)) {
|
|
800
|
+
return txnAtomMap.get(state);
|
|
801
|
+
}
|
|
802
|
+
if (data.values.has(state)) {
|
|
803
|
+
return data.values.get(state);
|
|
804
|
+
}
|
|
805
|
+
if (parentGetInTxnOrData) {
|
|
806
|
+
return parentGetInTxnOrData(state);
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
const initializedAtomsSet = new Set;
|
|
466
810
|
const txnGet = (state) => {
|
|
467
811
|
if (isAtom(state)) {
|
|
468
|
-
|
|
812
|
+
const value = getInTxnOrData(state);
|
|
813
|
+
if (value)
|
|
814
|
+
return value;
|
|
815
|
+
return getState(state, data, initializedAtomsSet);
|
|
469
816
|
} else if (isSelector(state)) {
|
|
470
817
|
if (txnSelectorCache.has(state)) {
|
|
471
818
|
return txnSelectorCache.get(state);
|
|
@@ -474,7 +821,7 @@ var transaction = (callback, data) => {
|
|
|
474
821
|
const res = state.get((s) => {
|
|
475
822
|
deps.add(s);
|
|
476
823
|
return txnGet(s);
|
|
477
|
-
});
|
|
824
|
+
}, data.id);
|
|
478
825
|
for (const dep of deps) {
|
|
479
826
|
if (!txnSubscribers.has(dep)) {
|
|
480
827
|
txnSubscribers.set(dep, new Set);
|
|
@@ -483,127 +830,526 @@ var transaction = (callback, data) => {
|
|
|
483
830
|
}
|
|
484
831
|
txnSelectorCache.set(state, res);
|
|
485
832
|
return res;
|
|
833
|
+
} else if (isAtomFamily(state)) {
|
|
834
|
+
const value = getInTxnOrData(state);
|
|
835
|
+
if (value)
|
|
836
|
+
return value;
|
|
837
|
+
return getState(state, data, initializedAtomsSet);
|
|
486
838
|
} else {
|
|
487
839
|
throw new Error("Unsupported state");
|
|
488
840
|
}
|
|
489
841
|
};
|
|
490
|
-
const txnSet = (
|
|
491
|
-
if (!isAtom(
|
|
842
|
+
const txnSet = (atom, value) => {
|
|
843
|
+
if (!isAtom(atom))
|
|
492
844
|
throw new Error("Not an atom");
|
|
493
|
-
if (
|
|
494
|
-
const currentValue = txnGet(
|
|
845
|
+
if (isFunction(value)) {
|
|
846
|
+
const currentValue = txnGet(atom);
|
|
495
847
|
value = value(currentValue);
|
|
496
848
|
}
|
|
497
|
-
for (const selector of findDependencies(
|
|
849
|
+
for (const selector of findDependencies(atom, data)) {
|
|
498
850
|
dirtySelectors.add(selector);
|
|
499
851
|
txnSelectorCache.delete(selector);
|
|
500
852
|
}
|
|
501
|
-
if (txnSubscribers.get(
|
|
502
|
-
recursivlyResetTxnSelectorCache(
|
|
853
|
+
if (txnSubscribers.get(atom)?.size) {
|
|
854
|
+
recursivlyResetTxnSelectorCache(atom, txnSubscribers, txnSelectorCache);
|
|
855
|
+
}
|
|
856
|
+
if (isProd()) {
|
|
857
|
+
txnAtomMap.set(atom, value);
|
|
858
|
+
} else {
|
|
859
|
+
txnAtomMap.set(atom, deepFreeze(value));
|
|
503
860
|
}
|
|
504
|
-
|
|
861
|
+
if (isFamilyAtom(atom)) {
|
|
862
|
+
const currentFamilyList = txnGet(atom.family);
|
|
863
|
+
if (!currentFamilyList.includes(atom)) {
|
|
864
|
+
const newArr = [...currentFamilyList, atom];
|
|
865
|
+
txnAtomMap.set(atom.family, newArr);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return value;
|
|
505
869
|
};
|
|
506
|
-
const txnReset = (
|
|
507
|
-
const value = getAtomInitValue(
|
|
508
|
-
txnAtomMap.set(
|
|
870
|
+
const txnReset = (atom) => {
|
|
871
|
+
const value = getAtomInitValue(atom, data, initializedAtomsSet);
|
|
872
|
+
txnAtomMap.set(atom, value);
|
|
509
873
|
return value;
|
|
510
874
|
};
|
|
875
|
+
const txnDel = (atom) => {
|
|
876
|
+
const array = txnGet(atom.family);
|
|
877
|
+
const index = array.indexOf(atom);
|
|
878
|
+
const newArr = [
|
|
879
|
+
...array.slice(0, index),
|
|
880
|
+
...array.slice(index + 1)
|
|
881
|
+
];
|
|
882
|
+
txnAtomMap.set(atom.family, newArr);
|
|
883
|
+
if (data.values.has(atom)) {
|
|
884
|
+
txnAtomDeleteSet.add(atom);
|
|
885
|
+
}
|
|
886
|
+
if (txnAtomMap.has(atom)) {
|
|
887
|
+
txnAtomMap.delete(atom);
|
|
888
|
+
}
|
|
889
|
+
};
|
|
511
890
|
const commit = () => {
|
|
512
|
-
setAtoms(txnAtomMap, data);
|
|
891
|
+
setAtoms(txnAtomMap, data, initializedAtomsSet);
|
|
892
|
+
if (txnAtomDeleteSet.size) {
|
|
893
|
+
deleteAtomFamilyAtoms(txnAtomDeleteSet, data);
|
|
894
|
+
}
|
|
513
895
|
dirtySelectors.clear();
|
|
896
|
+
if (scopedTransactions) {
|
|
897
|
+
for (const scopedTxn of Object.values(scopedTransactions)) {
|
|
898
|
+
scopedTxn.commit();
|
|
899
|
+
}
|
|
900
|
+
}
|
|
514
901
|
};
|
|
515
|
-
const result = callback(
|
|
516
|
-
|
|
902
|
+
const result = callback({
|
|
903
|
+
set: txnSet,
|
|
904
|
+
get: txnGet,
|
|
905
|
+
del: txnDel,
|
|
906
|
+
reset: txnReset,
|
|
907
|
+
commit,
|
|
908
|
+
scope: (scopeId, callback2) => {
|
|
909
|
+
if (scopeId in data.scopes) {
|
|
910
|
+
const scopedData = data.scopes[scopeId];
|
|
911
|
+
if (scopedTransactions === undefined) {
|
|
912
|
+
scopedTransactions = {};
|
|
913
|
+
}
|
|
914
|
+
if (scopedTransactions[scopeId] === undefined) {
|
|
915
|
+
scopedTransactions[scopeId] = captureScopedTransaction(scopedData, getInTxnOrData);
|
|
916
|
+
}
|
|
917
|
+
return callback2(scopedTransactions[scopeId]);
|
|
918
|
+
} else {
|
|
919
|
+
throw new Error(`Scope '${scopeId}' not found. Registered scopes: ${Object.keys(data.scopes).join(", ")}`);
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
data
|
|
923
|
+
});
|
|
924
|
+
if (autoCommit)
|
|
925
|
+
commit();
|
|
517
926
|
return result;
|
|
518
927
|
};
|
|
519
928
|
|
|
520
929
|
// src/lib/storeFromStoreData.ts
|
|
521
|
-
var
|
|
522
|
-
|
|
930
|
+
var SelectorProvidedToSetError = `Invalid state object passed to set().
|
|
931
|
+
You provided a \`selector\`.
|
|
932
|
+
Only \`atom\` cam be set.
|
|
933
|
+
`;
|
|
934
|
+
var InvalidStateSetError = `Invalid state object passed to set().
|
|
935
|
+
Only \`atom\` can be set.
|
|
936
|
+
`;
|
|
937
|
+
function storeFromStoreData(data, detach) {
|
|
938
|
+
const get = (state) => {
|
|
939
|
+
const set2 = new Set;
|
|
940
|
+
const res = getState(state, data, set2);
|
|
941
|
+
if (set2.size) {
|
|
942
|
+
propagateUpdatedAtoms([...set2], data);
|
|
943
|
+
}
|
|
944
|
+
return res;
|
|
945
|
+
};
|
|
523
946
|
const set = (state, value) => {
|
|
524
|
-
if (
|
|
525
|
-
|
|
526
|
-
|
|
947
|
+
if (isAtom(state))
|
|
948
|
+
return setAtom(state, value, data);
|
|
949
|
+
if (isSelector(state))
|
|
950
|
+
throw new Error(SelectorProvidedToSetError);
|
|
951
|
+
throw new Error(InvalidStateSetError);
|
|
527
952
|
};
|
|
528
|
-
const reset = (
|
|
953
|
+
const reset = (atom) => resetAtom(atom, data);
|
|
954
|
+
const del = (atom) => deleteFamilyAtom(atom, data);
|
|
529
955
|
const sub = (state, callback, deepEqualCheckBeforeCallback = true) => subscribe(state, callback, deepEqualCheckBeforeCallback, data);
|
|
530
956
|
const txn = (callback) => transaction(callback, data);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
957
|
+
const scope = (scopeId) => {
|
|
958
|
+
let scopedStoreData;
|
|
959
|
+
if (scopeId in data.scopes) {
|
|
960
|
+
scopedStoreData = data.scopes[scopeId];
|
|
961
|
+
} else {
|
|
962
|
+
scopedStoreData = createStoreData(scopeId, data);
|
|
963
|
+
data.scopes[scopeId] = scopedStoreData;
|
|
964
|
+
}
|
|
965
|
+
const detach2 = () => {
|
|
966
|
+
scopedStoreData.scopeConsumers.delete(detach2);
|
|
967
|
+
if (scopedStoreData.scopeConsumers.size === 0) {
|
|
968
|
+
delete data.scopes[scopeId];
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
scopedStoreData.scopeConsumers.add(detach2);
|
|
972
|
+
const newStore = storeFromStoreData(data.scopes[scopeId], detach2);
|
|
973
|
+
return newStore;
|
|
538
974
|
};
|
|
539
|
-
|
|
975
|
+
if (detach) {
|
|
976
|
+
return {
|
|
977
|
+
get,
|
|
978
|
+
set,
|
|
979
|
+
sub,
|
|
980
|
+
txn,
|
|
981
|
+
reset,
|
|
982
|
+
del,
|
|
983
|
+
data,
|
|
984
|
+
scope,
|
|
985
|
+
detach
|
|
986
|
+
};
|
|
987
|
+
} else {
|
|
988
|
+
return {
|
|
989
|
+
get,
|
|
990
|
+
set,
|
|
991
|
+
sub,
|
|
992
|
+
txn,
|
|
993
|
+
reset,
|
|
994
|
+
del,
|
|
995
|
+
data,
|
|
996
|
+
scope
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
}
|
|
540
1000
|
|
|
541
|
-
// src/
|
|
542
|
-
var
|
|
1001
|
+
// src/store.ts
|
|
1002
|
+
var store = (id) => {
|
|
543
1003
|
const data = createStoreData(id);
|
|
544
1004
|
return storeFromStoreData(data);
|
|
545
1005
|
};
|
|
1006
|
+
|
|
1007
|
+
// src/globalStore.ts
|
|
1008
|
+
var globalStore = Object.assign(store("valdres-global-store"), {
|
|
1009
|
+
atoms: new Map,
|
|
1010
|
+
atomFamilies: new Map
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
// src/lib/globalAtom.ts
|
|
1014
|
+
var globalAtom = (defaultValue, options) => {
|
|
1015
|
+
const stores = new Set;
|
|
1016
|
+
let value;
|
|
1017
|
+
let initialized = false;
|
|
1018
|
+
let onReset;
|
|
1019
|
+
if (options.onSet)
|
|
1020
|
+
throw new Error("onSet on globalAtom is currently not supported");
|
|
1021
|
+
const onInit = (setSelf2, data) => {
|
|
1022
|
+
setSelf2(globalStore.get(atom));
|
|
1023
|
+
if (!initialized && options.onInit) {
|
|
1024
|
+
onReset = options.onInit((newVal) => {
|
|
1025
|
+
setSelf2(newVal);
|
|
1026
|
+
value = newVal;
|
|
1027
|
+
}, data);
|
|
1028
|
+
initialized = true;
|
|
1029
|
+
}
|
|
1030
|
+
stores.add(data);
|
|
1031
|
+
};
|
|
1032
|
+
const onSet = (newValue, currentStore) => {
|
|
1033
|
+
value = newValue;
|
|
1034
|
+
if (stores.size > 1) {
|
|
1035
|
+
for (const store2 of stores) {
|
|
1036
|
+
if (store2.id !== currentStore.id) {
|
|
1037
|
+
setAtom(atom, value, store2, true);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
const getSelf = () => globalStore.get(atom);
|
|
1043
|
+
const setSelf = (newValue) => globalStore.set(atom, newValue);
|
|
1044
|
+
const resetSelf = () => {
|
|
1045
|
+
value = undefined;
|
|
1046
|
+
initialized = false;
|
|
1047
|
+
for (const store2 of stores) {
|
|
1048
|
+
if (store2.stateDependencies.has(atom)) {
|
|
1049
|
+
throw new Error("TODO: Reset support for stateDependencies");
|
|
1050
|
+
}
|
|
1051
|
+
store2.values.delete(atom);
|
|
1052
|
+
store2.expiredValues.delete(atom);
|
|
1053
|
+
propagateUpdatedAtoms([atom], store2);
|
|
1054
|
+
stores.delete(store2);
|
|
1055
|
+
onReset?.();
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
const atom = {
|
|
1059
|
+
equal,
|
|
1060
|
+
...options,
|
|
1061
|
+
defaultValue,
|
|
1062
|
+
name: options?.name,
|
|
1063
|
+
onInit,
|
|
1064
|
+
onSet,
|
|
1065
|
+
setSelf,
|
|
1066
|
+
getSelf,
|
|
1067
|
+
resetSelf,
|
|
1068
|
+
get stores() {
|
|
1069
|
+
return stores;
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
return atom;
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
// src/atom.ts
|
|
1076
|
+
function atom(defaultValue, options) {
|
|
1077
|
+
if (!options)
|
|
1078
|
+
return { equal, defaultValue };
|
|
1079
|
+
if (options.global) {
|
|
1080
|
+
return globalAtom(defaultValue, options);
|
|
1081
|
+
}
|
|
1082
|
+
return {
|
|
1083
|
+
equal,
|
|
1084
|
+
defaultValue,
|
|
1085
|
+
...options
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
// src/lib/atomFamilyAtom.ts
|
|
1089
|
+
function atomFamilyAtom(defaultValue, options) {
|
|
1090
|
+
if (options.global) {
|
|
1091
|
+
return globalAtom(defaultValue, options);
|
|
1092
|
+
}
|
|
1093
|
+
return {
|
|
1094
|
+
...options,
|
|
1095
|
+
defaultValue
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// src/lib/stableStringify.ts
|
|
1100
|
+
var stableStringifyRecurse = (x, key) => {
|
|
1101
|
+
if (typeof x === "string" && !x.includes('"') && !x.includes("\\")) {
|
|
1102
|
+
return `"${x}"`;
|
|
1103
|
+
}
|
|
1104
|
+
switch (typeof x) {
|
|
1105
|
+
case "undefined":
|
|
1106
|
+
return "";
|
|
1107
|
+
case "boolean":
|
|
1108
|
+
return x ? "true" : "false";
|
|
1109
|
+
case "number":
|
|
1110
|
+
case "symbol":
|
|
1111
|
+
return String(x);
|
|
1112
|
+
case "string":
|
|
1113
|
+
return JSON.stringify(x);
|
|
1114
|
+
case "function":
|
|
1115
|
+
return `__FUNCTION(${x.toString()})__`;
|
|
1116
|
+
}
|
|
1117
|
+
if (x === null) {
|
|
1118
|
+
return "null";
|
|
1119
|
+
}
|
|
1120
|
+
if (typeof x !== "object") {
|
|
1121
|
+
return JSON.stringify(x) ?? "";
|
|
1122
|
+
}
|
|
1123
|
+
if (isPromiseLike(x)) {
|
|
1124
|
+
return "__PROMISE__";
|
|
1125
|
+
}
|
|
1126
|
+
if (Array.isArray(x)) {
|
|
1127
|
+
return `[${x.map((v, i) => stableStringifyRecurse(v, i.toString()))}]`;
|
|
1128
|
+
}
|
|
1129
|
+
if (typeof x.toJSON === "function") {
|
|
1130
|
+
return stableStringifyRecurse(x.toJSON(key), key);
|
|
1131
|
+
}
|
|
1132
|
+
if (x instanceof Map) {
|
|
1133
|
+
const obj = {};
|
|
1134
|
+
for (const [k, v] of x) {
|
|
1135
|
+
obj[typeof k === "string" ? k : stringify(k, opt)] = v;
|
|
1136
|
+
}
|
|
1137
|
+
return stableStringifyRecurse(obj, key);
|
|
1138
|
+
}
|
|
1139
|
+
if (x instanceof Set) {
|
|
1140
|
+
return stableStringifyRecurse(Array.from(x).sort((a, b) => stableStringifyRecurse(a).localeCompare(stableStringifyRecurse(b))), key);
|
|
1141
|
+
}
|
|
1142
|
+
if (Symbol !== undefined && x[Symbol.iterator] != null && typeof x[Symbol.iterator] === "function") {
|
|
1143
|
+
return stableStringifyRecurse(Array.from(x), key);
|
|
1144
|
+
}
|
|
1145
|
+
return `{${Object.keys(x).filter((k) => x[k] !== undefined).sort().map((k) => `${stableStringifyRecurse(k)}:${stableStringifyRecurse(x[k], k)}`).join(",")}}`;
|
|
1146
|
+
};
|
|
1147
|
+
var stableStringify = (x) => {
|
|
1148
|
+
if (typeof x === "string" || typeof x === "boolean" || typeof x === "number")
|
|
1149
|
+
return x;
|
|
1150
|
+
return stableStringifyRecurse(x);
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1153
|
+
// src/lib/stringifyFamilyArgs.ts
|
|
1154
|
+
var stringifyFamilyArgs = (args) => {
|
|
1155
|
+
return args.length === 1 ? stableStringify(args[0]) : stableStringify(args);
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
// src/lib/createAtomFamily.ts
|
|
1159
|
+
var createOptions = (options = {}, family, familyArgs, familyArgsStringified) => {
|
|
1160
|
+
if (options.name) {
|
|
1161
|
+
return {
|
|
1162
|
+
equal,
|
|
1163
|
+
...options,
|
|
1164
|
+
name: options?.name + "_" + familyArgsStringified,
|
|
1165
|
+
family,
|
|
1166
|
+
familyArgs,
|
|
1167
|
+
familyArgsStringified
|
|
1168
|
+
};
|
|
1169
|
+
} else {
|
|
1170
|
+
return { equal, ...options, family, familyArgs, familyArgsStringified };
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
var handleDefaultValue = (defaultValue, ...args) => {
|
|
1174
|
+
if (isSelectorFamily(defaultValue))
|
|
1175
|
+
return defaultValue(...args);
|
|
1176
|
+
if (typeof defaultValue === "function")
|
|
1177
|
+
return () => defaultValue(...args);
|
|
1178
|
+
return defaultValue;
|
|
1179
|
+
};
|
|
1180
|
+
var createAtomFamily = (defaultValue, options) => {
|
|
1181
|
+
const map = new Map;
|
|
1182
|
+
const atomFamily = (...args) => {
|
|
1183
|
+
const argsStringified = stringifyFamilyArgs(args);
|
|
1184
|
+
if (map.has(argsStringified)) {
|
|
1185
|
+
return map.get(argsStringified);
|
|
1186
|
+
}
|
|
1187
|
+
const familyAtom = atomFamilyAtom(handleDefaultValue(defaultValue, ...args), createOptions(options, atomFamily, args, argsStringified));
|
|
1188
|
+
map.set(argsStringified, familyAtom);
|
|
1189
|
+
return familyAtom;
|
|
1190
|
+
};
|
|
1191
|
+
if (options?.name)
|
|
1192
|
+
Object.defineProperty(atomFamily, "name", {
|
|
1193
|
+
value: options.name,
|
|
1194
|
+
writable: false
|
|
1195
|
+
});
|
|
1196
|
+
return Object.assign(atomFamily, {
|
|
1197
|
+
__valdresAtomFamilyMap: map,
|
|
1198
|
+
release: (...args) => map.delete(stringifyFamilyArgs(args)),
|
|
1199
|
+
equal
|
|
1200
|
+
});
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
// src/lib/createGlobalAtomFamily.ts
|
|
1204
|
+
var createGlobalAtomFamily = (defaultValue, options) => {
|
|
1205
|
+
if (!options.name)
|
|
1206
|
+
throw new Error(`Missing name for global atomFamiliy`);
|
|
1207
|
+
if (globalStore.atomFamilies.has(options.name)) {
|
|
1208
|
+
return globalStore.atomFamilies.get(options.name);
|
|
1209
|
+
}
|
|
1210
|
+
const family = createAtomFamily(defaultValue, options);
|
|
1211
|
+
globalStore.atomFamilies.set(options.name, family);
|
|
1212
|
+
return family;
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
// src/atomFamily.ts
|
|
1216
|
+
function atomFamily(defaultValue, options) {
|
|
1217
|
+
if (options?.global)
|
|
1218
|
+
return createGlobalAtomFamily(defaultValue, options);
|
|
1219
|
+
return createAtomFamily(defaultValue, options);
|
|
1220
|
+
}
|
|
546
1221
|
// src/createStoreWithSelectorSet.ts
|
|
547
|
-
var setSelector = (selector, values,
|
|
548
|
-
return selector.set(
|
|
1222
|
+
var setSelector = (selector, values, store2) => {
|
|
1223
|
+
return selector.set(store2.set, store2.get, store2.reset, ...values);
|
|
549
1224
|
};
|
|
550
1225
|
var createStoreWithSelectorSet = (id) => {
|
|
551
1226
|
const data = createStoreData(id);
|
|
552
|
-
const
|
|
553
|
-
|
|
1227
|
+
const store2 = storeFromStoreData(data);
|
|
1228
|
+
store2.set = (state, value, ...rest) => {
|
|
554
1229
|
if (isAtom(state))
|
|
555
1230
|
return setAtom(state, value, data);
|
|
556
1231
|
if (isSelector(state))
|
|
557
|
-
return setSelector(state, [value, ...rest],
|
|
1232
|
+
return setSelector(state, [value, ...rest], store2);
|
|
558
1233
|
throw new Error("Invalid state object");
|
|
559
1234
|
};
|
|
560
|
-
|
|
561
|
-
return
|
|
1235
|
+
store2.kind = "storeWithSelectorSet";
|
|
1236
|
+
return store2;
|
|
562
1237
|
};
|
|
563
|
-
// src/getDefaultStore.ts
|
|
564
|
-
if (!globalThis._valdresStore) {
|
|
565
|
-
globalThis._valdresStore = createStore("default");
|
|
566
|
-
}
|
|
567
|
-
var getDefaultStore = () => globalThis._valdresStore;
|
|
568
|
-
var resetDefaultStore = () => globalThis._valdresStore = createStore();
|
|
569
1238
|
// src/selector.ts
|
|
570
|
-
var selector = (get,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
1239
|
+
var selector = (get, options) => {
|
|
1240
|
+
if (!options)
|
|
1241
|
+
return { equal, get };
|
|
1242
|
+
return { equal, ...options, get };
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/indexConstructor.ts
|
|
1246
|
+
var index = (family, callback, options) => {
|
|
1247
|
+
const map = new Map;
|
|
1248
|
+
const index2 = (term) => {
|
|
1249
|
+
const termKey = stableStringify(term);
|
|
1250
|
+
if (map.has(termKey))
|
|
1251
|
+
return map.get(termKey);
|
|
1252
|
+
const termIndexSelectorSet = new Set;
|
|
1253
|
+
const termIndexSelectorMap = new Map;
|
|
1254
|
+
const termIndexSelector = selector((get) => {
|
|
1255
|
+
const allFamilyAtoms = new Set(get(family));
|
|
1256
|
+
const deletedAtoms = termIndexSelectorSet.symmetricDifference(allFamilyAtoms);
|
|
1257
|
+
const addedAtoms = allFamilyAtoms.difference(termIndexSelectorSet);
|
|
1258
|
+
if (deletedAtoms.size || addedAtoms.size) {
|
|
1259
|
+
deletedAtoms.forEach((atom2) => {
|
|
1260
|
+
termIndexSelectorSet.delete(atom2);
|
|
1261
|
+
termIndexSelectorMap.delete(atom2);
|
|
1262
|
+
});
|
|
1263
|
+
addedAtoms.forEach((atom2) => {
|
|
1264
|
+
termIndexSelectorSet.add(atom2);
|
|
1265
|
+
termIndexSelectorMap.set(atom2, selector((get2) => callback(get2(atom2), term), {
|
|
1266
|
+
name: `index:callback:selector:${atom2.name}`
|
|
1267
|
+
}));
|
|
1268
|
+
});
|
|
1269
|
+
return new Set(termIndexSelectorSet);
|
|
1270
|
+
} else {
|
|
1271
|
+
return termIndexSelectorSet;
|
|
1272
|
+
}
|
|
1273
|
+
}, { name: `index:${options?.name}(${termKey})` });
|
|
1274
|
+
const filteredSelector = selector((get) => {
|
|
1275
|
+
const set = get(termIndexSelector);
|
|
1276
|
+
const res = [];
|
|
1277
|
+
set.forEach((atom2) => {
|
|
1278
|
+
if (get(termIndexSelectorMap.get(atom2))) {
|
|
1279
|
+
res.push(atom2);
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
return res;
|
|
1283
|
+
}, {
|
|
1284
|
+
name: `index:${options?.name}:${termKey}:termSelector`
|
|
1285
|
+
});
|
|
1286
|
+
map.set(termKey, filteredSelector);
|
|
1287
|
+
return filteredSelector;
|
|
1288
|
+
};
|
|
1289
|
+
return Object.assign(index2, {
|
|
1290
|
+
map,
|
|
1291
|
+
callback
|
|
1292
|
+
});
|
|
1293
|
+
};
|
|
574
1294
|
// src/selectorFamily.ts
|
|
575
|
-
var
|
|
1295
|
+
var createOptions2 = (options = {}, family, familyArgs, familyArgsStringified) => {
|
|
1296
|
+
if (options.name) {
|
|
1297
|
+
return {
|
|
1298
|
+
equal,
|
|
1299
|
+
...options,
|
|
1300
|
+
name: options?.name + "_" + familyArgsStringified,
|
|
1301
|
+
family,
|
|
1302
|
+
familyArgs,
|
|
1303
|
+
familyArgsStringified
|
|
1304
|
+
};
|
|
1305
|
+
} else {
|
|
1306
|
+
return { equal, ...options, family, familyArgs, familyArgsStringified };
|
|
1307
|
+
}
|
|
1308
|
+
};
|
|
1309
|
+
var selectorFamily = (callback, options) => {
|
|
576
1310
|
const map = new Map;
|
|
577
|
-
const selectorFamily2 = (
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
throw e;
|
|
584
|
-
}
|
|
585
|
-
if (map.has(keyStringified))
|
|
586
|
-
return map.get(keyStringified);
|
|
587
|
-
const selectorDebugLabel = debugLabel ? debugLabel + "_" + keyStringified : undefined;
|
|
588
|
-
const newSelector = selector((selectorArgs) => get(key)(selectorArgs), selectorDebugLabel);
|
|
589
|
-
newSelector.family = selectorFamily2;
|
|
590
|
-
map.set(keyStringified, newSelector);
|
|
1311
|
+
const selectorFamily2 = (...args) => {
|
|
1312
|
+
const argsStringified = stringifyFamilyArgs(args);
|
|
1313
|
+
if (map.has(argsStringified))
|
|
1314
|
+
return map.get(argsStringified);
|
|
1315
|
+
const newSelector = selector((selectorArgs) => callback(...args)(selectorArgs), createOptions2(options, selectorFamily2, args, argsStringified));
|
|
1316
|
+
map.set(argsStringified, newSelector);
|
|
591
1317
|
return newSelector;
|
|
592
1318
|
};
|
|
593
|
-
selectorFamily2.
|
|
1319
|
+
selectorFamily2.__valdresSelectorFamilyMap = map;
|
|
1320
|
+
if (options?.name)
|
|
1321
|
+
Object.defineProperty(selectorFamily2, "name", {
|
|
1322
|
+
value: options.name,
|
|
1323
|
+
writable: false
|
|
1324
|
+
});
|
|
594
1325
|
return selectorFamily2;
|
|
595
1326
|
};
|
|
1327
|
+
// src/utils/isFamilySelector.ts
|
|
1328
|
+
var isFamilySelector = (state) => isFamilyState(state) && isSelector(state);
|
|
1329
|
+
|
|
1330
|
+
// src/index.ts
|
|
1331
|
+
if (globalThis.__valdres__) {
|
|
1332
|
+
throw new Error(`Error! An instance of valdres is already loaded. Loaded: ${globalThis.__valdres__}. Attempted to load: ${version}`);
|
|
1333
|
+
} else {
|
|
1334
|
+
globalThis.__valdres__ = version;
|
|
1335
|
+
}
|
|
596
1336
|
export {
|
|
1337
|
+
store,
|
|
597
1338
|
selectorFamily,
|
|
598
1339
|
selector,
|
|
599
|
-
|
|
1340
|
+
isSelectorFamily,
|
|
600
1341
|
isSelector,
|
|
601
1342
|
isPromiseLike,
|
|
1343
|
+
isFamilyState,
|
|
1344
|
+
isFamilySelector,
|
|
1345
|
+
isFamilyAtom,
|
|
602
1346
|
isFamily,
|
|
1347
|
+
isAtomFamily,
|
|
603
1348
|
isAtom,
|
|
604
|
-
|
|
1349
|
+
index,
|
|
1350
|
+
globalStore,
|
|
1351
|
+
deepFreeze,
|
|
605
1352
|
createStoreWithSelectorSet,
|
|
606
|
-
createStore,
|
|
607
1353
|
atomFamily,
|
|
608
1354
|
atom
|
|
609
1355
|
};
|