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