atom.io 0.22.0 → 0.23.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 (79) hide show
  1. package/data/dist/index.cjs +17 -1
  2. package/data/dist/index.js +1 -1
  3. package/data/src/join.ts +30 -1
  4. package/dist/chunk-6MLFYN32.js +18 -0
  5. package/dist/{chunk-JA4V7TJY.js → chunk-7DT3PVS3.js} +18 -2
  6. package/dist/chunk-OAYGID5B.js +27 -0
  7. package/dist/index.cjs +2 -11
  8. package/dist/index.d.ts +51 -23
  9. package/dist/index.js +2 -11
  10. package/eslint-plugin/dist/index.cjs +0 -1
  11. package/eslint-plugin/dist/index.js +0 -1
  12. package/eslint-plugin/src/rules/lifespan.ts +0 -1
  13. package/immortal/dist/index.cjs +180 -20
  14. package/immortal/dist/index.js +134 -19
  15. package/immortal/src/index.ts +1 -0
  16. package/immortal/src/make-molecule.ts +222 -0
  17. package/immortal/src/molecule.ts +49 -16
  18. package/immortal/src/seek-state.ts +15 -2
  19. package/internal/dist/index.cjs +1119 -754
  20. package/internal/dist/index.d.ts +109 -12
  21. package/internal/dist/index.js +1098 -760
  22. package/internal/src/atom/create-regular-atom.ts +0 -2
  23. package/internal/src/atom/create-standalone-atom.ts +6 -2
  24. package/internal/src/atom/dispose-atom.ts +22 -2
  25. package/internal/src/families/create-readonly-selector-family.ts +7 -2
  26. package/internal/src/families/create-regular-atom-family.ts +6 -2
  27. package/internal/src/families/create-writable-selector-family.ts +7 -2
  28. package/internal/src/families/dispose-from-store.ts +22 -0
  29. package/internal/src/families/find-in-store.ts +0 -1
  30. package/internal/src/families/index.ts +1 -0
  31. package/internal/src/families/init-family-member.ts +22 -1
  32. package/internal/src/families/seek-in-store.ts +23 -6
  33. package/internal/src/ingest-updates/index.ts +1 -0
  34. package/internal/src/ingest-updates/ingest-creation-disposal.ts +104 -0
  35. package/internal/src/ingest-updates/ingest-transaction-update.ts +26 -4
  36. package/internal/src/mutable/create-mutable-atom-family.ts +6 -2
  37. package/internal/src/mutable/create-mutable-atom.ts +0 -2
  38. package/internal/src/mutable/get-json-token.ts +0 -1
  39. package/internal/src/mutable/tracker-family.ts +7 -7
  40. package/internal/src/not-found-error.ts +5 -0
  41. package/internal/src/selector/create-readonly-selector.ts +2 -3
  42. package/internal/src/selector/create-standalone-selector.ts +6 -2
  43. package/internal/src/selector/create-writable-selector.ts +2 -3
  44. package/internal/src/selector/dispose-selector.ts +32 -5
  45. package/internal/src/selector/register-selector.ts +2 -0
  46. package/internal/src/set-state/stow-update.ts +5 -1
  47. package/internal/src/store/deposit.ts +41 -7
  48. package/internal/src/store/store.ts +11 -0
  49. package/internal/src/store/withdraw.ts +28 -1
  50. package/internal/src/timeline/add-atom-to-timeline.ts +206 -182
  51. package/internal/src/timeline/create-timeline.ts +181 -60
  52. package/internal/src/timeline/time-travel.ts +20 -0
  53. package/internal/src/transaction/apply-transaction.ts +2 -12
  54. package/internal/src/transaction/build-transaction.ts +11 -2
  55. package/introspection/dist/index.cjs +2 -1
  56. package/introspection/dist/index.js +2 -1
  57. package/introspection/src/attach-timeline-family.ts +1 -0
  58. package/json/dist/index.cjs +3 -3
  59. package/json/dist/index.js +6 -5
  60. package/json/src/select-json-family.ts +3 -4
  61. package/package.json +5 -5
  62. package/react-devtools/dist/index.cjs +58 -47
  63. package/react-devtools/dist/index.js +60 -48
  64. package/react-devtools/src/TimelineIndex.tsx +15 -13
  65. package/react-devtools/src/Updates.tsx +41 -32
  66. package/realtime-server/dist/index.cjs +21 -10
  67. package/realtime-server/dist/index.d.ts +1 -1
  68. package/realtime-server/dist/index.js +21 -11
  69. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +21 -11
  70. package/realtime-testing/dist/index.cjs +1 -0
  71. package/realtime-testing/dist/index.js +1 -1
  72. package/src/atom.ts +9 -3
  73. package/src/dispose-state.ts +3 -12
  74. package/src/index.ts +4 -0
  75. package/src/selector.ts +3 -3
  76. package/src/subscribe.ts +8 -4
  77. package/src/timeline.ts +18 -1
  78. package/src/transaction.ts +56 -4
  79. package/dist/chunk-BF4MVQF6.js +0 -44
@@ -1,6 +1,5 @@
1
1
  import type {
2
2
  FamilyMetadata,
3
- MutableAtomOptions,
4
3
  RegularAtomOptions,
5
4
  RegularAtomToken,
6
5
  UpdateHandler,
@@ -85,6 +84,5 @@ export function createRegularAtom<T>(
85
84
  }
86
85
  }
87
86
  }
88
- store.on.atomCreation.next(token)
89
87
  return token
90
88
  }
@@ -27,7 +27,11 @@ export function createStandaloneAtom<T>(
27
27
  const isMutable = `mutable` in options
28
28
 
29
29
  if (isMutable) {
30
- return createMutableAtom(options, undefined, store)
30
+ const state = createMutableAtom(options, undefined, store)
31
+ store.on.atomCreation.next(state)
32
+ return state
31
33
  }
32
- return createRegularAtom(options, undefined, store)
34
+ const state = createRegularAtom(options, undefined, store)
35
+ store.on.atomCreation.next(state)
36
+ return state
33
37
  }
@@ -1,7 +1,13 @@
1
1
  import type { AtomToken } from "atom.io"
2
2
 
3
3
  import type { Store } from ".."
4
- import { disposeSelector, getUpdateToken, newest } from ".."
4
+ import {
5
+ disposeSelector,
6
+ getUpdateToken,
7
+ isChildStore,
8
+ newest,
9
+ withdraw,
10
+ } from ".."
5
11
 
6
12
  export function disposeAtom(atomToken: AtomToken<unknown>, store: Store): void {
7
13
  const target = newest(store)
@@ -18,6 +24,13 @@ export function disposeAtom(atomToken: AtomToken<unknown>, store: Store): void {
18
24
  store.logger.error(`❌`, `atom`, key, `Standalone atoms cannot be disposed.`)
19
25
  } else {
20
26
  atom.cleanup?.()
27
+ const lastValue = store.valueMap.get(atom.key)
28
+ const family = withdraw({ key: atom.family.key, type: `atom_family` }, store)
29
+ family.subject.next({
30
+ type: `state_disposal`,
31
+ token: atomToken,
32
+ value: lastValue,
33
+ })
21
34
  target.atoms.delete(key)
22
35
  target.valueMap.delete(key)
23
36
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key)
@@ -40,6 +53,13 @@ export function disposeAtom(atomToken: AtomToken<unknown>, store: Store): void {
40
53
  store.trackers.delete(key)
41
54
  }
42
55
  store.logger.info(`🔥`, `atom`, key, `deleted`)
43
- store.on.atomDisposal.next(atomToken)
56
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
57
+ target.transactionMeta.update.updates.push({
58
+ type: `state_disposal`,
59
+ token: atomToken,
60
+ })
61
+ } else {
62
+ store.on.atomDisposal.next(atomToken)
63
+ }
44
64
  }
45
65
  }
@@ -3,6 +3,8 @@ import type {
3
3
  ReadonlySelectorFamily,
4
4
  ReadonlySelectorFamilyOptions,
5
5
  ReadonlySelectorToken,
6
+ StateCreation,
7
+ StateDisposal,
6
8
  } from "atom.io"
7
9
  import type { Json } from "atom.io/json"
8
10
  import { stringifyJson } from "atom.io/json"
@@ -16,7 +18,10 @@ export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
16
18
  options: ReadonlySelectorFamilyOptions<T, K>,
17
19
  store: Store,
18
20
  ): ReadonlySelectorFamily<T, K> {
19
- const subject = new Subject<ReadonlySelectorToken<T>>()
21
+ const subject = new Subject<
22
+ | StateCreation<ReadonlySelectorToken<T>>
23
+ | StateDisposal<ReadonlySelectorToken<T>>
24
+ >()
20
25
 
21
26
  const readonlySelectorFamily = Object.assign(
22
27
  (key: K): ReadonlySelectorToken<T> => {
@@ -34,7 +39,7 @@ export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
34
39
  target,
35
40
  )
36
41
 
37
- subject.next(token)
42
+ subject.next({ type: `state_creation`, token })
38
43
  return token
39
44
  },
40
45
  {
@@ -4,6 +4,8 @@ import type {
4
4
  RegularAtomFamilyOptions,
5
5
  RegularAtomOptions,
6
6
  RegularAtomToken,
7
+ StateCreation,
8
+ StateDisposal,
7
9
  } from "atom.io"
8
10
  import type { Json } from "atom.io/json"
9
11
  import { stringifyJson } from "atom.io/json"
@@ -17,7 +19,9 @@ export function createRegularAtomFamily<T, K extends Json.Serializable>(
17
19
  options: RegularAtomFamilyOptions<T, K>,
18
20
  store: Store,
19
21
  ): RegularAtomFamily<T, K> {
20
- const subject = new Subject<RegularAtomToken<T>>()
22
+ const subject = new Subject<
23
+ StateCreation<RegularAtomToken<T>> | StateDisposal<RegularAtomToken<T>>
24
+ >()
21
25
 
22
26
  const atomFamily: RegularAtomFamily<T, K> = Object.assign(
23
27
  (key: K): RegularAtomToken<any> => {
@@ -37,7 +41,7 @@ export function createRegularAtomFamily<T, K extends Json.Serializable>(
37
41
 
38
42
  const token = createRegularAtom(individualOptions, family, target)
39
43
 
40
- subject.next(token)
44
+ subject.next({ type: `state_creation`, token })
41
45
  return token
42
46
  },
43
47
  {
@@ -1,5 +1,7 @@
1
1
  import type {
2
2
  FamilyMetadata,
3
+ StateCreation,
4
+ StateDisposal,
3
5
  WritableSelectorFamily,
4
6
  WritableSelectorFamilyOptions,
5
7
  WritableSelectorToken,
@@ -16,7 +18,10 @@ export function createWritableSelectorFamily<T, K extends Json.Serializable>(
16
18
  options: WritableSelectorFamilyOptions<T, K>,
17
19
  store: Store,
18
20
  ): WritableSelectorFamily<T, K> {
19
- const subject = new Subject<WritableSelectorToken<T>>()
21
+ const subject = new Subject<
22
+ | StateCreation<WritableSelectorToken<T>>
23
+ | StateDisposal<WritableSelectorToken<T>>
24
+ >()
20
25
 
21
26
  const selectorFamily = Object.assign(
22
27
  (key: K): WritableSelectorToken<T> => {
@@ -35,7 +40,7 @@ export function createWritableSelectorFamily<T, K extends Json.Serializable>(
35
40
  target,
36
41
  )
37
42
 
38
- subject.next(token)
43
+ subject.next({ type: `state_creation`, token })
39
44
  return token
40
45
  },
41
46
  {
@@ -0,0 +1,22 @@
1
+ import type { ReadableToken } from "atom.io"
2
+ import { disposeMolecule, type MoleculeToken } from "atom.io/immortal"
3
+ import * as Internal from "atom.io/internal"
4
+
5
+ export function disposeFromStore(
6
+ token: MoleculeToken<any, any, any> | ReadableToken<any>,
7
+ store: Internal.Store = Internal.IMPLICIT.STORE,
8
+ ): void {
9
+ switch (token.type) {
10
+ case `atom`:
11
+ case `mutable_atom`:
12
+ Internal.disposeAtom(token, store)
13
+ break
14
+ case `selector`:
15
+ case `readonly_selector`:
16
+ Internal.disposeSelector(token, store)
17
+ break
18
+ case `molecule`:
19
+ disposeMolecule(token, store)
20
+ break
21
+ }
22
+ }
@@ -19,7 +19,6 @@ import type {
19
19
  import type { Json } from "atom.io/json"
20
20
 
21
21
  import type { Transceiver } from "../mutable"
22
- import { NotFoundError } from "../not-found-error"
23
22
  import type { Store } from "../store"
24
23
  import { initFamilyMember } from "./init-family-member"
25
24
  import { seekInStore } from "./seek-in-store"
@@ -2,6 +2,7 @@ export * from "./create-atom-family"
2
2
  export * from "./create-readonly-selector-family"
3
3
  export * from "./create-regular-atom-family"
4
4
  export * from "./create-selector-family"
5
+ export * from "./dispose-from-store"
5
6
  export * from "./find-in-store"
6
7
  export * from "./init-family-member"
7
8
  export * from "./seek-in-store"
@@ -18,10 +18,11 @@ import type {
18
18
  } from "atom.io"
19
19
  import type { Json } from "atom.io/json"
20
20
 
21
+ import { newest } from "../lineage"
21
22
  import type { Transceiver } from "../mutable"
22
23
  import { NotFoundError } from "../not-found-error"
23
24
  import type { Store } from "../store"
24
- import { seekInStore } from "./seek-in-store"
25
+ import { isChildStore } from "../transaction"
25
26
 
26
27
  export function initFamilyMember<
27
28
  T extends Transceiver<any>,
@@ -87,5 +88,25 @@ export function initFamilyMember(
87
88
  throw new NotFoundError(token, store)
88
89
  }
89
90
  const state = family(key)
91
+ const target = newest(store)
92
+ if (state.family) {
93
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
94
+ target.transactionMeta.update.updates.push({
95
+ type: `state_creation`,
96
+ token: state,
97
+ })
98
+ } else {
99
+ switch (state.type) {
100
+ case `atom`:
101
+ case `mutable_atom`:
102
+ store.on.atomCreation.next(state)
103
+ break
104
+ case `selector`:
105
+ case `readonly_selector`:
106
+ store.on.selectorCreation.next(state)
107
+ break
108
+ }
109
+ }
110
+ }
90
111
  return state
91
112
  }
@@ -16,6 +16,11 @@ import type {
16
16
  WritableSelectorToken,
17
17
  WritableToken,
18
18
  } from "atom.io"
19
+ import type {
20
+ Molecule,
21
+ MoleculeFamilyToken,
22
+ MoleculeToken,
23
+ } from "atom.io/immortal"
19
24
  import { type Json, stringifyJson } from "atom.io/json"
20
25
 
21
26
  import type { ReadableState } from ".."
@@ -76,28 +81,40 @@ export function seekInStore<T, K extends Json.Serializable, Key extends K>(
76
81
  store: Store,
77
82
  ): ReadableToken<T> | undefined
78
83
 
84
+ export function seekInStore<
85
+ K extends Json.Serializable,
86
+ S extends { [key: string]: any },
87
+ >(
88
+ token: MoleculeFamilyToken<K, S, any[]>,
89
+ key: K,
90
+ store: Store,
91
+ ): MoleculeToken<K, S, any[]> | undefined
92
+
79
93
  export function seekInStore(
80
- token: ReadableFamilyToken<any, any>,
94
+ token: MoleculeFamilyToken<any, any, any> | ReadableFamilyToken<any, any>,
81
95
  key: Json.Serializable,
82
96
  store: Store,
83
- ): ReadableToken<any> | undefined {
97
+ ): MoleculeToken<any, any, any> | ReadableToken<any> | undefined {
84
98
  const subKey = stringifyJson(key)
85
99
  const fullKey = `${token.key}(${subKey})`
86
100
  const target = newest(store)
87
- let state: ReadableState<any> | undefined
101
+ let state: Molecule<any> | ReadableState<any> | undefined
88
102
  switch (token.type) {
89
103
  case `atom_family`:
90
104
  case `mutable_atom_family`:
91
105
  state = target.atoms.get(fullKey)
92
106
  break
93
-
94
- case `selector_family`: {
107
+ case `selector_family`:
95
108
  state = target.selectors.get(fullKey)
96
109
  break
97
- }
98
110
  case `readonly_selector_family`:
99
111
  state = target.readonlySelectors.get(fullKey)
100
112
  break
113
+ case `molecule_family`:
114
+ state = target.molecules.get(stringifyJson(key))
115
+ if (state) {
116
+ return deposit(state)
117
+ }
101
118
  }
102
119
  if (state) {
103
120
  return deposit(state)
@@ -1,3 +1,4 @@
1
1
  export * from "./ingest-atom-update"
2
+ export * from "./ingest-creation-disposal.ts"
2
3
  export * from "./ingest-selector-update"
3
4
  export * from "./ingest-transaction-update"
@@ -0,0 +1,104 @@
1
+ import { parseJson } from "anvl/json"
2
+ import type {
3
+ MoleculeCreation,
4
+ MoleculeDisposal,
5
+ ReadableToken,
6
+ StateCreation,
7
+ StateDisposal,
8
+ } from "atom.io"
9
+ import { disposeMolecule, makeMoleculeInStore } from "atom.io/immortal"
10
+
11
+ import { disposeFromStore, initFamilyMember } from "../families"
12
+ import type { Store } from "../store"
13
+
14
+ export function ingestCreationEvent(
15
+ update: StateCreation<any>,
16
+ applying: `newValue` | `oldValue`,
17
+ store: Store,
18
+ ): void {
19
+ switch (applying) {
20
+ case `newValue`: {
21
+ createInStore(update.token, store)
22
+ break
23
+ }
24
+ case `oldValue`: {
25
+ disposeFromStore(update.token, store)
26
+ break
27
+ }
28
+ }
29
+ }
30
+
31
+ export function ingestDisposalEvent(
32
+ update: StateDisposal<any>,
33
+ applying: `newValue` | `oldValue`,
34
+ store: Store,
35
+ ): void {
36
+ switch (applying) {
37
+ case `newValue`: {
38
+ disposeFromStore(update.token, store)
39
+ break
40
+ }
41
+ case `oldValue`: {
42
+ createInStore(update.token, store)
43
+ store.valueMap.set(update.token.key, update.value)
44
+ break
45
+ }
46
+ }
47
+ }
48
+
49
+ function createInStore(token: ReadableToken<any>, store: Store): void {
50
+ if (token.family) {
51
+ const family = store.families.get(token.family.key)
52
+ if (family) {
53
+ const molecule = store.molecules.get(token.family.subKey)
54
+ if (molecule) {
55
+ molecule.bond(family)
56
+ return
57
+ }
58
+ if (store.config.lifespan === `immortal`) {
59
+ throw new Error(`No molecule found for key "${token.family.subKey}"`)
60
+ }
61
+ initFamilyMember(family, parseJson(token.family.subKey), store)
62
+ }
63
+ }
64
+ }
65
+
66
+ export function ingestMoleculeCreationEvent(
67
+ update: MoleculeCreation<any>,
68
+ applying: `newValue` | `oldValue`,
69
+ store: Store,
70
+ ): void {
71
+ switch (applying) {
72
+ case `newValue`:
73
+ makeMoleculeInStore(
74
+ store,
75
+ update.context[0],
76
+ update.family,
77
+ update.token.key,
78
+ ...update.params,
79
+ )
80
+ break
81
+ case `oldValue`:
82
+ disposeMolecule(update.token, store)
83
+ break
84
+ }
85
+ }
86
+ export function ingestMoleculeDisposalEvent(
87
+ update: MoleculeDisposal<any>,
88
+ applying: `newValue` | `oldValue`,
89
+ store: Store,
90
+ ): void {
91
+ switch (applying) {
92
+ case `newValue`:
93
+ disposeMolecule(update.token, store)
94
+ break
95
+ case `oldValue`:
96
+ makeMoleculeInStore(
97
+ store,
98
+ update.context[0],
99
+ update.family,
100
+ update.token.key,
101
+ )
102
+ break
103
+ }
104
+ }
@@ -2,6 +2,12 @@ import type { TransactionUpdate } from "atom.io"
2
2
 
3
3
  import type { Store } from "../store"
4
4
  import { ingestAtomUpdate } from "./ingest-atom-update"
5
+ import {
6
+ ingestCreationEvent,
7
+ ingestDisposalEvent,
8
+ ingestMoleculeCreationEvent,
9
+ ingestMoleculeDisposalEvent,
10
+ } from "./ingest-creation-disposal"
5
11
 
6
12
  export function ingestTransactionUpdate(
7
13
  applying: `newValue` | `oldValue`,
@@ -13,10 +19,26 @@ export function ingestTransactionUpdate(
13
19
  ? transactionUpdate.updates
14
20
  : [...transactionUpdate.updates].reverse()
15
21
  for (const updateFromTransaction of updates) {
16
- if (`newValue` in updateFromTransaction) {
17
- ingestAtomUpdate(applying, updateFromTransaction, store)
18
- } else {
19
- ingestTransactionUpdate(applying, updateFromTransaction, store)
22
+ switch (updateFromTransaction.type) {
23
+ case `atom_update`:
24
+ case `selector_update`:
25
+ ingestAtomUpdate(applying, updateFromTransaction, store)
26
+ break
27
+ case `state_creation`:
28
+ ingestCreationEvent(updateFromTransaction, applying, store)
29
+ break
30
+ case `state_disposal`:
31
+ ingestDisposalEvent(updateFromTransaction, applying, store)
32
+ break
33
+ case `molecule_creation`:
34
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store)
35
+ break
36
+ case `molecule_disposal`:
37
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store)
38
+ break
39
+ case `transaction_update`:
40
+ ingestTransactionUpdate(applying, updateFromTransaction, store)
41
+ break
20
42
  }
21
43
  }
22
44
  }
@@ -4,6 +4,8 @@ import type {
4
4
  MutableAtomFamilyOptions,
5
5
  MutableAtomOptions,
6
6
  MutableAtomToken,
7
+ StateCreation,
8
+ StateDisposal,
7
9
  } from "atom.io"
8
10
  import type { Json } from "atom.io/json"
9
11
  import { selectJsonFamily, stringifyJson } from "atom.io/json"
@@ -23,7 +25,9 @@ export function createMutableAtomFamily<
23
25
  options: MutableAtomFamilyOptions<T, J, K>,
24
26
  store: Store,
25
27
  ): MutableAtomFamily<T, J, K> {
26
- const subject = new Subject<MutableAtomToken<T, J>>()
28
+ const subject = new Subject<
29
+ StateCreation<MutableAtomToken<T, J>> | StateDisposal<MutableAtomToken<T, J>>
30
+ >()
27
31
 
28
32
  const atomFamily = Object.assign(
29
33
  (key: K): MutableAtomToken<T, J> => {
@@ -45,7 +49,7 @@ export function createMutableAtomFamily<
45
49
 
46
50
  const token = createMutableAtom(individualOptions, family, target)
47
51
 
48
- subject.next(token)
52
+ subject.next({ type: `state_creation`, token })
49
53
  return token
50
54
  },
51
55
  {
@@ -92,7 +92,5 @@ export function createMutableAtom<
92
92
  selectJson(token, options, store)
93
93
  }
94
94
 
95
- store.on.atomCreation.next(token)
96
-
97
95
  return token
98
96
  }
@@ -1,6 +1,5 @@
1
1
  import type {
2
2
  MutableAtomToken,
3
- WritableSelectorFamily,
4
3
  WritableSelectorFamilyToken,
5
4
  WritableSelectorToken,
6
5
  } from "atom.io"
@@ -38,19 +38,19 @@ export class FamilyTracker<
38
38
  this.mutableAtoms = mutableAtoms
39
39
  this.mutableAtoms.subject.subscribe(
40
40
  `store=${store.config.name}::tracker-atom-family`,
41
- (atomToken) => {
42
- if (atomToken.family) {
43
- const key = parseJson(atomToken.family.subKey) as FamilyMemberKey
41
+ (event) => {
42
+ if (event.token.family) {
43
+ const key = parseJson(event.token.family.subKey) as FamilyMemberKey
44
44
  seekInStore(this.latestUpdateAtoms, key, store)
45
- new Tracker<Core>(atomToken, store)
45
+ new Tracker<Core>(event.token, store)
46
46
  }
47
47
  },
48
48
  )
49
49
  this.latestUpdateAtoms.subject.subscribe(
50
50
  `store=${store.config.name}::tracker-atom-family`,
51
- (atomToken) => {
52
- if (atomToken.family) {
53
- const key = parseJson(atomToken.family.subKey) as FamilyMemberKey
51
+ (event) => {
52
+ if (event.token.family) {
53
+ const key = parseJson(event.token.family.subKey) as FamilyMemberKey
54
54
  const mutableAtomToken = seekInStore(this.mutableAtoms, key, store)
55
55
  if (mutableAtomToken) {
56
56
  new Tracker<Core>(mutableAtomToken, store)
@@ -4,12 +4,15 @@ import type {
4
4
  TimelineToken,
5
5
  TransactionToken,
6
6
  } from "atom.io"
7
+ import type { MoleculeFamilyToken, MoleculeToken } from "atom.io/immortal"
7
8
 
8
9
  import type { Store } from "./store"
9
10
 
10
11
  const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1)
11
12
 
12
13
  type AtomIOToken =
14
+ | MoleculeFamilyToken<any, any, any>
15
+ | MoleculeToken<any, any, any>
13
16
  | ReadableFamilyToken<any, any>
14
17
  | ReadableToken<any>
15
18
  | TimelineToken<any>
@@ -19,6 +22,8 @@ function prettyPrintTokenType(token: AtomIOToken) {
19
22
  switch (token.type) {
20
23
  case `atom_family`:
21
24
  return `Atom Family`
25
+ case `molecule_family`:
26
+ return `Molecule Family`
22
27
  case `readonly_selector`:
23
28
  return `Readonly Selector`
24
29
  case `readonly_selector_family`:
@@ -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, seek } = registerSelector(options.key, target)
22
+ const { get, find, seek, json } = registerSelector(options.key, target)
23
23
  const getSelf = () => {
24
- const value = options.get({ get, find, seek })
24
+ const value = options.get({ get, find, seek, json })
25
25
  cacheValue(options.key, value, subject, newest(store))
26
26
  return value
27
27
  }
@@ -50,6 +50,5 @@ export const createReadonlySelector = <T>(
50
50
  if (family) {
51
51
  token.family = family
52
52
  }
53
- store.on.selectorCreation.next(token)
54
53
  return token
55
54
  }
@@ -24,7 +24,11 @@ export function createStandaloneSelector<T>(
24
24
  const isWritable = `set` in options
25
25
 
26
26
  if (isWritable) {
27
- return createWritableSelector(options, undefined, store)
27
+ const state = createWritableSelector(options, undefined, store)
28
+ store.on.selectorCreation.next(state)
29
+ return state
28
30
  }
29
- return createReadonlySelector(options, undefined, store)
31
+ const state = createReadonlySelector(options, undefined, store)
32
+ store.on.selectorCreation.next(state)
33
+ return state
30
34
  }
@@ -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, seek } = transactors
26
- const readonlyTransactors = { find, get, seek }
25
+ const { find, get, seek, json } = transactors
26
+ const readonlyTransactors = { find, get, seek, json }
27
27
 
28
28
  const getSelf = () => {
29
29
  const value = options.get(readonlyTransactors)
@@ -70,6 +70,5 @@ export const createWritableSelector = <T>(
70
70
  if (family) {
71
71
  token.family = family
72
72
  }
73
- store.on.selectorCreation.next(token)
74
73
  return token
75
74
  }
@@ -1,7 +1,7 @@
1
1
  import type { ReadonlySelectorToken, WritableSelectorToken } from "atom.io"
2
2
 
3
3
  import type { Store } from ".."
4
- import { newest } from ".."
4
+ import { isChildStore, newest, withdraw } from ".."
5
5
 
6
6
  export function disposeSelector(
7
7
  selectorToken: ReadonlySelectorToken<unknown> | WritableSelectorToken<unknown>,
@@ -11,7 +11,7 @@ export function disposeSelector(
11
11
  const { key } = selectorToken
12
12
  const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key)
13
13
  if (!selector) {
14
- store.logger.error(
14
+ store.logger.info(
15
15
  `❌`,
16
16
  `selector`,
17
17
  key,
@@ -27,10 +27,30 @@ export function disposeSelector(
27
27
  } else {
28
28
  switch (selectorToken.type) {
29
29
  case `selector`:
30
- target.selectors.delete(key)
30
+ {
31
+ target.selectors.delete(key)
32
+ const family = withdraw(
33
+ { key: selector.family.key, type: `selector_family` },
34
+ store,
35
+ )
36
+ family.subject.next({
37
+ type: `state_disposal`,
38
+ token: selectorToken,
39
+ })
40
+ }
31
41
  break
32
42
  case `readonly_selector`:
33
- target.readonlySelectors.delete(key)
43
+ {
44
+ target.readonlySelectors.delete(key)
45
+ const family = withdraw(
46
+ { key: selector.family.key, type: `readonly_selector_family` },
47
+ store,
48
+ )
49
+ family.subject.next({
50
+ type: `state_disposal`,
51
+ token: selectorToken,
52
+ })
53
+ }
34
54
  break
35
55
  }
36
56
  target.valueMap.delete(key)
@@ -50,6 +70,13 @@ export function disposeSelector(
50
70
  }
51
71
  target.selectorGraph.delete(key)
52
72
  store.logger.info(`🔥`, selectorToken.type, key, `deleted`)
53
- store.on.selectorDisposal.next(selectorToken)
73
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
74
+ target.transactionMeta.update.updates.push({
75
+ type: `state_disposal`,
76
+ token: selectorToken,
77
+ })
78
+ } else {
79
+ store.on.selectorDisposal.next(selectorToken)
80
+ }
54
81
  }
55
82
  }