atom.io 0.21.1 → 0.22.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 (92) hide show
  1. package/data/dist/index.cjs +136 -63
  2. package/data/dist/index.d.ts +6 -0
  3. package/data/dist/index.js +3 -3
  4. package/data/src/join.ts +135 -51
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/{chunk-RT43TVKP.js → chunk-GVHKIJ3G.js} +1 -1
  7. package/dist/{chunk-HITX3MO4.js → chunk-JA4V7TJY.js} +135 -62
  8. package/dist/index.cjs +2 -7
  9. package/dist/index.d.ts +29 -14
  10. package/dist/index.js +4 -8
  11. package/ephemeral/dist/index.cjs +11 -0
  12. package/ephemeral/dist/index.js +9 -0
  13. package/ephemeral/package.json +16 -0
  14. package/ephemeral/src/index.ts +1 -0
  15. package/eslint-plugin/dist/index.cjs +156 -1
  16. package/eslint-plugin/dist/index.js +156 -1
  17. package/eslint-plugin/src/rules/index.ts +1 -0
  18. package/eslint-plugin/src/rules/lifespan.ts +204 -0
  19. package/eslint-plugin/src/rules/synchronous-selector-dependencies.ts +1 -65
  20. package/eslint-plugin/src/walk.ts +73 -0
  21. package/immortal/dist/index.cjs +100 -0
  22. package/immortal/dist/index.js +97 -0
  23. package/immortal/package.json +16 -0
  24. package/immortal/src/index.ts +2 -0
  25. package/immortal/src/molecule.ts +134 -0
  26. package/immortal/src/seek-state.ts +60 -0
  27. package/internal/dist/index.cjs +186 -146
  28. package/internal/dist/index.d.ts +29 -13
  29. package/internal/dist/index.js +185 -146
  30. package/internal/src/atom/dispose-atom.ts +4 -1
  31. package/internal/src/families/create-readonly-selector-family.ts +9 -9
  32. package/internal/src/families/create-regular-atom-family.ts +15 -20
  33. package/internal/src/families/create-writable-selector-family.ts +6 -7
  34. package/internal/src/families/find-in-store.ts +11 -5
  35. package/internal/src/families/index.ts +2 -0
  36. package/internal/src/families/init-family-member.ts +91 -0
  37. package/internal/src/families/seek-in-store.ts +106 -0
  38. package/internal/src/get-state/get-from-store.ts +2 -2
  39. package/internal/src/mutable/create-mutable-atom-family.ts +17 -23
  40. package/internal/src/mutable/create-mutable-atom.ts +3 -1
  41. package/internal/src/mutable/get-json-family.ts +2 -2
  42. package/internal/src/mutable/get-json-token.ts +27 -12
  43. package/internal/src/mutable/tracker-family.ts +14 -12
  44. package/internal/src/not-found-error.ts +11 -3
  45. package/internal/src/selector/create-readonly-selector.ts +2 -2
  46. package/internal/src/selector/create-writable-selector.ts +2 -2
  47. package/internal/src/selector/dispose-selector.ts +40 -23
  48. package/internal/src/selector/register-selector.ts +8 -5
  49. package/internal/src/set-state/set-into-store.ts +2 -2
  50. package/internal/src/store/index.ts +0 -1
  51. package/internal/src/store/store.ts +18 -5
  52. package/internal/src/subscribe/subscribe-to-state.ts +2 -2
  53. package/internal/src/transaction/build-transaction.ts +7 -2
  54. package/introspection/dist/index.cjs +38 -52
  55. package/introspection/dist/index.js +38 -52
  56. package/introspection/src/attach-atom-index.ts +38 -48
  57. package/introspection/src/attach-selector-index.ts +45 -50
  58. package/json/dist/index.cjs +38 -4
  59. package/json/dist/index.js +40 -6
  60. package/json/src/select-json-family.ts +46 -7
  61. package/package.json +30 -10
  62. package/react/dist/index.cjs +1 -1
  63. package/react/dist/index.js +1 -1
  64. package/react/src/use-json.ts +1 -1
  65. package/react-devtools/dist/index.cjs +11 -10
  66. package/react-devtools/dist/index.js +2 -1
  67. package/react-devtools/src/StateIndex.tsx +2 -1
  68. package/react-devtools/src/TimelineIndex.tsx +2 -1
  69. package/react-devtools/src/TransactionIndex.tsx +7 -7
  70. package/realtime-client/dist/index.cjs +3 -3
  71. package/realtime-client/dist/index.js +3 -3
  72. package/realtime-client/src/pull-mutable-atom-family-member.ts +1 -1
  73. package/realtime-client/src/pull-mutable-atom.ts +1 -1
  74. package/realtime-client/src/sync-continuity.ts +1 -2
  75. package/realtime-react/dist/index.cjs +1 -1
  76. package/realtime-react/dist/index.js +1 -1
  77. package/realtime-server/dist/index.cjs +18 -17
  78. package/realtime-server/dist/index.js +7 -6
  79. package/realtime-server/src/realtime-continuity-synchronizer.ts +5 -3
  80. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  81. package/realtime-server/src/realtime-mutable-provider.ts +1 -1
  82. package/realtime-testing/dist/index.cjs +6 -2
  83. package/realtime-testing/dist/index.js +8 -5
  84. package/realtime-testing/src/setup-realtime-test.tsx +5 -2
  85. package/src/atom.ts +10 -4
  86. package/src/index.ts +1 -2
  87. package/src/selector.ts +10 -4
  88. package/src/silo.ts +3 -3
  89. package/src/transaction.ts +5 -2
  90. package/internal/src/store/withdraw-new-family-member.ts +0 -69
  91. /package/{src → ephemeral/src}/find-state.ts +0 -0
  92. /package/src/{dispose.ts → dispose-state.ts} +0 -0
@@ -18,30 +18,26 @@ export function createRegularAtomFamily<T, K extends Json.Serializable>(
18
18
  store: Store,
19
19
  ): RegularAtomFamily<T, K> {
20
20
  const subject = new Subject<RegularAtomToken<T>>()
21
+
21
22
  const atomFamily: RegularAtomFamily<T, K> = Object.assign(
22
23
  (key: K): RegularAtomToken<any> => {
23
24
  const subKey = stringifyJson(key)
24
25
  const family: FamilyMetadata = { key: options.key, subKey }
25
26
  const fullKey = `${options.key}(${subKey})`
26
27
  const target = newest(store)
27
- const atomAlreadyCreated = target.atoms.has(fullKey)
28
- let token: RegularAtomToken<any>
29
- if (atomAlreadyCreated) {
30
- token = { type: `atom`, key: fullKey, family }
31
- } else {
32
- const individualOptions: RegularAtomOptions<any> = {
33
- key: fullKey,
34
- default:
35
- options.default instanceof Function
36
- ? options.default(key)
37
- : options.default,
38
- }
39
- if (options.effects) {
40
- individualOptions.effects = options.effects(key)
41
- }
42
- token = createRegularAtom(individualOptions, family, store)
43
- subject.next(token)
28
+
29
+ const def = options.default
30
+ const individualOptions: RegularAtomOptions<T> = {
31
+ key: fullKey,
32
+ default: def instanceof Function ? def(key) : def,
33
+ }
34
+ if (options.effects) {
35
+ individualOptions.effects = options.effects(key)
44
36
  }
37
+
38
+ const token = createRegularAtom(individualOptions, family, target)
39
+
40
+ subject.next(token)
45
41
  return token
46
42
  },
47
43
  {
@@ -50,8 +46,7 @@ export function createRegularAtomFamily<T, K extends Json.Serializable>(
50
46
  subject,
51
47
  install: (s: Store) => createRegularAtomFamily(options, s),
52
48
  } as const,
53
- )
54
- const target = newest(store)
55
- target.families.set(options.key, atomFamily)
49
+ ) satisfies RegularAtomFamily<T, K>
50
+ store.families.set(options.key, atomFamily)
56
51
  return atomFamily
57
52
  }
@@ -7,9 +7,9 @@ import type {
7
7
  import type { Json } from "atom.io/json"
8
8
  import { stringifyJson } from "atom.io/json"
9
9
 
10
+ import { newest } from "../lineage"
10
11
  import { createWritableSelector } from "../selector"
11
12
  import type { Store } from "../store"
12
- import { deposit } from "../store"
13
13
  import { Subject } from "../subject"
14
14
 
15
15
  export function createWritableSelectorFamily<T, K extends Json.Serializable>(
@@ -23,10 +23,8 @@ export function createWritableSelectorFamily<T, K extends Json.Serializable>(
23
23
  const subKey = stringifyJson(key)
24
24
  const family: FamilyMetadata = { key: options.key, subKey }
25
25
  const fullKey = `${options.key}(${subKey})`
26
- const existing = store.selectors.get(fullKey)
27
- if (existing) {
28
- return deposit(existing)
29
- }
26
+ const target = newest(store)
27
+
30
28
  const token = createWritableSelector(
31
29
  {
32
30
  key: fullKey,
@@ -34,8 +32,9 @@ export function createWritableSelectorFamily<T, K extends Json.Serializable>(
34
32
  set: options.set(key),
35
33
  },
36
34
  family,
37
- store,
35
+ target,
38
36
  )
37
+
39
38
  subject.next(token)
40
39
  return token
41
40
  },
@@ -45,7 +44,7 @@ export function createWritableSelectorFamily<T, K extends Json.Serializable>(
45
44
  subject,
46
45
  install: (s: Store) => createWritableSelectorFamily(options, s),
47
46
  } as const,
48
- ) as WritableSelectorFamily<T, K>
47
+ ) satisfies WritableSelectorFamily<T, K>
49
48
  store.families.set(options.key, selectorFamily)
50
49
  return selectorFamily
51
50
  }
@@ -21,6 +21,8 @@ import type { Json } from "atom.io/json"
21
21
  import type { Transceiver } from "../mutable"
22
22
  import { NotFoundError } from "../not-found-error"
23
23
  import type { Store } from "../store"
24
+ import { initFamilyMember } from "./init-family-member"
25
+ import { seekInStore } from "./seek-in-store"
24
26
 
25
27
  export function findInStore<
26
28
  T extends Transceiver<any>,
@@ -80,11 +82,15 @@ export function findInStore(
80
82
  key: Json.Serializable,
81
83
  store: Store,
82
84
  ): ReadableToken<any> {
83
- const familyKey = token.key
84
- const family = store.families.get(familyKey)
85
- if (family === undefined) {
86
- throw new NotFoundError(token, store)
85
+ if (store.config.lifespan === `immortal`) {
86
+ throw new Error(
87
+ `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`,
88
+ )
87
89
  }
88
- const state = family(key)
90
+ let state = seekInStore(token, key, store)
91
+ if (state) {
92
+ return state
93
+ }
94
+ state = initFamilyMember(token, key, store)
89
95
  return state
90
96
  }
@@ -3,3 +3,5 @@ export * from "./create-readonly-selector-family"
3
3
  export * from "./create-regular-atom-family"
4
4
  export * from "./create-selector-family"
5
5
  export * from "./find-in-store"
6
+ export * from "./init-family-member"
7
+ export * from "./seek-in-store"
@@ -0,0 +1,91 @@
1
+ import type {
2
+ AtomFamilyToken,
3
+ AtomToken,
4
+ MutableAtomFamilyToken,
5
+ MutableAtomToken,
6
+ ReadableFamilyToken,
7
+ ReadableToken,
8
+ ReadonlySelectorFamilyToken,
9
+ ReadonlySelectorToken,
10
+ RegularAtomFamilyToken,
11
+ RegularAtomToken,
12
+ SelectorFamilyToken,
13
+ SelectorToken,
14
+ WritableFamilyToken,
15
+ WritableSelectorFamilyToken,
16
+ WritableSelectorToken,
17
+ WritableToken,
18
+ } from "atom.io"
19
+ import type { Json } from "atom.io/json"
20
+
21
+ import type { Transceiver } from "../mutable"
22
+ import { NotFoundError } from "../not-found-error"
23
+ import type { Store } from "../store"
24
+ import { seekInStore } from "./seek-in-store"
25
+
26
+ export function initFamilyMember<
27
+ T extends Transceiver<any>,
28
+ J extends Json.Serializable,
29
+ K extends Json.Serializable,
30
+ Key extends K,
31
+ >(
32
+ token: MutableAtomFamilyToken<T, J, K>,
33
+ key: Key,
34
+ store: Store,
35
+ ): MutableAtomToken<T, J>
36
+
37
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
38
+ token: RegularAtomFamilyToken<T, K>,
39
+ key: Key,
40
+ store: Store,
41
+ ): RegularAtomToken<T>
42
+
43
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
44
+ token: AtomFamilyToken<T, K>,
45
+ key: Key,
46
+ store: Store,
47
+ ): AtomToken<T>
48
+
49
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
50
+ token: WritableSelectorFamilyToken<T, K>,
51
+ key: Key,
52
+ store: Store,
53
+ ): WritableSelectorToken<T>
54
+
55
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
56
+ token: ReadonlySelectorFamilyToken<T, K>,
57
+ key: Key,
58
+ store: Store,
59
+ ): ReadonlySelectorToken<T>
60
+
61
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
62
+ token: SelectorFamilyToken<T, K>,
63
+ key: Key,
64
+ store: Store,
65
+ ): SelectorToken<T>
66
+
67
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
68
+ token: WritableFamilyToken<T, K>,
69
+ key: Key,
70
+ store: Store,
71
+ ): WritableToken<T>
72
+
73
+ export function initFamilyMember<T, K extends Json.Serializable, Key extends K>(
74
+ token: ReadableFamilyToken<T, K>,
75
+ key: Key,
76
+ store: Store,
77
+ ): ReadableToken<T>
78
+
79
+ export function initFamilyMember(
80
+ token: ReadableFamilyToken<any, any>,
81
+ key: Json.Serializable,
82
+ store: Store,
83
+ ): ReadableToken<any> {
84
+ const familyKey = token.key
85
+ const family = store.families.get(familyKey)
86
+ if (family === undefined) {
87
+ throw new NotFoundError(token, store)
88
+ }
89
+ const state = family(key)
90
+ return state
91
+ }
@@ -0,0 +1,106 @@
1
+ import type {
2
+ AtomFamilyToken,
3
+ AtomToken,
4
+ MutableAtomFamilyToken,
5
+ MutableAtomToken,
6
+ ReadableFamilyToken,
7
+ ReadableToken,
8
+ ReadonlySelectorFamilyToken,
9
+ ReadonlySelectorToken,
10
+ RegularAtomFamilyToken,
11
+ RegularAtomToken,
12
+ SelectorFamilyToken,
13
+ SelectorToken,
14
+ WritableFamilyToken,
15
+ WritableSelectorFamilyToken,
16
+ WritableSelectorToken,
17
+ WritableToken,
18
+ } from "atom.io"
19
+ import { type Json, stringifyJson } from "atom.io/json"
20
+
21
+ import type { ReadableState } from ".."
22
+ import { newest } from "../lineage"
23
+ import type { Transceiver } from "../mutable"
24
+ import { deposit, type Store } from "../store"
25
+
26
+ export function seekInStore<
27
+ T extends Transceiver<any>,
28
+ J extends Json.Serializable,
29
+ K extends Json.Serializable,
30
+ Key extends K,
31
+ >(
32
+ token: MutableAtomFamilyToken<T, J, K>,
33
+ key: Key,
34
+ store: Store,
35
+ ): MutableAtomToken<T, J> | undefined
36
+
37
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
38
+ token: RegularAtomFamilyToken<T, K>,
39
+ key: Key,
40
+ store: Store,
41
+ ): RegularAtomToken<T> | undefined
42
+
43
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
44
+ token: AtomFamilyToken<T, K>,
45
+ key: Key,
46
+ store: Store,
47
+ ): AtomToken<T> | undefined
48
+
49
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
50
+ token: WritableSelectorFamilyToken<T, K>,
51
+ key: Key,
52
+ store: Store,
53
+ ): WritableSelectorToken<T> | undefined
54
+
55
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
56
+ token: ReadonlySelectorFamilyToken<T, K>,
57
+ key: Key,
58
+ store: Store,
59
+ ): ReadonlySelectorToken<T> | undefined
60
+
61
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
62
+ token: SelectorFamilyToken<T, K>,
63
+ key: Key,
64
+ store: Store,
65
+ ): SelectorToken<T> | undefined
66
+
67
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
68
+ token: WritableFamilyToken<T, K>,
69
+ key: Key,
70
+ store: Store,
71
+ ): WritableToken<T> | undefined
72
+
73
+ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
74
+ token: ReadableFamilyToken<T, K>,
75
+ key: Key,
76
+ store: Store,
77
+ ): ReadableToken<T> | undefined
78
+
79
+ export function seekInStore(
80
+ token: ReadableFamilyToken<any, any>,
81
+ key: Json.Serializable,
82
+ store: Store,
83
+ ): ReadableToken<any> | undefined {
84
+ const subKey = stringifyJson(key)
85
+ const fullKey = `${token.key}(${subKey})`
86
+ const target = newest(store)
87
+ let state: ReadableState<any> | undefined
88
+ switch (token.type) {
89
+ case `atom_family`:
90
+ case `mutable_atom_family`:
91
+ state = target.atoms.get(fullKey)
92
+ break
93
+
94
+ case `selector_family`: {
95
+ state = target.selectors.get(fullKey)
96
+ break
97
+ }
98
+ case `readonly_selector_family`:
99
+ state = target.readonlySelectors.get(fullKey)
100
+ break
101
+ }
102
+ if (state) {
103
+ return deposit(state)
104
+ }
105
+ return state
106
+ }
@@ -1,10 +1,10 @@
1
1
  import type { ReadableToken } from "atom.io"
2
2
 
3
3
  import type { Store } from "../store"
4
- import { withdrawOrCreate } from "../store"
4
+ import { withdraw } from "../store"
5
5
  import { readOrComputeValue } from "./read-or-compute-value"
6
6
 
7
7
  export function getFromStore<T>(token: ReadableToken<T>, store: Store): T {
8
- const state = withdrawOrCreate(token, store)
8
+ const state = withdraw(token, store)
9
9
  return readOrComputeValue(state, store)
10
10
  }
@@ -24,32 +24,28 @@ export function createMutableAtomFamily<
24
24
  store: Store,
25
25
  ): MutableAtomFamily<T, J, K> {
26
26
  const subject = new Subject<MutableAtomToken<T, J>>()
27
- const atomFamily: MutableAtomFamily<T, J, K> = Object.assign(
27
+
28
+ const atomFamily = Object.assign(
28
29
  (key: K): MutableAtomToken<T, J> => {
29
30
  const subKey = stringifyJson(key)
30
31
  const family: FamilyMetadata = { key: options.key, subKey }
31
32
  const fullKey = `${options.key}(${subKey})`
32
33
  const target = newest(store)
33
- const atomAlreadyCreated = target.atoms.has(fullKey)
34
- let token: MutableAtomToken<T, J>
35
- if (atomAlreadyCreated) {
36
- token = { type: `mutable_atom`, key: fullKey, family }
37
- } else {
38
- const individualOptions: MutableAtomOptions<T, J> = {
39
- key: fullKey,
40
- default: () => options.default(key),
41
- toJson: options.toJson,
42
- fromJson: options.fromJson,
43
- mutable: true,
44
- }
45
- if (options.effects) {
46
- individualOptions.effects = options.effects(key)
47
- }
48
-
49
- token = createMutableAtom(individualOptions, family, store)
50
34
 
51
- subject.next(token)
35
+ const individualOptions: MutableAtomOptions<T, J> = {
36
+ key: fullKey,
37
+ default: () => options.default(key),
38
+ toJson: options.toJson,
39
+ fromJson: options.fromJson,
40
+ mutable: true,
41
+ }
42
+ if (options.effects) {
43
+ individualOptions.effects = options.effects(key)
52
44
  }
45
+
46
+ const token = createMutableAtom(individualOptions, family, target)
47
+
48
+ subject.next(token)
53
49
  return token
54
50
  },
55
51
  {
@@ -60,10 +56,8 @@ export function createMutableAtomFamily<
60
56
  toJson: options.toJson,
61
57
  fromJson: options.fromJson,
62
58
  } as const,
63
- )
64
-
65
- const target = newest(store)
66
- target.families.set(options.key, atomFamily)
59
+ ) satisfies MutableAtomFamily<T, J, K>
60
+ store.families.set(options.key, atomFamily)
67
61
  selectJsonFamily(atomFamily, options, store)
68
62
  new FamilyTracker(atomFamily, store)
69
63
  return atomFamily
@@ -88,7 +88,9 @@ export function createMutableAtom<
88
88
  }
89
89
 
90
90
  new Tracker(token, store)
91
- selectJson(token, options, store)
91
+ if (!family) {
92
+ selectJson(token, options, store)
93
+ }
92
94
 
93
95
  store.on.atomCreation.next(token)
94
96
 
@@ -1,4 +1,4 @@
1
- import type { MutableAtomFamily, WritableSelectorFamily } from "atom.io"
1
+ import type { MutableAtomFamilyToken, WritableSelectorFamily } from "atom.io"
2
2
  import type { Json } from "atom.io/json"
3
3
 
4
4
  import { newest } from "../lineage"
@@ -10,7 +10,7 @@ export const getJsonFamily = <
10
10
  SerializableCore extends Json.Serializable,
11
11
  Key extends string,
12
12
  >(
13
- mutableAtomFamily: MutableAtomFamily<Core, SerializableCore, Key>,
13
+ mutableAtomFamily: MutableAtomFamilyToken<Core, SerializableCore, Key>,
14
14
  store: Store,
15
15
  ): WritableSelectorFamily<SerializableCore, Key> => {
16
16
  const target = newest(store)
@@ -1,6 +1,14 @@
1
- import type { MutableAtomToken, WritableSelectorToken } from "atom.io"
1
+ import type {
2
+ MutableAtomToken,
3
+ WritableSelectorFamily,
4
+ WritableSelectorFamilyToken,
5
+ WritableSelectorToken,
6
+ } from "atom.io"
2
7
  import type { Json } from "atom.io/json"
3
8
 
9
+ import { findInStore } from "../families"
10
+ import { newest } from "../lineage"
11
+ import { type Store, withdraw } from "../store"
4
12
  import type { Transceiver } from "./transceiver"
5
13
 
6
14
  export const getJsonToken = <
@@ -8,19 +16,26 @@ export const getJsonToken = <
8
16
  SerializableCore extends Json.Serializable,
9
17
  >(
10
18
  mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
19
+ store: Store,
11
20
  ): WritableSelectorToken<SerializableCore> => {
12
- const key = mutableAtomToken.family
13
- ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})`
14
- : `${mutableAtomToken.key}:JSON`
15
- const jsonToken: WritableSelectorToken<SerializableCore> = {
16
- type: `selector`,
17
- key,
18
- }
19
21
  if (mutableAtomToken.family) {
20
- jsonToken.family = {
21
- key: `${mutableAtomToken.family.key}:JSON`,
22
- subKey: mutableAtomToken.family.subKey,
22
+ const target = newest(store)
23
+ const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`
24
+ const jsonFamilyToken: WritableSelectorFamilyToken<
25
+ SerializableCore,
26
+ string
27
+ > = {
28
+ key: jsonFamilyKey,
29
+ type: `selector_family`,
23
30
  }
31
+ const family = withdraw(jsonFamilyToken, target)
32
+ const subKey = JSON.parse(mutableAtomToken.family.subKey)
33
+ const jsonToken = findInStore(family, subKey, store)
34
+ return jsonToken
35
+ }
36
+ const token: WritableSelectorToken<SerializableCore> = {
37
+ type: `selector`,
38
+ key: `${mutableAtomToken.key}:JSON`,
24
39
  }
25
- return jsonToken
40
+ return token
26
41
  }
@@ -2,7 +2,7 @@ import type { MutableAtomFamily, RegularAtomFamily } from "atom.io"
2
2
  import type { Json } from "atom.io/json"
3
3
  import { parseJson } from "atom.io/json"
4
4
 
5
- import { createRegularAtomFamily } from "../families"
5
+ import { createRegularAtomFamily, seekInStore } from "../families"
6
6
  import type { Store } from "../store"
7
7
  import { Tracker } from "./tracker"
8
8
  import type { Transceiver } from "./transceiver"
@@ -15,44 +15,46 @@ export class FamilyTracker<
15
15
  ? Signal
16
16
  : never
17
17
 
18
- public readonly findLatestUpdateState: RegularAtomFamily<
18
+ public readonly latestUpdateAtoms: RegularAtomFamily<
19
19
  typeof this.Update | null,
20
20
  FamilyMemberKey
21
21
  >
22
- public readonly findMutableState: MutableAtomFamily<Core, any, FamilyMemberKey>
22
+ public readonly mutableAtoms: MutableAtomFamily<Core, any, FamilyMemberKey>
23
23
 
24
24
  public constructor(
25
- findMutableState: MutableAtomFamily<Core, any, FamilyMemberKey>,
25
+ mutableAtoms: MutableAtomFamily<Core, any, FamilyMemberKey>,
26
26
  store: Store,
27
27
  ) {
28
- this.findLatestUpdateState = createRegularAtomFamily<
28
+ this.latestUpdateAtoms = createRegularAtomFamily<
29
29
  typeof this.Update | null,
30
30
  FamilyMemberKey
31
31
  >(
32
32
  {
33
- key: `*${findMutableState.key}`,
33
+ key: `*${mutableAtoms.key}`,
34
34
  default: null,
35
35
  },
36
36
  store,
37
37
  )
38
- this.findMutableState = findMutableState
39
- this.findMutableState.subject.subscribe(
38
+ this.mutableAtoms = mutableAtoms
39
+ this.mutableAtoms.subject.subscribe(
40
40
  `store=${store.config.name}::tracker-atom-family`,
41
41
  (atomToken) => {
42
42
  if (atomToken.family) {
43
43
  const key = parseJson(atomToken.family.subKey) as FamilyMemberKey
44
- this.findLatestUpdateState(key)
44
+ seekInStore(this.latestUpdateAtoms, key, store)
45
45
  new Tracker<Core>(atomToken, store)
46
46
  }
47
47
  },
48
48
  )
49
- this.findLatestUpdateState.subject.subscribe(
49
+ this.latestUpdateAtoms.subject.subscribe(
50
50
  `store=${store.config.name}::tracker-atom-family`,
51
51
  (atomToken) => {
52
52
  if (atomToken.family) {
53
53
  const key = parseJson(atomToken.family.subKey) as FamilyMemberKey
54
- const mutableAtomToken = this.findMutableState(key)
55
- new Tracker<Core>(mutableAtomToken, store)
54
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store)
55
+ if (mutableAtomToken) {
56
+ new Tracker<Core>(mutableAtomToken, store)
57
+ }
56
58
  }
57
59
  },
58
60
  )
@@ -16,10 +16,18 @@ type AtomIOToken =
16
16
  | TransactionToken<any>
17
17
 
18
18
  function prettyPrintTokenType(token: AtomIOToken) {
19
- if (token.type === `readonly_selector`) {
20
- return `Readonly Selector`
19
+ switch (token.type) {
20
+ case `atom_family`:
21
+ return `Atom Family`
22
+ case `readonly_selector`:
23
+ return `Readonly Selector`
24
+ case `readonly_selector_family`:
25
+ return `Readonly Selector Family`
26
+ case `selector_family`:
27
+ return `Selector Family`
28
+ default:
29
+ return capitalize(token.type)
21
30
  }
22
- return capitalize(token.type)
23
31
  }
24
32
 
25
33
  export class NotFoundError extends Error {
@@ -19,9 +19,9 @@ export const createReadonlySelector = <T>(
19
19
  const target = newest(store)
20
20
  const subject = new Subject<{ newValue: T; oldValue: T }>()
21
21
 
22
- const { get, find } = registerSelector(options.key, target)
22
+ const { get, find, seek } = registerSelector(options.key, target)
23
23
  const getSelf = () => {
24
- const value = options.get({ get, find })
24
+ const value = options.get({ get, find, seek })
25
25
  cacheValue(options.key, value, subject, newest(store))
26
26
  return value
27
27
  }
@@ -22,8 +22,8 @@ export const createWritableSelector = <T>(
22
22
  const target = newest(store)
23
23
  const subject = new Subject<{ newValue: T; oldValue: T }>()
24
24
  const transactors = registerSelector(options.key, target)
25
- const { find, get } = transactors
26
- const readonlyTransactors = { find, get }
25
+ const { find, get, seek } = transactors
26
+ const readonlyTransactors = { find, get, seek }
27
27
 
28
28
  const getSelf = () => {
29
29
  const value = options.get(readonlyTransactors)
@@ -9,30 +9,47 @@ export function disposeSelector(
9
9
  ): void {
10
10
  const target = newest(store)
11
11
  const { key } = selectorToken
12
- switch (selectorToken.type) {
13
- case `selector`:
14
- target.selectors.delete(key)
15
- break
16
- case `readonly_selector`:
17
- target.readonlySelectors.delete(key)
18
- break
19
- }
20
- target.valueMap.delete(key)
21
- target.selectorAtoms.delete(key)
22
- const downstreamTokens = target.selectorGraph
23
- .getRelationEntries({ upstreamSelectorKey: key })
24
- .filter(([_, { source }]) => source === key)
25
- .map(
26
- ([downstreamSelectorKey]) =>
27
- target.selectors.get(downstreamSelectorKey) ??
28
- target.readonlySelectors.get(downstreamSelectorKey),
12
+ const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key)
13
+ if (!selector) {
14
+ store.logger.error(
15
+ `❌`,
16
+ `selector`,
17
+ key,
18
+ `Tried to dispose selector, but it does not exist in the store.`,
19
+ )
20
+ } else if (!selector.family) {
21
+ store.logger.error(
22
+ `❌`,
23
+ `selector`,
24
+ key,
25
+ `Standalone selectors cannot be disposed.`,
29
26
  )
30
- for (const downstreamToken of downstreamTokens) {
31
- if (downstreamToken) {
32
- disposeSelector(downstreamToken, store)
27
+ } else {
28
+ switch (selectorToken.type) {
29
+ case `selector`:
30
+ target.selectors.delete(key)
31
+ break
32
+ case `readonly_selector`:
33
+ target.readonlySelectors.delete(key)
34
+ break
35
+ }
36
+ target.valueMap.delete(key)
37
+ target.selectorAtoms.delete(key)
38
+ const downstreamTokens = target.selectorGraph
39
+ .getRelationEntries({ upstreamSelectorKey: key })
40
+ .filter(([_, { source }]) => source === key)
41
+ .map(
42
+ ([downstreamSelectorKey]) =>
43
+ target.selectors.get(downstreamSelectorKey) ??
44
+ target.readonlySelectors.get(downstreamSelectorKey),
45
+ )
46
+ for (const downstreamToken of downstreamTokens) {
47
+ if (downstreamToken) {
48
+ disposeSelector(downstreamToken, store)
49
+ }
33
50
  }
51
+ target.selectorGraph.delete(key)
52
+ store.logger.info(`🔥`, selectorToken.type, key, `deleted`)
53
+ store.on.selectorDisposal.next(selectorToken)
34
54
  }
35
- target.selectorGraph.delete(key)
36
- store.logger.info(`🔥`, selectorToken.type, key, `deleted`)
37
- store.on.selectorDisposal.next(selectorToken)
38
55
  }