valdres 0.2.0-alpha.8 → 0.2.0-alpha.9

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 CHANGED
@@ -1,109 +1,11 @@
1
- // src/atom.ts
2
- var atom = (defaultValue, options) => {
3
- if (!options)
4
- return { defaultValue };
5
- return {
6
- defaultValue,
7
- ...options
8
- };
9
- };
1
+ // src/lib/setAtom.ts
2
+ import equal4 from "fast-deep-equal";
3
+
10
4
  // src/utils/isPromiseLike.ts
11
5
  var isPromiseLike = (object) => {
12
6
  return object && object.then && typeof object.then === "function";
13
7
  };
14
8
 
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;
52
- }
53
- return stableStringifyRecurse(obj, key);
54
- }
55
- if (x instanceof Set) {
56
- return stableStringifyRecurse(Array.from(x).sort((a, b) => stableStringifyRecurse(a).localeCompare(stableStringifyRecurse(b))), key);
57
- }
58
- if (Symbol !== undefined && x[Symbol.iterator] != null && typeof x[Symbol.iterator] === "function") {
59
- return stableStringifyRecurse(Array.from(x), key);
60
- }
61
- return `{${Object.keys(x).filter((k) => x[k] !== undefined).sort().map((k) => `${stableStringifyRecurse(k)}:${stableStringifyRecurse(x[k], k)}`).join(",")}}`;
62
- };
63
- var stableStringify = (x) => {
64
- if (typeof x === "string" || typeof x === "boolean" || typeof x === "number")
65
- return x;
66
- return stableStringifyRecurse(x);
67
- };
68
-
69
- // src/atomFamily.ts
70
- var atomFamily = (defaultValue, debugLabel) => {
71
- const map = new Map;
72
- const atomFamily2 = (key, defaultOverride) => {
73
- const keyStringified = stableStringify(key);
74
- if (map.has(keyStringified)) {
75
- return map.get(keyStringified);
76
- }
77
- const atomDebugLabel = debugLabel && debugLabel + "_" + keyStringified;
78
- const newAtom = atom(typeof defaultValue === "function" ? () => defaultValue(key) : defaultValue, {
79
- label: atomDebugLabel
80
- });
81
- newAtom.family = atomFamily2;
82
- newAtom.familyKey = Object.freeze(key);
83
- map.set(keyStringified, newAtom);
84
- return newAtom;
85
- };
86
- atomFamily2._map = map;
87
- return atomFamily2;
88
- };
89
- // src/lib/createStoreData.ts
90
- var generateId = () => (Math.random() + 1).toString(36).substring(7);
91
- var createStoreData = (id = generateId()) => ({
92
- id,
93
- values: new WeakMap,
94
- expiredValues: new WeakMap,
95
- subscriptions: new WeakMap,
96
- subscriptionsRequireEqualCheck: new WeakMap,
97
- stateConsumers: new WeakMap,
98
- stateDependencies: new WeakMap
99
- });
100
-
101
- // src/utils/isAtom.ts
102
- var isAtom = (state) => Object.hasOwn(state, "defaultValue");
103
-
104
- // src/lib/getState.ts
105
- import equal4 from "fast-deep-equal";
106
-
107
9
  // src/lib/updateStateSubscribers.ts
108
10
  var updateStateSubscribers = (state, data) => {
109
11
  const subscribtions = data.subscriptions.get(state);
@@ -123,10 +25,76 @@ var updateStateSubscribers = (state, data) => {
123
25
  };
124
26
 
125
27
  // src/lib/updateSelectorSubscribers.ts
126
- import equal2 from "fast-deep-equal";
28
+ import equal3 from "fast-deep-equal";
127
29
 
128
30
  // src/lib/initSelector.ts
31
+ import equal2 from "fast-deep-equal";
32
+
33
+ // src/lib/getState.ts
129
34
  import equal from "fast-deep-equal";
35
+
36
+ // src/lib/initAtom.ts
37
+ var getAtomInitValue = (atom, data) => {
38
+ if (atom.defaultValue === undefined) {
39
+ let promiseResolve;
40
+ const promise = new Promise((resolve) => {
41
+ promiseResolve = resolve;
42
+ });
43
+ promise.__isEmptyAtomPromise__ = true;
44
+ promise.__resolveEmptyAtomPromise__ = promiseResolve;
45
+ return promise;
46
+ } else if (typeof atom.defaultValue === "function") {
47
+ const value = atom.defaultValue();
48
+ if (isPromiseLike(value)) {
49
+ value.then((resolvedValue) => {
50
+ data.values.set(atom, resolvedValue);
51
+ propagateUpdatedAtoms([atom], data);
52
+ });
53
+ }
54
+ return value;
55
+ } else {
56
+ return atom.defaultValue;
57
+ }
58
+ };
59
+ var initAtom = (atom, data) => {
60
+ let value = getAtomInitValue(atom, data);
61
+ data.values.set(atom, value);
62
+ if (atom.onInit)
63
+ atom.onInit((newVal) => {
64
+ value = newVal;
65
+ setAtom(atom, newVal, data, true);
66
+ }, data);
67
+ return value;
68
+ };
69
+
70
+ // src/utils/isAtom.ts
71
+ var isAtom = (state) => Object.hasOwn(state, "defaultValue");
72
+
73
+ // src/utils/isSelector.ts
74
+ var isSelector = (state) => Object.hasOwn(state, "get");
75
+
76
+ // src/utils/isFamily.ts
77
+ var isFamily = (state) => Object.hasOwn(state, "_map");
78
+
79
+ // src/lib/getState.ts
80
+ function getState(state, data) {
81
+ if (data.values.has(state))
82
+ return data.values.get(state);
83
+ if (isAtom(state))
84
+ return initAtom(state, data);
85
+ if (isSelector(state))
86
+ return initSelector(state, data);
87
+ if (isFamily(state)) {
88
+ const array = Array.from(state._map.keys());
89
+ if (equal(array, state._keyArray))
90
+ return state._keyArray;
91
+ state._keyArray = array;
92
+ return array;
93
+ }
94
+ throw new Error("Invalid object passed to get");
95
+ }
96
+
97
+ // src/lib/initSelector.ts
130
98
  class SuspendAndWaitForResolveError extends Error {
131
99
  promise;
132
100
  constructor(promise) {
@@ -143,7 +111,6 @@ var getOrInitConsumersSet = (state, data) => {
143
111
  return newSet;
144
112
  };
145
113
  var evaluateSelector = (selector, data) => {
146
- const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
147
114
  const updatedDependencies = new Set;
148
115
  let result;
149
116
  try {
@@ -153,7 +120,7 @@ var evaluateSelector = (selector, data) => {
153
120
  if (isPromiseLike(value))
154
121
  throw new SuspendAndWaitForResolveError(value);
155
122
  return value;
156
- });
123
+ }, data.id);
157
124
  } catch (error) {
158
125
  if (error instanceof SuspendAndWaitForResolveError) {
159
126
  result = error;
@@ -161,6 +128,7 @@ var evaluateSelector = (selector, data) => {
161
128
  throw error;
162
129
  }
163
130
  }
131
+ const currentDependencies = data.stateDependencies.get(selector) ?? new Set;
164
132
  const added = updatedDependencies?.difference(currentDependencies);
165
133
  const removed = currentDependencies?.difference(updatedDependencies);
166
134
  for (const state of added) {
@@ -194,7 +162,7 @@ var initSelector = (selector, data) => {
194
162
  const value = handleSelectorResult(tmpValue, selector, data);
195
163
  if (data.expiredValues.has(selector)) {
196
164
  const expiredValue = data.expiredValues.get(selector);
197
- if (equal(expiredValue, value)) {
165
+ if (equal2(expiredValue, value)) {
198
166
  data.values.set(selector, expiredValue);
199
167
  return expiredValue;
200
168
  }
@@ -213,7 +181,7 @@ var updateSelectorSubscribers = (selector, data) => {
213
181
  try {
214
182
  const oldValue = data.expiredValues.get(selector);
215
183
  const newValue = initSelector(selector, data);
216
- if (equal2(newValue, oldValue))
184
+ if (equal3(newValue, oldValue))
217
185
  return;
218
186
  } catch (e) {
219
187
  }
@@ -246,13 +214,13 @@ var recursivlyResetSelectorTree = (selectors, data, clearedSelectors) => {
246
214
  };
247
215
  var propagateUpdatedAtoms = (atoms, data) => {
248
216
  const clearedSelectors = new Set;
249
- for (const atom2 of atoms) {
250
- const consumers = data.stateConsumers.get(atom2);
217
+ for (const atom of atoms) {
218
+ const consumers = data.stateConsumers.get(atom);
251
219
  if (consumers && consumers.size) {
252
220
  recursivlyResetSelectorTree(consumers, data, clearedSelectors);
253
221
  }
254
- if (atom2.family) {
255
- const consumersFamily = data.stateConsumers.get(atom2.family);
222
+ if (atom.family) {
223
+ const consumersFamily = data.stateConsumers.get(atom.family);
256
224
  if (consumersFamily?.size) {
257
225
  recursivlyResetSelectorTree(consumersFamily, data, clearedSelectors);
258
226
  }
@@ -261,86 +229,151 @@ var propagateUpdatedAtoms = (atoms, data) => {
261
229
  for (const selector of clearedSelectors) {
262
230
  updateSelectorSubscribers(selector, data);
263
231
  }
264
- for (const atom2 of atoms) {
265
- updateStateSubscribers(atom2, data);
232
+ for (const atom of atoms) {
233
+ updateStateSubscribers(atom, data);
266
234
  }
267
235
  };
268
236
 
269
237
  // src/lib/setAtom.ts
270
- import equal3 from "fast-deep-equal";
271
- var setAtom = (atom2, newValue, data) => {
272
- const currentValue = getState(atom2, data);
238
+ var setAtom = (atom, newValue, data, skipOnSet = false) => {
239
+ const currentValue = getState(atom, data);
273
240
  if (typeof newValue === "function") {
274
241
  newValue = newValue(currentValue);
275
242
  if (isPromiseLike(newValue) || isPromiseLike(currentValue))
276
243
  throw new Error("Todo, how should we handle this?");
277
244
  }
278
- if (equal3(currentValue, newValue))
245
+ if (equal4(currentValue, newValue))
279
246
  return;
280
- data.values.set(atom2, newValue);
247
+ data.values.set(atom, newValue);
248
+ if (atom.onSet && !skipOnSet)
249
+ atom.onSet(newValue, data);
281
250
  if (currentValue?.__isEmptyAtomPromise__) {
282
251
  currentValue.__resolveEmptyAtomPromise__(newValue);
283
252
  }
284
- propagateUpdatedAtoms([atom2], data);
253
+ propagateUpdatedAtoms([atom], data);
285
254
  };
286
255
 
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
- });
256
+ // src/atom.ts
257
+ var globalAtom = (defaultValue, options) => {
258
+ const stores = new Set;
259
+ let value = defaultValue;
260
+ const onSet = (newValue, currentStore) => {
261
+ value = newValue;
262
+ if (stores.size > 1) {
263
+ for (const store of stores) {
264
+ if (store.id !== currentStore.id) {
265
+ setAtom(newAtom, value, store, true);
266
+ }
267
+ }
304
268
  }
305
- return value;
306
- } else {
307
- return atom2.defaultValue;
269
+ };
270
+ const newAtom = {
271
+ defaultValue,
272
+ ...options,
273
+ onInit: (setSelf, store) => {
274
+ setSelf(value);
275
+ stores.add(store);
276
+ },
277
+ onSet,
278
+ label: options?.label
279
+ };
280
+ return newAtom;
281
+ };
282
+ var atom = (defaultValue, options) => {
283
+ if (!options)
284
+ return { defaultValue };
285
+ if (options.global)
286
+ return globalAtom(defaultValue, options);
287
+ return {
288
+ defaultValue,
289
+ ...options
290
+ };
291
+ };
292
+ // src/lib/stableStringify.ts
293
+ var stableStringifyRecurse = (x, key) => {
294
+ if (typeof x === "string" && !x.includes('"') && !x.includes("\\")) {
295
+ return `"${x}"`;
296
+ }
297
+ switch (typeof x) {
298
+ case "undefined":
299
+ return "";
300
+ case "boolean":
301
+ return x ? "true" : "false";
302
+ case "number":
303
+ case "symbol":
304
+ return String(x);
305
+ case "string":
306
+ return JSON.stringify(x);
307
+ case "function":
308
+ return `__FUNCTION(${x.toString()})__`;
309
+ }
310
+ if (x === null) {
311
+ return "null";
312
+ }
313
+ if (typeof x !== "object") {
314
+ return JSON.stringify(x) ?? "";
315
+ }
316
+ if (isPromiseLike(x)) {
317
+ return "__PROMISE__";
318
+ }
319
+ if (Array.isArray(x)) {
320
+ return `[${x.map((v, i) => stableStringifyRecurse(v, i.toString()))}]`;
321
+ }
322
+ if (typeof x.toJSON === "function") {
323
+ return stableStringifyRecurse(x.toJSON(key), key);
324
+ }
325
+ if (x instanceof Map) {
326
+ const obj = {};
327
+ for (const [k, v] of x) {
328
+ obj[typeof k === "string" ? k : stringify(k, opt)] = v;
329
+ }
330
+ return stableStringifyRecurse(obj, key);
308
331
  }
332
+ if (x instanceof Set) {
333
+ return stableStringifyRecurse(Array.from(x).sort((a, b) => stableStringifyRecurse(a).localeCompare(stableStringifyRecurse(b))), key);
334
+ }
335
+ if (Symbol !== undefined && x[Symbol.iterator] != null && typeof x[Symbol.iterator] === "function") {
336
+ return stableStringifyRecurse(Array.from(x), key);
337
+ }
338
+ return `{${Object.keys(x).filter((k) => x[k] !== undefined).sort().map((k) => `${stableStringifyRecurse(k)}:${stableStringifyRecurse(x[k], k)}`).join(",")}}`;
309
339
  };
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;
340
+ var stableStringify = (x) => {
341
+ if (typeof x === "string" || typeof x === "boolean" || typeof x === "number")
342
+ return x;
343
+ return stableStringifyRecurse(x);
319
344
  };
320
345
 
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
- }
346
+ // src/atomFamily.ts
347
+ var atomFamily = (defaultValue, debugLabel) => {
348
+ const map = new Map;
349
+ const atomFamily2 = (key, defaultOverride) => {
350
+ const keyStringified = stableStringify(key);
351
+ if (map.has(keyStringified)) {
352
+ return map.get(keyStringified);
353
+ }
354
+ const atomDebugLabel = debugLabel && debugLabel + "_" + keyStringified;
355
+ const newAtom = atom(typeof defaultValue === "function" ? () => defaultValue(key) : defaultValue, {
356
+ label: atomDebugLabel
357
+ });
358
+ newAtom.family = atomFamily2;
359
+ newAtom.familyKey = Object.freeze(key);
360
+ map.set(keyStringified, newAtom);
361
+ return newAtom;
362
+ };
363
+ atomFamily2._map = map;
364
+ return atomFamily2;
365
+ };
366
+ // src/lib/createStoreData.ts
367
+ var generateId = () => (Math.random() + 1).toString(36).substring(7);
368
+ var createStoreData = (id = generateId()) => ({
369
+ id,
370
+ values: new WeakMap,
371
+ expiredValues: new WeakMap,
372
+ subscriptions: new WeakMap,
373
+ subscriptionsRequireEqualCheck: new WeakMap,
374
+ stateConsumers: new WeakMap,
375
+ stateDependencies: new WeakMap
376
+ });
344
377
 
345
378
  // src/lib/resetAtom.ts
346
379
  var resetAtom = (atom2, data) => {
@@ -474,7 +507,7 @@ var transaction = (callback, data) => {
474
507
  const res = state.get((s) => {
475
508
  deps.add(s);
476
509
  return txnGet(s);
477
- });
510
+ }, data.id);
478
511
  for (const dep of deps) {
479
512
  if (!txnSubscribers.has(dep)) {
480
513
  txnSubscribers.set(dep, new Set);
@@ -1,8 +1,13 @@
1
1
  import type { Atom } from "./types/Atom";
2
- type AtomOptions<Value> = {
2
+ import type { AtomOnSet } from "./types/AtomOnSet";
3
+ import type { StoreData } from "./types/StoreData";
4
+ type AtomOptions<Value = any> = {
5
+ global?: boolean;
3
6
  label?: string;
4
- onInit?: (setSelf: (value: Value) => void) => void;
7
+ onInit?: (setSelf: (value: Value) => void, store: StoreData) => void;
8
+ onSet?: AtomOnSet<Value>;
5
9
  onMount?: () => () => void;
6
10
  };
7
- export declare const atom: <Value, FamilyKey = undefined>(defaultValue?: Value | (() => Value | Promise<Value>), options?: AtomOptions<Value>) => Atom<Value, FamilyKey>;
11
+ export declare const globalAtom: <Value = any, FamilyKey = undefined>(defaultValue: Value | (() => Value | Promise<Value>), options: AtomOptions<Value>) => Atom<Value>;
12
+ export declare const atom: <Value = any, FamilyKey = undefined>(defaultValue?: Value | (() => Value | Promise<Value>), options?: AtomOptions<Value>) => Atom<Value, FamilyKey>;
8
13
  export {};
@@ -1,3 +1,3 @@
1
1
  import type { Atom } from "../types/Atom";
2
2
  import type { StoreData } from "../types/StoreData";
3
- export declare const setAtom: <V>(atom: Atom<V>, newValue: V, data: StoreData) => void;
3
+ export declare const setAtom: <Value = any>(atom: Atom<Value>, newValue: Value, data: StoreData, skipOnSet?: boolean) => void;
@@ -1,3 +1,3 @@
1
1
  import type { GetValue } from "./types/GetValue";
2
2
  import type { Selector } from "./types/Selector";
3
- export declare const selector: <Value, FamilyKey = undefined>(get: (get: GetValue) => Value, debugLabel?: string) => Selector<Value, FamilyKey>;
3
+ export declare const selector: <Value, FamilyKey = undefined>(get: (get: GetValue, storeId: string) => Value, debugLabel?: string) => Selector<Value, FamilyKey>;
@@ -1,9 +1,12 @@
1
1
  import type { AtomFamily } from "./AtomFamily";
2
- export type Atom<Value = unknown, FamilyKey = undefined> = {
2
+ import type { AtomOnInit } from "./AtomOnInit";
3
+ import type { AtomOnSet } from "./AtomOnSet";
4
+ export type Atom<Value = any, FamilyKey = undefined> = {
3
5
  defaultValue?: Value | (() => Value | Promise<Value>);
4
6
  label?: string;
5
7
  family?: AtomFamily<Value, FamilyKey>;
6
8
  familyKey?: FamilyKey;
7
- onInit?: (setSelf: (value: Value) => void) => void;
9
+ onInit?: AtomOnInit<Value>;
10
+ onSet?: AtomOnSet<Value>;
8
11
  onMount?: () => void | (() => void);
9
12
  };
@@ -0,0 +1,2 @@
1
+ import type { StoreData } from "./StoreData";
2
+ export type AtomOnInit<Value = unknown> = (setSelf: (value: Value) => void, store: StoreData) => void;
@@ -0,0 +1,2 @@
1
+ import type { StoreData } from "./StoreData";
2
+ export type AtomOnSet<Value = unknown> = (value: Value, store: StoreData) => void;
@@ -1,7 +1,7 @@
1
1
  import type { GetValue } from "./GetValue";
2
2
  import type { SelectorFamily } from "./SelectorFamily";
3
3
  export type Selector<Value = unknown, FamilyKey = undefined> = {
4
- get: (get: GetValue) => Value;
4
+ get: (get: GetValue, storeId: string) => Value;
5
5
  debugLabel?: string;
6
6
  family?: SelectorFamily<Value, FamilyKey>;
7
7
  familyKey?: FamilyKey;
@@ -1,3 +1,3 @@
1
1
  import type { Atom } from "./Atom";
2
2
  import type { SetAtomValue } from "./SetAtomValue";
3
- export type SetAtom<V = unknown> = (atom: Atom<V>, value: SetAtomValue<V>) => void;
3
+ export type SetAtom<V = any> = (atom: Atom<V>, value: SetAtomValue<V>) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valdres",
3
- "version": "0.2.0-alpha.8",
3
+ "version": "0.2.0-alpha.9",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Eigil Sagafos"
@@ -39,5 +39,5 @@
39
39
  "access": "public",
40
40
  "registry": "https://registry.npmjs.org/"
41
41
  },
42
- "gitHead": "c7f6e2d76adc15985444d02244522841d52aa233"
42
+ "gitHead": "e912b2bc8ae395473d0e843cceaf4037bc624b40"
43
43
  }