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