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