valdres 0.2.0-alpha.8 → 0.2.0-y.0

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