valdres 0.2.0-alpha.4 → 0.2.0-alpha.40
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 +687 -275
- package/package.json +12 -10
- package/dist/index.d.ts +0 -19
- package/dist/src/atom.d.ts +0 -9
- 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 -3
- 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/resetAtom.d.ts +0 -3
- package/dist/src/lib/setAtom.d.ts +0 -3
- package/dist/src/lib/setAtoms.d.ts +0 -3
- package/dist/src/lib/stableStringify.d.ts +0 -1
- package/dist/src/lib/storeFromStoreData.d.ts +0 -3
- package/dist/src/lib/subscribe.d.ts +0 -4
- package/dist/src/lib/transaction.d.ts +0 -8
- package/dist/src/lib/unsubscribe.d.ts +0 -3
- 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 -10
- 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 -2
- package/dist/src/types/ResetAtom.d.ts +0 -2
- package/dist/src/types/Selector.d.ts +0 -8
- package/dist/src/types/SelectorFamily.d.ts +0 -5
- package/dist/src/types/SetAtom.d.ts +0 -2
- 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/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/isPromiseLike.d.ts +0 -1
- package/dist/src/utils/isSelector.d.ts +0 -2
package/dist/index.js
CHANGED
|
@@ -1,108 +1,102 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
case "undefined":
|
|
22
|
-
return "";
|
|
23
|
-
case "boolean":
|
|
24
|
-
return x ? "true" : "false";
|
|
25
|
-
case "number":
|
|
26
|
-
case "symbol":
|
|
27
|
-
return String(x);
|
|
28
|
-
case "string":
|
|
29
|
-
return JSON.stringify(x);
|
|
30
|
-
case "function":
|
|
31
|
-
return `__FUNCTION(${x.toString()})__`;
|
|
32
|
-
}
|
|
33
|
-
if (x === null) {
|
|
34
|
-
return "null";
|
|
35
|
-
}
|
|
36
|
-
if (typeof x !== "object") {
|
|
37
|
-
return JSON.stringify(x) ?? "";
|
|
38
|
-
}
|
|
39
|
-
if (isPromiseLike(x)) {
|
|
40
|
-
return "__PROMISE__";
|
|
41
|
-
}
|
|
42
|
-
if (Array.isArray(x)) {
|
|
43
|
-
return `[${x.map((v, i) => stableStringifyRecurse(v, i.toString()))}]`;
|
|
44
|
-
}
|
|
45
|
-
if (typeof x.toJSON === "function") {
|
|
46
|
-
return stableStringifyRecurse(x.toJSON(key), key);
|
|
47
|
-
}
|
|
48
|
-
if (x instanceof Map) {
|
|
49
|
-
const obj = {};
|
|
50
|
-
for (const [k, v] of x) {
|
|
51
|
-
obj[typeof k === "string" ? k : stringify(k, opt)] = v;
|
|
1
|
+
// src/lib/equal.ts
|
|
2
|
+
var hasElementType = typeof Element !== "undefined";
|
|
3
|
+
var hasMap = typeof Map === "function";
|
|
4
|
+
var hasSet = typeof Set === "function";
|
|
5
|
+
var hasArrayBuffer = typeof ArrayBuffer === "function" && !!ArrayBuffer.isView;
|
|
6
|
+
var deepEqualFn = (a, b) => {
|
|
7
|
+
if (a === b)
|
|
8
|
+
return true;
|
|
9
|
+
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
10
|
+
if (a.constructor !== b.constructor)
|
|
11
|
+
return false;
|
|
12
|
+
var length, i, keys;
|
|
13
|
+
if (Array.isArray(a)) {
|
|
14
|
+
length = a.length;
|
|
15
|
+
if (length != b.length)
|
|
16
|
+
return false;
|
|
17
|
+
for (i = length;i-- !== 0; )
|
|
18
|
+
if (!deepEqualFn(a[i], b[i]))
|
|
19
|
+
return false;
|
|
20
|
+
return true;
|
|
52
21
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
22
|
+
var it;
|
|
23
|
+
if (hasMap && a instanceof Map && b instanceof Map) {
|
|
24
|
+
if (a.size !== b.size)
|
|
25
|
+
return false;
|
|
26
|
+
it = a.entries();
|
|
27
|
+
while (!(i = it.next()).done)
|
|
28
|
+
if (!b.has(i.value[0]))
|
|
29
|
+
return false;
|
|
30
|
+
it = a.entries();
|
|
31
|
+
while (!(i = it.next()).done)
|
|
32
|
+
if (!deepEqualFn(i.value[1], b.get(i.value[0])))
|
|
33
|
+
return false;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (hasSet && a instanceof Set && b instanceof Set) {
|
|
37
|
+
if (a.size !== b.size)
|
|
38
|
+
return false;
|
|
39
|
+
it = a.entries();
|
|
40
|
+
while (!(i = it.next()).done)
|
|
41
|
+
if (!b.has(i.value[0]))
|
|
42
|
+
return false;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (hasArrayBuffer && ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
46
|
+
length = a.length;
|
|
47
|
+
if (length != b.length)
|
|
48
|
+
return false;
|
|
49
|
+
for (i = length;i-- !== 0; )
|
|
50
|
+
if (a[i] !== b[i])
|
|
51
|
+
return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (a.constructor === RegExp)
|
|
55
|
+
return a.source === b.source && a.flags === b.flags;
|
|
56
|
+
if (a.valueOf !== Object.prototype.valueOf && typeof a.valueOf === "function" && typeof b.valueOf === "function")
|
|
57
|
+
return a.valueOf() === b.valueOf();
|
|
58
|
+
if (a.toString !== Object.prototype.toString && typeof a.toString === "function" && typeof b.toString === "function")
|
|
59
|
+
return a.toString() === b.toString();
|
|
60
|
+
keys = Object.keys(a);
|
|
61
|
+
length = keys.length;
|
|
62
|
+
if (length !== Object.keys(b).length)
|
|
63
|
+
return false;
|
|
64
|
+
for (i = length;i-- !== 0; )
|
|
65
|
+
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
|
|
66
|
+
return false;
|
|
67
|
+
if (hasElementType && a instanceof Element)
|
|
68
|
+
return false;
|
|
69
|
+
for (i = length;i-- !== 0; ) {
|
|
70
|
+
if ((keys[i] === "_owner" || keys[i] === "__v" || keys[i] === "__o") && a.$$typeof) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!deepEqualFn(a[keys[i]], b[keys[i]]))
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
60
77
|
}
|
|
61
|
-
return
|
|
78
|
+
return a !== a && b !== b;
|
|
62
79
|
};
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var atomFamily = (defaultValue, debugLabel) => {
|
|
71
|
-
const map = new Map;
|
|
72
|
-
const atomFamily2 = (key, defaultOverride) => {
|
|
73
|
-
const keyStringified = stableStringify(key);
|
|
74
|
-
if (map.has(keyStringified)) {
|
|
75
|
-
return map.get(keyStringified);
|
|
80
|
+
var equal = (a, b) => {
|
|
81
|
+
try {
|
|
82
|
+
return deepEqualFn(a, b);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
if ((error.message || "").match(/stack|recursion/i)) {
|
|
85
|
+
console.warn("react-fast-compare cannot handle circular refs");
|
|
86
|
+
return false;
|
|
76
87
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
label: atomDebugLabel
|
|
80
|
-
});
|
|
81
|
-
newAtom.family = atomFamily2;
|
|
82
|
-
newAtom.familyKey = Object.freeze(key);
|
|
83
|
-
map.set(keyStringified, newAtom);
|
|
84
|
-
return newAtom;
|
|
85
|
-
};
|
|
86
|
-
atomFamily2._map = map;
|
|
87
|
-
return atomFamily2;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
88
90
|
};
|
|
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
91
|
|
|
101
92
|
// src/utils/isAtom.ts
|
|
102
93
|
var isAtom = (state) => Object.hasOwn(state, "defaultValue");
|
|
103
94
|
|
|
104
|
-
// src/utils/
|
|
105
|
-
var
|
|
95
|
+
// src/utils/isFamilyState.ts
|
|
96
|
+
var isFamilyState = (state) => state && Object.hasOwn(state, "family");
|
|
97
|
+
|
|
98
|
+
// src/utils/isFamilyAtom.ts
|
|
99
|
+
var isFamilyAtom = (state) => isFamilyState(state) && isAtom(state);
|
|
106
100
|
|
|
107
101
|
// src/lib/updateStateSubscribers.ts
|
|
108
102
|
var updateStateSubscribers = (state, data) => {
|
|
@@ -112,7 +106,7 @@ var updateStateSubscribers = (state, data) => {
|
|
|
112
106
|
subscribtion.callback();
|
|
113
107
|
}
|
|
114
108
|
}
|
|
115
|
-
if (state
|
|
109
|
+
if (isFamilyState(state)) {
|
|
116
110
|
const familySubscriptions = data.subscriptions.get(state.family);
|
|
117
111
|
if (familySubscriptions?.size) {
|
|
118
112
|
for (const subscribtion of familySubscriptions) {
|
|
@@ -122,11 +116,119 @@ var updateStateSubscribers = (state, data) => {
|
|
|
122
116
|
}
|
|
123
117
|
};
|
|
124
118
|
|
|
125
|
-
// src/
|
|
126
|
-
|
|
119
|
+
// src/utils/isPromiseLike.ts
|
|
120
|
+
var isPromiseLike = (object) => {
|
|
121
|
+
return object && object.then && typeof object.then === "function";
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// src/utils/isAtomFamily.ts
|
|
125
|
+
var isAtomFamily = (state) => state && Object.hasOwn(state, "__valdresAtomFamilyMap");
|
|
126
|
+
|
|
127
|
+
// src/utils/isSelector.ts
|
|
128
|
+
var isSelector = (state) => state && Object.hasOwn(state, "get");
|
|
129
|
+
|
|
130
|
+
// src/utils/isSelectorFamily.ts
|
|
131
|
+
var isSelectorFamily = (state) => state && Object.hasOwn(state, "__valdresSelectorFamilyMap");
|
|
132
|
+
|
|
133
|
+
// src/lib/setAtom.ts
|
|
134
|
+
var setAtom = (atom, newValue, data, skipOnSet = false) => {
|
|
135
|
+
const currentValue = getState2(atom, data);
|
|
136
|
+
if (typeof newValue === "function") {
|
|
137
|
+
newValue = newValue(currentValue);
|
|
138
|
+
if (isPromiseLike(newValue) || isPromiseLike(currentValue))
|
|
139
|
+
throw new Error("Todo, how should we handle this?");
|
|
140
|
+
}
|
|
141
|
+
if (atom.equal(currentValue, newValue))
|
|
142
|
+
return;
|
|
143
|
+
data.values.set(atom, newValue);
|
|
144
|
+
if (atom.onSet && !skipOnSet)
|
|
145
|
+
atom.onSet(newValue, data);
|
|
146
|
+
if (currentValue?.__isEmptyAtomPromise__) {
|
|
147
|
+
currentValue.__resolveEmptyAtomPromise__(newValue);
|
|
148
|
+
}
|
|
149
|
+
propagateUpdatedAtoms2([atom], data);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// src/lib/initAtom.ts
|
|
153
|
+
var getAtomInitValue = (atom, data) => {
|
|
154
|
+
if (atom.defaultValue === undefined) {
|
|
155
|
+
let promiseResolve;
|
|
156
|
+
const promise = new Promise((resolve) => {
|
|
157
|
+
promiseResolve = resolve;
|
|
158
|
+
});
|
|
159
|
+
promise.__isEmptyAtomPromise__ = true;
|
|
160
|
+
promise.__resolveEmptyAtomPromise__ = promiseResolve;
|
|
161
|
+
return promise;
|
|
162
|
+
} else if (typeof atom.defaultValue === "function") {
|
|
163
|
+
const value = atom.defaultValue();
|
|
164
|
+
if (isPromiseLike(value)) {
|
|
165
|
+
value.then((resolvedValue) => {
|
|
166
|
+
data.values.set(atom, resolvedValue);
|
|
167
|
+
propagateUpdatedAtoms2([atom], data);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return value;
|
|
171
|
+
} else if (isSelector(atom.defaultValue)) {
|
|
172
|
+
return getState2(atom.defaultValue, data);
|
|
173
|
+
} else {
|
|
174
|
+
return atom.defaultValue;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
var initAtom = (atom, data) => {
|
|
178
|
+
let value = getAtomInitValue(atom, data);
|
|
179
|
+
data.values.set(atom, value);
|
|
180
|
+
if (isFamilyAtom(atom)) {
|
|
181
|
+
const currentKeySet = getState2(atom.family.__keysAtom, data);
|
|
182
|
+
if (!currentKeySet.has(atom.familyKey)) {
|
|
183
|
+
const newSet = new Set(currentKeySet);
|
|
184
|
+
newSet.add(atom.familyKey);
|
|
185
|
+
setAtom(atom.family.__keysAtom, newSet, data);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (atom.onInit)
|
|
189
|
+
atom.onInit((newVal) => {
|
|
190
|
+
value = newVal;
|
|
191
|
+
setAtom(atom, newVal, data, true);
|
|
192
|
+
}, data);
|
|
193
|
+
return value;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/lib/getState.ts
|
|
197
|
+
function getState2(state, data) {
|
|
198
|
+
if (data.values.has(state))
|
|
199
|
+
return data.values.get(state);
|
|
200
|
+
if (isAtom(state)) {
|
|
201
|
+
if ("parent" in data)
|
|
202
|
+
return getState2(state, data.parent);
|
|
203
|
+
return initAtom(state, data);
|
|
204
|
+
}
|
|
205
|
+
if (isSelector(state))
|
|
206
|
+
return initSelector2(state, data);
|
|
207
|
+
if (isAtomFamily(state)) {
|
|
208
|
+
if ("parent" in data) {
|
|
209
|
+
const closestData = findClosestStoreWithAtomInitialized(state.__keysAtom, data);
|
|
210
|
+
return getState2(state.__keysSelector, closestData);
|
|
211
|
+
}
|
|
212
|
+
return getState2(state.__keysSelector, data);
|
|
213
|
+
}
|
|
214
|
+
if (isSelectorFamily(state)) {
|
|
215
|
+
const array = Array.from(state.__valdresSelectorFamilyMap.keys());
|
|
216
|
+
if (equal(array, state._keyArray))
|
|
217
|
+
return state._keyArray;
|
|
218
|
+
state._keyArray = array;
|
|
219
|
+
return array;
|
|
220
|
+
}
|
|
221
|
+
throw new Error("Invalid object passed to get");
|
|
222
|
+
}
|
|
223
|
+
var findClosestStoreWithAtomInitialized = (atom, data) => {
|
|
224
|
+
if ("parent" in data === false)
|
|
225
|
+
return data;
|
|
226
|
+
if (data.values.has(atom))
|
|
227
|
+
return data;
|
|
228
|
+
return findClosestStoreWithAtomInitialized(atom, data.parent);
|
|
229
|
+
};
|
|
127
230
|
|
|
128
231
|
// src/lib/initSelector.ts
|
|
129
|
-
import equal from "fast-deep-equal";
|
|
130
232
|
class SuspendAndWaitForResolveError extends Error {
|
|
131
233
|
promise;
|
|
132
234
|
constructor(promise) {
|
|
@@ -143,7 +245,6 @@ var getOrInitConsumersSet = (state, data) => {
|
|
|
143
245
|
return newSet;
|
|
144
246
|
};
|
|
145
247
|
var evaluateSelector = (selector, data) => {
|
|
146
|
-
const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
|
|
147
248
|
const updatedDependencies = new Set;
|
|
148
249
|
let result;
|
|
149
250
|
try {
|
|
@@ -153,7 +254,7 @@ var evaluateSelector = (selector, data) => {
|
|
|
153
254
|
if (isPromiseLike(value))
|
|
154
255
|
throw new SuspendAndWaitForResolveError(value);
|
|
155
256
|
return value;
|
|
156
|
-
});
|
|
257
|
+
}, data.id);
|
|
157
258
|
} catch (error) {
|
|
158
259
|
if (error instanceof SuspendAndWaitForResolveError) {
|
|
159
260
|
result = error;
|
|
@@ -161,6 +262,7 @@ var evaluateSelector = (selector, data) => {
|
|
|
161
262
|
throw error;
|
|
162
263
|
}
|
|
163
264
|
}
|
|
265
|
+
const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
|
|
164
266
|
const added = updatedDependencies?.difference(currentDependencies);
|
|
165
267
|
const removed = currentDependencies?.difference(updatedDependencies);
|
|
166
268
|
for (const state of added) {
|
|
@@ -176,25 +278,25 @@ var evaluateSelector = (selector, data) => {
|
|
|
176
278
|
};
|
|
177
279
|
var handleSelectorResult = (value, selector, data) => {
|
|
178
280
|
if (value instanceof SuspendAndWaitForResolveError) {
|
|
179
|
-
value.promise.then(() =>
|
|
281
|
+
value.promise.then(() => initSelector2(selector, data));
|
|
180
282
|
return value.promise;
|
|
181
283
|
} else if (isPromiseLike(value)) {
|
|
182
284
|
value.then((resolved) => {
|
|
183
285
|
data.values.set(selector, resolved);
|
|
184
286
|
updateStateSubscribers(selector, data);
|
|
185
|
-
console.log(
|
|
287
|
+
console.log("Should we reEvaluate?");
|
|
186
288
|
});
|
|
187
289
|
return value;
|
|
188
290
|
} else {
|
|
189
291
|
return value;
|
|
190
292
|
}
|
|
191
293
|
};
|
|
192
|
-
var
|
|
294
|
+
var initSelector2 = (selector, data) => {
|
|
193
295
|
const tmpValue = evaluateSelector(selector, data);
|
|
194
296
|
const value = handleSelectorResult(tmpValue, selector, data);
|
|
195
297
|
if (data.expiredValues.has(selector)) {
|
|
196
298
|
const expiredValue = data.expiredValues.get(selector);
|
|
197
|
-
if (equal(expiredValue, value)) {
|
|
299
|
+
if (selector.equal(expiredValue, value)) {
|
|
198
300
|
data.values.set(selector, expiredValue);
|
|
199
301
|
return expiredValue;
|
|
200
302
|
}
|
|
@@ -209,11 +311,11 @@ var updateSelectorSubscribers = (selector, data) => {
|
|
|
209
311
|
const familySubscriptions = selector.family && data.subscriptions.get(selector.family);
|
|
210
312
|
if (!subscribtions?.size && !familySubscriptions?.size)
|
|
211
313
|
return;
|
|
212
|
-
if (subscribtions?.size && data.subscriptionsRequireEqualCheck.get(selector) || familySubscriptions?.size && data.subscriptionsRequireEqualCheck.get(selector.family)) {
|
|
314
|
+
if (subscribtions?.size && data.subscriptionsRequireEqualCheck.get(selector) || familySubscriptions?.size && selector.family && data.subscriptionsRequireEqualCheck.get(selector.family)) {
|
|
213
315
|
try {
|
|
214
316
|
const oldValue = data.expiredValues.get(selector);
|
|
215
|
-
const newValue =
|
|
216
|
-
if (
|
|
317
|
+
const newValue = initSelector2(selector, data);
|
|
318
|
+
if (selector.equal(newValue, oldValue))
|
|
217
319
|
return;
|
|
218
320
|
} catch (e) {
|
|
219
321
|
}
|
|
@@ -244,15 +346,15 @@ var recursivlyResetSelectorTree = (selectors, data, clearedSelectors) => {
|
|
|
244
346
|
}
|
|
245
347
|
}
|
|
246
348
|
};
|
|
247
|
-
var
|
|
349
|
+
var propagateUpdatedAtoms2 = (atoms, data) => {
|
|
248
350
|
const clearedSelectors = new Set;
|
|
249
|
-
for (const
|
|
250
|
-
const consumers = data.stateConsumers.get(
|
|
351
|
+
for (const atom of atoms) {
|
|
352
|
+
const consumers = data.stateConsumers.get(atom);
|
|
251
353
|
if (consumers && consumers.size) {
|
|
252
354
|
recursivlyResetSelectorTree(consumers, data, clearedSelectors);
|
|
253
355
|
}
|
|
254
|
-
if (
|
|
255
|
-
const consumersFamily = data.stateConsumers.get(
|
|
356
|
+
if (isFamilyAtom(atom)) {
|
|
357
|
+
const consumersFamily = data.stateConsumers.get(atom.family);
|
|
256
358
|
if (consumersFamily?.size) {
|
|
257
359
|
recursivlyResetSelectorTree(consumersFamily, data, clearedSelectors);
|
|
258
360
|
}
|
|
@@ -261,94 +363,52 @@ var propagateUpdatedAtoms = (atoms, data) => {
|
|
|
261
363
|
for (const selector of clearedSelectors) {
|
|
262
364
|
updateSelectorSubscribers(selector, data);
|
|
263
365
|
}
|
|
264
|
-
for (const
|
|
265
|
-
updateStateSubscribers(
|
|
366
|
+
for (const atom of atoms) {
|
|
367
|
+
updateStateSubscribers(atom, data);
|
|
266
368
|
}
|
|
267
369
|
};
|
|
268
370
|
|
|
269
|
-
// src/lib/
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return;
|
|
280
|
-
data.values.set(atom3, newValue);
|
|
281
|
-
if (currentValue?.__isEmptyAtomPromise__) {
|
|
282
|
-
currentValue.__resolveEmptyAtomPromise__(newValue);
|
|
371
|
+
// src/lib/createStoreData.ts
|
|
372
|
+
function createStoreData(id, parent) {
|
|
373
|
+
if (parent) {
|
|
374
|
+
return {
|
|
375
|
+
...generateStoreData(id),
|
|
376
|
+
parent,
|
|
377
|
+
scopeConsumers: parent ? new Set : undefined
|
|
378
|
+
};
|
|
379
|
+
} else {
|
|
380
|
+
return generateStoreData(id);
|
|
283
381
|
}
|
|
284
|
-
|
|
382
|
+
}
|
|
383
|
+
var generateId = () => (Math.random() + 1).toString(36).substring(7);
|
|
384
|
+
var generateStoreData = (id = generateId()) => {
|
|
385
|
+
return {
|
|
386
|
+
id,
|
|
387
|
+
values: new WeakMap,
|
|
388
|
+
expiredValues: new WeakMap,
|
|
389
|
+
subscriptions: new WeakMap,
|
|
390
|
+
subscriptionsRequireEqualCheck: new WeakMap,
|
|
391
|
+
stateConsumers: new WeakMap,
|
|
392
|
+
stateDependencies: new WeakMap,
|
|
393
|
+
scopes: {}
|
|
394
|
+
};
|
|
285
395
|
};
|
|
286
396
|
|
|
287
|
-
// src/lib/
|
|
288
|
-
var
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
});
|
|
294
|
-
promise.__isEmptyAtomPromise__ = true;
|
|
295
|
-
promise.__resolveEmptyAtomPromise__ = promiseResolve;
|
|
296
|
-
return promise;
|
|
297
|
-
} else if (typeof atom3.defaultValue === "function") {
|
|
298
|
-
const value = atom3.defaultValue();
|
|
299
|
-
if (isPromiseLike(value)) {
|
|
300
|
-
value.then((resolvedValue) => {
|
|
301
|
-
data.values.set(atom3, resolvedValue);
|
|
302
|
-
propagateUpdatedAtoms([atom3], data);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
return value;
|
|
306
|
-
} else {
|
|
307
|
-
return atom3.defaultValue;
|
|
397
|
+
// src/lib/resetAtom.ts
|
|
398
|
+
var resetAtom = (atom, data) => {
|
|
399
|
+
let value = getAtomInitValue(atom, data);
|
|
400
|
+
data.values.set(atom, value);
|
|
401
|
+
if (!isPromiseLike(value)) {
|
|
402
|
+
propagateUpdatedAtoms2([atom], data);
|
|
308
403
|
}
|
|
309
|
-
};
|
|
310
|
-
var initAtom = (atom3, data) => {
|
|
311
|
-
const value = getAtomInitValue(atom3, data);
|
|
312
|
-
data.values.set(atom3, value);
|
|
313
|
-
if (atom3.onInit)
|
|
314
|
-
atom3.onInit((newVal) => {
|
|
315
|
-
setAtom(atom3, newVal, data);
|
|
316
|
-
});
|
|
317
404
|
return value;
|
|
318
405
|
};
|
|
319
406
|
|
|
320
407
|
// src/utils/isFamily.ts
|
|
321
|
-
var isFamily = (state) =>
|
|
322
|
-
|
|
323
|
-
// src/lib/getState.ts
|
|
324
|
-
var getState2 = (state, data) => {
|
|
325
|
-
if (data.values.has(state))
|
|
326
|
-
return data.values.get(state);
|
|
327
|
-
if (isAtom(state))
|
|
328
|
-
return initAtom(state, data);
|
|
329
|
-
if (isSelector(state))
|
|
330
|
-
return initSelector(state, data);
|
|
331
|
-
if (isFamily(state)) {
|
|
332
|
-
const res = [];
|
|
333
|
-
for (const atom3 of state._map.values()) {
|
|
334
|
-
res.push([atom3.familyKey, getState2(atom3, data)]);
|
|
335
|
-
}
|
|
336
|
-
return res;
|
|
337
|
-
}
|
|
338
|
-
throw new Error("Invalid object passed to get");
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
// src/lib/resetAtom.ts
|
|
342
|
-
var resetAtom = (atom3, data) => {
|
|
343
|
-
const res = initAtom(atom3, data);
|
|
344
|
-
if (!isPromiseLike(res)) {
|
|
345
|
-
propagateUpdatedAtoms([atom3], data);
|
|
346
|
-
}
|
|
347
|
-
return res;
|
|
348
|
-
};
|
|
408
|
+
var isFamily = (state) => isAtomFamily(state) || isSelectorFamily(state);
|
|
349
409
|
|
|
350
410
|
// src/lib/unsubscribe.ts
|
|
351
|
-
var unsubscribe = (state, subscription, data, mount) => {
|
|
411
|
+
var unsubscribe = (state, subscription, data, mount, maxAgeCleanup) => {
|
|
352
412
|
const subscribers = data.subscriptions.get(state);
|
|
353
413
|
if (subscribers) {
|
|
354
414
|
subscribers.delete(subscription);
|
|
@@ -364,10 +424,15 @@ var unsubscribe = (state, subscription, data, mount) => {
|
|
|
364
424
|
data.subscriptionsRequireEqualCheck.delete(state);
|
|
365
425
|
}
|
|
366
426
|
}
|
|
427
|
+
if (subscribers.size === 0) {
|
|
428
|
+
if (maxAgeCleanup)
|
|
429
|
+
maxAgeCleanup();
|
|
430
|
+
data.subscriptions.delete(state);
|
|
431
|
+
}
|
|
367
432
|
if (mount) {
|
|
368
433
|
if (subscribers.size === mount.mountSubscriptions.size) {
|
|
369
|
-
if (
|
|
370
|
-
|
|
434
|
+
if (typeof mount.onUnmount === "function") {
|
|
435
|
+
mount.onUnmount();
|
|
371
436
|
}
|
|
372
437
|
}
|
|
373
438
|
}
|
|
@@ -381,10 +446,24 @@ var initSubscribers = (state, data) => {
|
|
|
381
446
|
return set;
|
|
382
447
|
};
|
|
383
448
|
var subscribe = (state, callback, requireDeepEqualCheckBeforeCallback, data) => {
|
|
384
|
-
|
|
449
|
+
let parentUnsubscribe;
|
|
450
|
+
if ("parent" in data && !data.values.has(state) && isAtom(state)) {
|
|
451
|
+
const originalCallback = callback;
|
|
452
|
+
parentUnsubscribe = subscribe(state, originalCallback, requireDeepEqualCheckBeforeCallback, data.parent);
|
|
453
|
+
callback = () => {
|
|
454
|
+
if (parentUnsubscribe) {
|
|
455
|
+
parentUnsubscribe();
|
|
456
|
+
parentUnsubscribe = undefined;
|
|
457
|
+
}
|
|
458
|
+
originalCallback();
|
|
459
|
+
};
|
|
460
|
+
} else if (!data.values.has(state) && isAtom(state)) {
|
|
461
|
+
initAtom(state, data);
|
|
462
|
+
}
|
|
385
463
|
if (isSelector(state) && !data.values.has(state)) {
|
|
386
|
-
|
|
464
|
+
initSelector2(state, data);
|
|
387
465
|
}
|
|
466
|
+
const subscribers = data.subscriptions.get(state) || initSubscribers(state, data);
|
|
388
467
|
let subscription;
|
|
389
468
|
if (isFamily(state)) {
|
|
390
469
|
subscription = {
|
|
@@ -400,37 +479,70 @@ var subscribe = (state, callback, requireDeepEqualCheckBeforeCallback, data) =>
|
|
|
400
479
|
}
|
|
401
480
|
subscribers.add(subscription);
|
|
402
481
|
let mount;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
482
|
+
let maxAgeCleanup;
|
|
483
|
+
if (subscribers.size === 1) {
|
|
484
|
+
if (isAtom(state) && state.maxAge) {
|
|
485
|
+
let timeout;
|
|
486
|
+
const interval = setInterval(() => {
|
|
487
|
+
let value = getAtomInitValue(state, data);
|
|
488
|
+
if (isPromiseLike(value)) {
|
|
489
|
+
if (state.staleWhileRevalidate) {
|
|
490
|
+
const oldValue = data.values.get(state);
|
|
491
|
+
timeout = setTimeout(() => {
|
|
492
|
+
const nowValue = data.values.get(state);
|
|
493
|
+
console.log("todo", oldValue);
|
|
494
|
+
}, state.staleWhileRevalidate);
|
|
495
|
+
value.then((res) => clearTimeout(timeout));
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
data.values.set(state, value);
|
|
499
|
+
propagateUpdatedAtoms2([state], data);
|
|
500
|
+
}
|
|
501
|
+
}, state.maxAge);
|
|
502
|
+
maxAgeCleanup = () => {
|
|
503
|
+
clearInterval(interval);
|
|
504
|
+
if (timeout)
|
|
505
|
+
clearTimeout(timeout);
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
if (state.onMount) {
|
|
509
|
+
const store = storeFromStoreData2(data);
|
|
510
|
+
const mountSubscriptions = new Set;
|
|
511
|
+
const originalSub = store.sub;
|
|
512
|
+
store.sub = (state2, callback2) => {
|
|
513
|
+
mountSubscriptions.add(callback2);
|
|
514
|
+
return originalSub(state2, callback2);
|
|
515
|
+
};
|
|
516
|
+
mount = {
|
|
517
|
+
onUnmount: state.onMount(store, state),
|
|
518
|
+
mountSubscriptions
|
|
519
|
+
};
|
|
520
|
+
}
|
|
415
521
|
}
|
|
416
522
|
if (requireDeepEqualCheckBeforeCallback && data.subscriptionsRequireEqualCheck.get(state) !== true) {
|
|
417
523
|
data.subscriptionsRequireEqualCheck.set(state, true);
|
|
418
524
|
}
|
|
419
|
-
return () =>
|
|
525
|
+
return () => {
|
|
526
|
+
if (parentUnsubscribe) {
|
|
527
|
+
parentUnsubscribe();
|
|
528
|
+
}
|
|
529
|
+
unsubscribe(state, subscription, data, mount, maxAgeCleanup);
|
|
530
|
+
};
|
|
420
531
|
};
|
|
421
532
|
|
|
422
533
|
// src/lib/setAtoms.ts
|
|
423
|
-
import equal4 from "fast-deep-equal";
|
|
424
534
|
var setAtoms = (pairs, data) => {
|
|
425
535
|
const updatedAtoms = [];
|
|
426
|
-
for (let [
|
|
427
|
-
const currentValue = getState2(
|
|
428
|
-
if (!
|
|
429
|
-
updatedAtoms.push(
|
|
430
|
-
|
|
536
|
+
for (let [atom, value] of pairs) {
|
|
537
|
+
const currentValue = getState2(atom, data);
|
|
538
|
+
if (!atom.equal(currentValue, value)) {
|
|
539
|
+
updatedAtoms.push(atom);
|
|
540
|
+
if (atom.onSet)
|
|
541
|
+
atom.onSet(value, data);
|
|
542
|
+
data.values.set(atom, value);
|
|
431
543
|
}
|
|
432
544
|
}
|
|
433
|
-
|
|
545
|
+
propagateUpdatedAtoms2(updatedAtoms, data);
|
|
434
546
|
};
|
|
435
547
|
|
|
436
548
|
// src/lib/transaction.ts
|
|
@@ -446,41 +558,62 @@ var findDependencies = (state, data, result = new Set) => {
|
|
|
446
558
|
}
|
|
447
559
|
return result;
|
|
448
560
|
};
|
|
561
|
+
var recursivlyResetTxnSelectorCache = (state, txnSubscribers, txnSelectorCache) => {
|
|
562
|
+
for (const dep of txnSubscribers.get(state)) {
|
|
563
|
+
txnSelectorCache.delete(dep);
|
|
564
|
+
if (txnSubscribers.get(dep)?.size) {
|
|
565
|
+
recursivlyResetTxnSelectorCache(dep, txnSubscribers, txnSelectorCache);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
};
|
|
449
569
|
var transaction = (callback, data) => {
|
|
450
570
|
let txnAtomMap = new Map;
|
|
451
571
|
let txnSelectorCache = new Map;
|
|
572
|
+
let txnSubscribers = new Map;
|
|
452
573
|
let dirtySelectors = new Set;
|
|
453
574
|
const txnGet = (state) => {
|
|
454
575
|
if (isAtom(state)) {
|
|
455
576
|
return txnAtomMap.has(state) ? txnAtomMap.get(state) : getState2(state, data);
|
|
456
|
-
} else {
|
|
577
|
+
} else if (isSelector(state)) {
|
|
457
578
|
if (txnSelectorCache.has(state)) {
|
|
458
579
|
return txnSelectorCache.get(state);
|
|
459
|
-
} else if (dirtySelectors.has(state)) {
|
|
460
|
-
const res = state.get(txnGet);
|
|
461
|
-
txnSelectorCache.set(state, res);
|
|
462
|
-
return res;
|
|
463
|
-
} else {
|
|
464
|
-
return getState2(state, data);
|
|
465
580
|
}
|
|
581
|
+
const deps = new Set;
|
|
582
|
+
const res = state.get((s) => {
|
|
583
|
+
deps.add(s);
|
|
584
|
+
return txnGet(s);
|
|
585
|
+
}, data.id);
|
|
586
|
+
for (const dep of deps) {
|
|
587
|
+
if (!txnSubscribers.has(dep)) {
|
|
588
|
+
txnSubscribers.set(dep, new Set);
|
|
589
|
+
}
|
|
590
|
+
txnSubscribers.get(dep).add(state);
|
|
591
|
+
}
|
|
592
|
+
txnSelectorCache.set(state, res);
|
|
593
|
+
return res;
|
|
594
|
+
} else {
|
|
595
|
+
throw new Error("Unsupported state");
|
|
466
596
|
}
|
|
467
597
|
};
|
|
468
|
-
const txnSet = (
|
|
469
|
-
if (!isAtom(
|
|
598
|
+
const txnSet = (atom, value) => {
|
|
599
|
+
if (!isAtom(atom))
|
|
470
600
|
throw new Error("Not an atom");
|
|
471
601
|
if (typeof value === "function") {
|
|
472
|
-
const currentValue = txnGet(
|
|
602
|
+
const currentValue = txnGet(atom);
|
|
473
603
|
value = value(currentValue);
|
|
474
604
|
}
|
|
475
|
-
for (const selector of findDependencies(
|
|
605
|
+
for (const selector of findDependencies(atom, data)) {
|
|
476
606
|
dirtySelectors.add(selector);
|
|
477
607
|
txnSelectorCache.delete(selector);
|
|
478
608
|
}
|
|
479
|
-
|
|
609
|
+
if (txnSubscribers.get(atom)?.size) {
|
|
610
|
+
recursivlyResetTxnSelectorCache(atom, txnSubscribers, txnSelectorCache);
|
|
611
|
+
}
|
|
612
|
+
txnAtomMap.set(atom, value);
|
|
480
613
|
};
|
|
481
|
-
const txnReset = (
|
|
482
|
-
const value = getAtomInitValue(
|
|
483
|
-
txnAtomMap.set(
|
|
614
|
+
const txnReset = (atom) => {
|
|
615
|
+
const value = getAtomInitValue(atom, data);
|
|
616
|
+
txnAtomMap.set(atom, value);
|
|
484
617
|
return value;
|
|
485
618
|
};
|
|
486
619
|
const commit = () => {
|
|
@@ -493,84 +626,363 @@ var transaction = (callback, data) => {
|
|
|
493
626
|
};
|
|
494
627
|
|
|
495
628
|
// src/lib/storeFromStoreData.ts
|
|
496
|
-
|
|
629
|
+
function storeFromStoreData2(data, detach) {
|
|
497
630
|
const get = (state) => getState2(state, data);
|
|
498
631
|
const set = (state, value) => {
|
|
499
|
-
if (isAtom(state))
|
|
632
|
+
if (isAtom(state))
|
|
500
633
|
return setAtom(state, value, data);
|
|
634
|
+
if (isSelector(state))
|
|
635
|
+
throw new Error(SelectorProvidedToSetError);
|
|
636
|
+
throw new Error(InvalidStateSetError);
|
|
637
|
+
};
|
|
638
|
+
const reset = (atom) => resetAtom(atom, data);
|
|
639
|
+
const sub = (state, callback, deepEqualCheckBeforeCallback = true) => subscribe(state, callback, deepEqualCheckBeforeCallback, data);
|
|
640
|
+
const txn = (callback) => transaction(callback, data);
|
|
641
|
+
const scope = (scopeId) => {
|
|
642
|
+
let scopedStoreData;
|
|
643
|
+
if (scopeId in data.scopes) {
|
|
644
|
+
scopedStoreData = data.scopes[scopeId];
|
|
501
645
|
} else {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
646
|
+
scopedStoreData = createStoreData(scopeId, data);
|
|
647
|
+
data.scopes[scopeId] = scopedStoreData;
|
|
648
|
+
}
|
|
649
|
+
const detach2 = () => {
|
|
650
|
+
scopedStoreData.scopeConsumers.delete(detach2);
|
|
651
|
+
if (scopedStoreData.scopeConsumers.size === 0) {
|
|
652
|
+
delete data.scopes[scopeId];
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
scopedStoreData.scopeConsumers.add(detach2);
|
|
656
|
+
const newStore = storeFromStoreData2(data.scopes[scopeId], detach2);
|
|
657
|
+
return newStore;
|
|
658
|
+
};
|
|
659
|
+
if (detach) {
|
|
660
|
+
return {
|
|
661
|
+
get,
|
|
662
|
+
set,
|
|
663
|
+
sub,
|
|
664
|
+
txn,
|
|
665
|
+
reset,
|
|
666
|
+
data,
|
|
667
|
+
scope,
|
|
668
|
+
detach
|
|
669
|
+
};
|
|
670
|
+
} else {
|
|
671
|
+
return {
|
|
672
|
+
get,
|
|
673
|
+
set,
|
|
674
|
+
sub,
|
|
675
|
+
txn,
|
|
676
|
+
reset,
|
|
677
|
+
data,
|
|
678
|
+
scope
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
var SelectorProvidedToSetError = `Invalid state object passed to set().
|
|
683
|
+
You provided a \`selector\`.
|
|
684
|
+
Only \`atom\` cam be set.
|
|
685
|
+
`;
|
|
686
|
+
var InvalidStateSetError = `Invalid state object passed to set().
|
|
687
|
+
Only \`atom\` can be set.
|
|
688
|
+
`;
|
|
689
|
+
|
|
690
|
+
// src/store.ts
|
|
691
|
+
var store = (id) => {
|
|
692
|
+
const data = createStoreData(id);
|
|
693
|
+
return storeFromStoreData2(data);
|
|
694
|
+
};
|
|
695
|
+
// package.json
|
|
696
|
+
var version = "0.2.0-alpha.39";
|
|
697
|
+
|
|
698
|
+
// src/globalStore.ts
|
|
699
|
+
if (globalThis.__valdres__) {
|
|
700
|
+
throw new Error(`Error! An instance of valdres is already loaded`);
|
|
701
|
+
} else {
|
|
702
|
+
globalThis.__valdres__ = version;
|
|
703
|
+
}
|
|
704
|
+
var globalStore = Object.assign(store("valdres-global-store"), {
|
|
705
|
+
atoms: new Map,
|
|
706
|
+
atomFamilies: new Map
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// src/lib/globalAtom.ts
|
|
710
|
+
var globalAtom = (defaultValue, options) => {
|
|
711
|
+
const stores = new Set;
|
|
712
|
+
let value;
|
|
713
|
+
let initialized = false;
|
|
714
|
+
let onReset;
|
|
715
|
+
if (options.onSet)
|
|
716
|
+
throw new Error("onSet on globalAtom is currently not supported");
|
|
717
|
+
const onInit = (setSelf2, data) => {
|
|
718
|
+
setSelf2(globalStore.get(atom));
|
|
719
|
+
if (!initialized && options.onInit) {
|
|
720
|
+
onReset = options.onInit((newVal) => {
|
|
721
|
+
setSelf2(newVal);
|
|
722
|
+
value = newVal;
|
|
723
|
+
}, data);
|
|
724
|
+
initialized = true;
|
|
725
|
+
}
|
|
726
|
+
stores.add(data);
|
|
727
|
+
};
|
|
728
|
+
const onSet = (newValue, currentStore) => {
|
|
729
|
+
value = newValue;
|
|
730
|
+
if (stores.size > 1) {
|
|
731
|
+
for (const store3 of stores) {
|
|
732
|
+
if (store3.id !== currentStore.id) {
|
|
733
|
+
setAtom(atom, value, store3, true);
|
|
508
734
|
}
|
|
509
735
|
}
|
|
510
|
-
throw new Error("Invalid state object passed to set");
|
|
511
736
|
}
|
|
512
737
|
};
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
const
|
|
738
|
+
const getSelf = () => globalStore.get(atom);
|
|
739
|
+
const setSelf = (newValue) => globalStore.set(atom, newValue);
|
|
740
|
+
const resetSelf = () => {
|
|
741
|
+
value = undefined;
|
|
742
|
+
initialized = false;
|
|
743
|
+
for (const store3 of stores) {
|
|
744
|
+
if (store3.stateDependencies.has(atom)) {
|
|
745
|
+
throw new Error("TODO: Reset support for stateDependencies");
|
|
746
|
+
}
|
|
747
|
+
store3.values.delete(atom);
|
|
748
|
+
store3.expiredValues.delete(atom);
|
|
749
|
+
propagateUpdatedAtoms2([atom], store3);
|
|
750
|
+
stores.delete(store3);
|
|
751
|
+
onReset?.();
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
const atom = {
|
|
755
|
+
equal,
|
|
756
|
+
...options,
|
|
757
|
+
defaultValue,
|
|
758
|
+
name: options?.name,
|
|
759
|
+
onInit,
|
|
760
|
+
onSet,
|
|
761
|
+
setSelf,
|
|
762
|
+
getSelf,
|
|
763
|
+
resetSelf,
|
|
764
|
+
get stores() {
|
|
765
|
+
return stores;
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
return atom;
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
// src/atom.ts
|
|
772
|
+
function atom(defaultValue, options) {
|
|
773
|
+
if (!options)
|
|
774
|
+
return { equal, defaultValue };
|
|
775
|
+
if (options.global) {
|
|
776
|
+
return globalAtom(defaultValue, options);
|
|
777
|
+
}
|
|
516
778
|
return {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
779
|
+
equal,
|
|
780
|
+
defaultValue,
|
|
781
|
+
...options
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
// src/lib/atomFamilyAtom.ts
|
|
785
|
+
function atomFamilyAtom(defaultValue, options) {
|
|
786
|
+
if (options.global) {
|
|
787
|
+
return globalAtom(defaultValue, options);
|
|
788
|
+
}
|
|
789
|
+
return {
|
|
790
|
+
...options,
|
|
791
|
+
defaultValue
|
|
523
792
|
};
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// src/lib/stableStringify.ts
|
|
796
|
+
var stableStringifyRecurse = (x, key) => {
|
|
797
|
+
if (typeof x === "string" && !x.includes('"') && !x.includes("\\")) {
|
|
798
|
+
return `"${x}"`;
|
|
799
|
+
}
|
|
800
|
+
switch (typeof x) {
|
|
801
|
+
case "undefined":
|
|
802
|
+
return "";
|
|
803
|
+
case "boolean":
|
|
804
|
+
return x ? "true" : "false";
|
|
805
|
+
case "number":
|
|
806
|
+
case "symbol":
|
|
807
|
+
return String(x);
|
|
808
|
+
case "string":
|
|
809
|
+
return JSON.stringify(x);
|
|
810
|
+
case "function":
|
|
811
|
+
return `__FUNCTION(${x.toString()})__`;
|
|
812
|
+
}
|
|
813
|
+
if (x === null) {
|
|
814
|
+
return "null";
|
|
815
|
+
}
|
|
816
|
+
if (typeof x !== "object") {
|
|
817
|
+
return JSON.stringify(x) ?? "";
|
|
818
|
+
}
|
|
819
|
+
if (isPromiseLike(x)) {
|
|
820
|
+
return "__PROMISE__";
|
|
821
|
+
}
|
|
822
|
+
if (Array.isArray(x)) {
|
|
823
|
+
return `[${x.map((v, i) => stableStringifyRecurse(v, i.toString()))}]`;
|
|
824
|
+
}
|
|
825
|
+
if (typeof x.toJSON === "function") {
|
|
826
|
+
return stableStringifyRecurse(x.toJSON(key), key);
|
|
827
|
+
}
|
|
828
|
+
if (x instanceof Map) {
|
|
829
|
+
const obj = {};
|
|
830
|
+
for (const [k, v] of x) {
|
|
831
|
+
obj[typeof k === "string" ? k : stringify(k, opt)] = v;
|
|
832
|
+
}
|
|
833
|
+
return stableStringifyRecurse(obj, key);
|
|
834
|
+
}
|
|
835
|
+
if (x instanceof Set) {
|
|
836
|
+
return stableStringifyRecurse(Array.from(x).sort((a, b) => stableStringifyRecurse(a).localeCompare(stableStringifyRecurse(b))), key);
|
|
837
|
+
}
|
|
838
|
+
if (Symbol !== undefined && x[Symbol.iterator] != null && typeof x[Symbol.iterator] === "function") {
|
|
839
|
+
return stableStringifyRecurse(Array.from(x), key);
|
|
840
|
+
}
|
|
841
|
+
return `{${Object.keys(x).filter((k) => x[k] !== undefined).sort().map((k) => `${stableStringifyRecurse(k)}:${stableStringifyRecurse(x[k], k)}`).join(",")}}`;
|
|
842
|
+
};
|
|
843
|
+
var stableStringify = (x) => {
|
|
844
|
+
if (typeof x === "string" || typeof x === "boolean" || typeof x === "number")
|
|
845
|
+
return x;
|
|
846
|
+
return stableStringifyRecurse(x);
|
|
524
847
|
};
|
|
525
848
|
|
|
526
|
-
// src/
|
|
527
|
-
var
|
|
528
|
-
|
|
529
|
-
|
|
849
|
+
// src/selector.ts
|
|
850
|
+
var selector = (get, options) => {
|
|
851
|
+
if (!options)
|
|
852
|
+
return { equal, get };
|
|
853
|
+
return { equal, ...options, get };
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
// src/lib/createAtomFamily.ts
|
|
857
|
+
var createOptions = (options = {}, family, familyKey, keyStringified) => {
|
|
858
|
+
if (options.name) {
|
|
859
|
+
return {
|
|
860
|
+
equal,
|
|
861
|
+
...options,
|
|
862
|
+
name: options?.name + "_" + keyStringified,
|
|
863
|
+
family,
|
|
864
|
+
familyKey
|
|
865
|
+
};
|
|
866
|
+
} else {
|
|
867
|
+
return { equal, ...options, family, familyKey };
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
var handleDefaultValue = (defaultValue, key) => {
|
|
871
|
+
if (isSelectorFamily(defaultValue))
|
|
872
|
+
return defaultValue(key);
|
|
873
|
+
if (typeof defaultValue === "function")
|
|
874
|
+
return () => defaultValue(key);
|
|
875
|
+
return defaultValue;
|
|
530
876
|
};
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
877
|
+
var createAtomFamily = (defaultValue, options) => {
|
|
878
|
+
const map = new Map;
|
|
879
|
+
const keysAtom = atom(new Set);
|
|
880
|
+
const atomFamily = Object.assign((key) => {
|
|
881
|
+
const keyStringified = stableStringify(key);
|
|
882
|
+
if (map.has(keyStringified)) {
|
|
883
|
+
return map.get(keyStringified);
|
|
884
|
+
}
|
|
885
|
+
const familyAtom = atomFamilyAtom(handleDefaultValue(defaultValue, key), createOptions(options, atomFamily, Object.freeze(key), keyStringified));
|
|
886
|
+
map.set(keyStringified, familyAtom);
|
|
887
|
+
return familyAtom;
|
|
888
|
+
}, {
|
|
889
|
+
__valdresAtomFamilyMap: map,
|
|
890
|
+
release: (key) => map.delete(key),
|
|
891
|
+
__keysAtom: keysAtom,
|
|
892
|
+
__keysSelector: selector((get) => Array.from(get(keysAtom)))
|
|
893
|
+
});
|
|
894
|
+
if (options?.name)
|
|
895
|
+
Object.defineProperty(atomFamily, "name", {
|
|
896
|
+
value: options.name,
|
|
897
|
+
writable: false
|
|
898
|
+
});
|
|
899
|
+
return atomFamily;
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
// src/lib/createGlobalAtomFamily.ts
|
|
903
|
+
var createGlobalAtomFamily = (defaultValue, options) => {
|
|
904
|
+
if (!options.name)
|
|
905
|
+
throw new Error(`Missing name for global atomFamiliy`);
|
|
906
|
+
if (globalStore.atomFamilies.has(options.name)) {
|
|
907
|
+
return globalStore.atomFamilies.get(options.name);
|
|
908
|
+
}
|
|
909
|
+
const family = createAtomFamily(defaultValue, options);
|
|
910
|
+
globalStore.atomFamilies.set(options.name, family);
|
|
911
|
+
return family;
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
// src/atomFamily.ts
|
|
915
|
+
function atomFamily(defaultValue, options) {
|
|
916
|
+
if (options?.global)
|
|
917
|
+
return createGlobalAtomFamily(defaultValue, options);
|
|
918
|
+
return createAtomFamily(defaultValue, options);
|
|
534
919
|
}
|
|
535
|
-
|
|
536
|
-
var
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
920
|
+
// src/createStoreWithSelectorSet.ts
|
|
921
|
+
var setSelector = (selector3, values, store3) => {
|
|
922
|
+
return selector3.set(store3.set, store3.get, store3.reset, ...values);
|
|
923
|
+
};
|
|
924
|
+
var createStoreWithSelectorSet = (id) => {
|
|
925
|
+
const data = createStoreData(id);
|
|
926
|
+
const store3 = storeFromStoreData2(data);
|
|
927
|
+
store3.set = (state, value, ...rest) => {
|
|
928
|
+
if (isAtom(state))
|
|
929
|
+
return setAtom(state, value, data);
|
|
930
|
+
if (isSelector(state))
|
|
931
|
+
return setSelector(state, [value, ...rest], store3);
|
|
932
|
+
throw new Error("Invalid state object");
|
|
933
|
+
};
|
|
934
|
+
store3.kind = "storeWithSelectorSet";
|
|
935
|
+
return store3;
|
|
936
|
+
};
|
|
542
937
|
// src/selectorFamily.ts
|
|
543
|
-
var
|
|
938
|
+
var createOptions2 = (options = {}, family, familyKey, keyStringified) => {
|
|
939
|
+
if (options.name) {
|
|
940
|
+
return {
|
|
941
|
+
equal,
|
|
942
|
+
...options,
|
|
943
|
+
name: options?.name + "_" + keyStringified,
|
|
944
|
+
family,
|
|
945
|
+
familyKey
|
|
946
|
+
};
|
|
947
|
+
} else {
|
|
948
|
+
return { equal, ...options, family, familyKey };
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
var selectorFamily = (get, options) => {
|
|
544
952
|
const map = new Map;
|
|
545
953
|
const selectorFamily2 = (key) => {
|
|
546
|
-
|
|
547
|
-
try {
|
|
548
|
-
keyStringified = stableStringify(key);
|
|
549
|
-
} catch (e) {
|
|
550
|
-
console.log(`errro`, { key, debugLabel, e });
|
|
551
|
-
throw e;
|
|
552
|
-
}
|
|
954
|
+
const keyStringified = stableStringify(key);
|
|
553
955
|
if (map.has(keyStringified))
|
|
554
956
|
return map.get(keyStringified);
|
|
555
|
-
const
|
|
556
|
-
const newSelector = selector((selectorArgs) => get(key)(selectorArgs), selectorDebugLabel);
|
|
557
|
-
newSelector.family = selectorFamily2;
|
|
957
|
+
const newSelector = selector((selectorArgs) => get(key)(selectorArgs), createOptions2(options, selectorFamily2, key, keyStringified));
|
|
558
958
|
map.set(keyStringified, newSelector);
|
|
559
959
|
return newSelector;
|
|
560
960
|
};
|
|
561
|
-
selectorFamily2.
|
|
961
|
+
selectorFamily2.__valdresSelectorFamilyMap = map;
|
|
962
|
+
if (options?.name)
|
|
963
|
+
Object.defineProperty(selectorFamily2, "name", {
|
|
964
|
+
value: options.name,
|
|
965
|
+
writable: false
|
|
966
|
+
});
|
|
562
967
|
return selectorFamily2;
|
|
563
968
|
};
|
|
969
|
+
// src/utils/isFamilySelector.ts
|
|
970
|
+
var isFamilySelector = (state) => isFamilyState(state) && isSelector(state);
|
|
564
971
|
export {
|
|
972
|
+
store,
|
|
565
973
|
selectorFamily,
|
|
566
974
|
selector,
|
|
567
|
-
|
|
975
|
+
isSelectorFamily,
|
|
568
976
|
isSelector,
|
|
569
977
|
isPromiseLike,
|
|
978
|
+
isFamilyState,
|
|
979
|
+
isFamilySelector,
|
|
980
|
+
isFamilyAtom,
|
|
570
981
|
isFamily,
|
|
982
|
+
isAtomFamily,
|
|
571
983
|
isAtom,
|
|
572
|
-
|
|
573
|
-
|
|
984
|
+
globalStore,
|
|
985
|
+
createStoreWithSelectorSet,
|
|
574
986
|
atomFamily,
|
|
575
987
|
atom
|
|
576
988
|
};
|