atom.io 0.7.0 → 0.8.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.
@@ -61,7 +61,7 @@ export function createAtom<T>(
61
61
  options.default instanceof Function ? options.default() : options.default
62
62
  core.atoms.set(newAtom.key, newAtom)
63
63
  markAtomAsDefault(options.key, store)
64
- cacheValue(options.key, initialValue, store)
64
+ cacheValue(options.key, initialValue, subject, store)
65
65
  const token = deposit(newAtom)
66
66
  for (const effect of options.effects ?? []) {
67
67
  effect({
@@ -1,13 +1,30 @@
1
+ import type { StateUpdate } from "../../src"
2
+ import { Future } from "./future"
1
3
  import type { Store } from "./store"
2
4
  import { IMPLICIT } from "./store"
5
+ import type { Subject } from "./subject"
3
6
  import { target } from "./transaction"
4
7
 
5
8
  export const cacheValue = (
6
9
  key: string,
7
10
  value: unknown,
11
+ subject: Subject<StateUpdate<unknown>>,
8
12
  store: Store = IMPLICIT.STORE,
9
13
  ): void => {
10
- target(store).valueMap.set(key, value)
14
+ const currentValue = target(store).valueMap.get(key)
15
+ if (currentValue instanceof Future) {
16
+ currentValue.cancel()
17
+ }
18
+ if (value instanceof Promise) {
19
+ const future = new Future(value)
20
+ target(store).valueMap.set(key, future)
21
+ future.then((value) => {
22
+ cacheValue(key, value, subject, store)
23
+ subject.next({ newValue: value, oldValue: value })
24
+ })
25
+ } else {
26
+ target(store).valueMap.set(key, value)
27
+ }
11
28
  }
12
29
 
13
30
  export const readCachedValue = <T>(
@@ -0,0 +1,39 @@
1
+ import { E } from "vitest/dist/reporters-5f784f42"
2
+
3
+ export type Eventual<T> = Promise<T> | T
4
+ export type Fated<T, E extends Error = Error> = Eventual<E | T>
5
+
6
+ /**
7
+ * A Promise that can be canceled.
8
+ * @internal
9
+ * @private
10
+ * @typeParam T The type of the value that the promise will resolve to.
11
+ *
12
+ * @remarks
13
+ * Can be constructed like a Promise, or from an existing Promise.
14
+ */
15
+ export class Future<T> extends Promise<T> {
16
+ private isCanceled = false
17
+
18
+ public constructor(
19
+ executor:
20
+ | Promise<T>
21
+ | ((resolve: (value: T) => void, reject: (reason?: any) => void) => void),
22
+ ) {
23
+ super((resolve, reject) => {
24
+ const pass = (value: T) =>
25
+ this.isCanceled ? reject(`canceled`) : resolve(value)
26
+ const fail = (reason: any) =>
27
+ this.isCanceled ? reject(`canceled`) : reject(reason)
28
+ if (typeof executor === `function`) {
29
+ executor(pass, fail)
30
+ } else {
31
+ executor.then(pass, fail)
32
+ }
33
+ })
34
+ }
35
+
36
+ public cancel(): void {
37
+ this.isCanceled = true
38
+ }
39
+ }
@@ -1,6 +1,7 @@
1
1
  export * from "./atom"
2
2
  export * from "./caching"
3
3
  export * from "./families"
4
+ export * from "./future"
4
5
  export * from "./get-state-internal"
5
6
  export * from "./operation"
6
7
  export * from "./mutable"
@@ -20,7 +20,7 @@ export const createReadWriteSelector = <T>(
20
20
  const { get, set } = registerSelector(options.key, store)
21
21
  const getSelf = () => {
22
22
  const value = options.get({ get })
23
- cacheValue(options.key, value, store)
23
+ cacheValue(options.key, value, subject, store)
24
24
  return value
25
25
  }
26
26
 
@@ -34,7 +34,7 @@ export const createReadWriteSelector = <T>(
34
34
  `)`,
35
35
  )
36
36
  const newValue = become(next)(oldValue)
37
- cacheValue(options.key, newValue, store)
37
+ cacheValue(options.key, newValue, subject, store)
38
38
  markDone(options.key, store)
39
39
  if (store.transactionStatus.phase === `idle`) {
40
40
  subject.next({ newValue, oldValue })
@@ -22,7 +22,7 @@ export const createReadonlySelector = <T>(
22
22
  const { get } = registerSelector(options.key, store)
23
23
  const getSelf = () => {
24
24
  const value = options.get({ get })
25
- cacheValue(options.key, value, store)
25
+ cacheValue(options.key, value, subject, store)
26
26
  return value
27
27
  }
28
28
 
@@ -20,7 +20,7 @@ export const setAtomState = <T>(
20
20
  let newValue = copyMutableIfWithinTransaction(atom, store)
21
21
  newValue = become(next)(newValue)
22
22
  store.config.logger?.info(`<< setting atom "${atom.key}" to`, newValue)
23
- cacheValue(atom.key, newValue, store)
23
+ cacheValue(atom.key, newValue, atom.subject, store)
24
24
  if (isAtomDefault(atom.key, store)) {
25
25
  markAtomAsNotDefault(atom.key, store)
26
26
  }
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Reactive state graph for React, Preact, and vanilla",
5
- "dependencies": {},
6
5
  "peerDependencies": {
7
- "@testing-library/react": ">=14.0.0",
8
6
  "@floating-ui/react": ">=0.25.0",
9
7
  "@floating-ui/react-dom": ">=2.0.0",
8
+ "@testing-library/react": ">=14.0.0",
10
9
  "framer-motion": ">=10.0.0",
11
10
  "react": ">=18.0.0",
12
11
  "socket.io": ">=4.0.0",
@@ -38,14 +37,15 @@
38
37
  "devDependencies": {
39
38
  "@emotion/react": "11.11.1",
40
39
  "@testing-library/react": "14.0.0",
41
- "@types/mock-fs": "4.13.1",
42
- "@types/react": "18.2.21",
40
+ "@types/mock-fs": "4.13.2",
41
+ "@types/react": "18.2.25",
43
42
  "@types/tmp": "0.2.4",
43
+ "@vitest/coverage-v8": "0.34.6",
44
44
  "concurrently": "8.2.1",
45
45
  "eslint": "8.50.0",
46
46
  "framer-motion": "10.16.4",
47
- "happy-dom": "12.1.6",
48
- "preact": "10.17.1",
47
+ "happy-dom": "12.8.0",
48
+ "preact": "10.18.1",
49
49
  "react": "18.2.0",
50
50
  "react-dom": "18.2.0",
51
51
  "react-router-dom": "6.16.0",
@@ -54,9 +54,9 @@
54
54
  "tmp": "0.2.1",
55
55
  "tsup": "7.2.0",
56
56
  "typescript": "5.2.2",
57
- "vite": "4.4.9",
57
+ "vite": "4.4.11",
58
58
  "vite-tsconfig-paths": "4.2.1",
59
- "vitest": "0.34.5"
59
+ "vitest": "0.34.6"
60
60
  },
61
61
  "main": "dist/index.js",
62
62
  "types": "dist/index.d.ts",
@@ -2,7 +2,6 @@
2
2
 
3
3
  var atom_io = require('atom.io');
4
4
  var introspection = require('atom.io/introspection');
5
- var webEffects = require('atom.io/web-effects');
6
5
  var react = require('atom.io/react');
7
6
  var framerMotion = require('framer-motion');
8
7
  var React = require('react');
@@ -62,6 +61,21 @@ var __objRest = (source, exclude) => {
62
61
  return target;
63
62
  };
64
63
 
64
+ // ../__unstable__/web-effects/src/storage.ts
65
+ var persistAtom = (storage) => ({ stringify, parse }) => (key) => ({ setSelf, onSet }) => {
66
+ const savedValue = storage.getItem(key);
67
+ if (savedValue != null)
68
+ setSelf(parse(savedValue));
69
+ onSet(({ newValue }) => {
70
+ if (newValue == null) {
71
+ storage.removeItem(key);
72
+ return;
73
+ }
74
+ storage.setItem(key, stringify(newValue));
75
+ });
76
+ };
77
+ var lazyLocalStorageEffect = persistAtom(localStorage)(JSON);
78
+
65
79
  // ../../anvl/src/function/pipe.ts
66
80
  function pipe(a2, ab, bc, cd, de, ef, fg, gh, hi) {
67
81
  switch (arguments.length) {
@@ -2765,22 +2779,22 @@ var {
2765
2779
  var devtoolsAreOpenState = atom_io.atom({
2766
2780
  key: `\u{1F441}\u200D\u{1F5E8} Devtools Are Open`,
2767
2781
  default: true,
2768
- effects: [webEffects.lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools Are Open`)]
2782
+ effects: [lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools Are Open`)]
2769
2783
  });
2770
2784
  var devtoolsViewSelectionState = atom_io.atom({
2771
2785
  key: `\u{1F441}\u200D\u{1F5E8} Devtools View Selection`,
2772
2786
  default: `atoms`,
2773
- effects: [webEffects.lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools View`)]
2787
+ effects: [lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools View`)]
2774
2788
  });
2775
2789
  var devtoolsViewOptionsState = atom_io.atom({
2776
2790
  key: `\u{1F441}\u200D\u{1F5E8} Devtools View Options`,
2777
2791
  default: [`atoms`, `selectors`, `transactions`, `timelines`],
2778
- effects: [webEffects.lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools View Options`)]
2792
+ effects: [lazyLocalStorageEffect(`\u{1F441}\u200D\u{1F5E8} Devtools View Options`)]
2779
2793
  });
2780
2794
  var findViewIsOpenState = atom_io.atomFamily({
2781
2795
  key: `\u{1F441}\u200D\u{1F5E8} Devtools View Is Open`,
2782
2796
  default: false,
2783
- effects: (key) => [webEffects.lazyLocalStorageEffect(key + `:view-is-open`)]
2797
+ effects: (key) => [lazyLocalStorageEffect(key + `:view-is-open`)]
2784
2798
  });
2785
2799
  var primitiveRefinery = new Refinery({
2786
2800
  number: (input) => typeof input === `number`,