atom.io 0.22.0 → 0.23.1

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 (82) 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/ephemeral/dist/index.d.ts +12 -0
  11. package/eslint-plugin/dist/index.cjs +0 -1
  12. package/eslint-plugin/dist/index.d.ts +73 -0
  13. package/eslint-plugin/dist/index.js +0 -1
  14. package/eslint-plugin/src/rules/lifespan.ts +0 -1
  15. package/immortal/dist/index.cjs +180 -20
  16. package/immortal/dist/index.d.ts +103 -0
  17. package/immortal/dist/index.js +134 -19
  18. package/immortal/src/index.ts +1 -0
  19. package/immortal/src/make-molecule.ts +222 -0
  20. package/immortal/src/molecule.ts +49 -16
  21. package/immortal/src/seek-state.ts +15 -2
  22. package/internal/dist/index.cjs +1119 -754
  23. package/internal/dist/index.d.ts +109 -12
  24. package/internal/dist/index.js +1098 -760
  25. package/internal/src/atom/create-regular-atom.ts +0 -2
  26. package/internal/src/atom/create-standalone-atom.ts +6 -2
  27. package/internal/src/atom/dispose-atom.ts +22 -2
  28. package/internal/src/families/create-readonly-selector-family.ts +7 -2
  29. package/internal/src/families/create-regular-atom-family.ts +6 -2
  30. package/internal/src/families/create-writable-selector-family.ts +7 -2
  31. package/internal/src/families/dispose-from-store.ts +22 -0
  32. package/internal/src/families/find-in-store.ts +0 -1
  33. package/internal/src/families/index.ts +1 -0
  34. package/internal/src/families/init-family-member.ts +22 -1
  35. package/internal/src/families/seek-in-store.ts +23 -6
  36. package/internal/src/ingest-updates/index.ts +1 -0
  37. package/internal/src/ingest-updates/ingest-creation-disposal.ts +104 -0
  38. package/internal/src/ingest-updates/ingest-transaction-update.ts +26 -4
  39. package/internal/src/mutable/create-mutable-atom-family.ts +6 -2
  40. package/internal/src/mutable/create-mutable-atom.ts +0 -2
  41. package/internal/src/mutable/get-json-token.ts +0 -1
  42. package/internal/src/mutable/tracker-family.ts +7 -7
  43. package/internal/src/not-found-error.ts +5 -0
  44. package/internal/src/selector/create-readonly-selector.ts +2 -3
  45. package/internal/src/selector/create-standalone-selector.ts +6 -2
  46. package/internal/src/selector/create-writable-selector.ts +2 -3
  47. package/internal/src/selector/dispose-selector.ts +32 -5
  48. package/internal/src/selector/register-selector.ts +2 -0
  49. package/internal/src/set-state/stow-update.ts +5 -1
  50. package/internal/src/store/deposit.ts +41 -7
  51. package/internal/src/store/store.ts +11 -0
  52. package/internal/src/store/withdraw.ts +28 -1
  53. package/internal/src/timeline/add-atom-to-timeline.ts +206 -182
  54. package/internal/src/timeline/create-timeline.ts +181 -60
  55. package/internal/src/timeline/time-travel.ts +20 -0
  56. package/internal/src/transaction/apply-transaction.ts +2 -12
  57. package/internal/src/transaction/build-transaction.ts +11 -2
  58. package/introspection/dist/index.cjs +2 -1
  59. package/introspection/dist/index.js +2 -1
  60. package/introspection/src/attach-timeline-family.ts +1 -0
  61. package/json/dist/index.cjs +3 -3
  62. package/json/dist/index.js +6 -5
  63. package/json/src/select-json-family.ts +3 -4
  64. package/package.json +8 -5
  65. package/react-devtools/dist/index.cjs +58 -47
  66. package/react-devtools/dist/index.js +60 -48
  67. package/react-devtools/src/TimelineIndex.tsx +15 -13
  68. package/react-devtools/src/Updates.tsx +41 -32
  69. package/realtime-server/dist/index.cjs +21 -10
  70. package/realtime-server/dist/index.d.ts +1 -1
  71. package/realtime-server/dist/index.js +21 -11
  72. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +21 -11
  73. package/realtime-testing/dist/index.cjs +1 -0
  74. package/realtime-testing/dist/index.js +1 -1
  75. package/src/atom.ts +9 -3
  76. package/src/dispose-state.ts +3 -12
  77. package/src/index.ts +4 -0
  78. package/src/selector.ts +3 -3
  79. package/src/subscribe.ts +8 -4
  80. package/src/timeline.ts +18 -1
  81. package/src/transaction.ts +56 -4
  82. package/dist/chunk-BF4MVQF6.js +0 -44
@@ -5,6 +5,7 @@ import type { seekState } from "atom.io/immortal"
5
5
  import { findInStore, seekInStore } from "../families"
6
6
  import { readOrComputeValue } from "../get-state/read-or-compute-value"
7
7
  import { newest } from "../lineage"
8
+ import { getJsonToken } from "../mutable"
8
9
  import { setAtomOrSelector } from "../set-state"
9
10
  import type { Store } from "../store"
10
11
  import { withdraw } from "../store"
@@ -47,4 +48,5 @@ export const registerSelector = (
47
48
  },
48
49
  find: ((token, key) => findInStore(token, key, store)) as typeof findState,
49
50
  seek: ((token, key) => seekInStore(token, key, store)) as typeof seekState,
51
+ json: (token) => getJsonToken(token, store),
50
52
  })
@@ -38,7 +38,11 @@ export const stowUpdate = <T>(
38
38
  if (!shouldStow) {
39
39
  return
40
40
  }
41
- const atomUpdate: KeyedStateUpdate<T> = { key, ...update }
41
+ const atomUpdate: KeyedStateUpdate<T> = {
42
+ type: `atom_update`,
43
+ key,
44
+ ...update,
45
+ }
42
46
  if (state.family) {
43
47
  atomUpdate.family = state.family
44
48
  }
@@ -10,6 +10,13 @@ import type {
10
10
  WritableSelectorToken,
11
11
  WritableToken,
12
12
  } from "atom.io"
13
+ import type {
14
+ Molecule,
15
+ MoleculeFamily,
16
+ MoleculeFamilyToken,
17
+ MoleculeToken,
18
+ } from "atom.io/immortal"
19
+ import type { Json } from "atom.io/json"
13
20
 
14
21
  import type {
15
22
  Atom,
@@ -33,28 +40,55 @@ export function deposit<T>(state: WritableSelector<T>): WritableSelectorToken<T>
33
40
  export function deposit<T>(state: ReadonlySelector<T>): ReadonlySelectorToken<T>
34
41
  export function deposit<T>(state: Selector<T>): SelectorToken<T>
35
42
  export function deposit<T>(state: WritableState<T>): WritableToken<T>
43
+ export function deposit<
44
+ K extends Json.Serializable,
45
+ S extends { [key: string]: any },
46
+ P extends any[],
47
+ >(state: Molecule<K>): MoleculeToken<K, S, P>
48
+ export function deposit<
49
+ K extends Json.Serializable,
50
+ S extends { [key: string]: any },
51
+ P extends any[],
52
+ >(state: MoleculeFamily<K, S, P>): MoleculeFamilyToken<K, S, P>
36
53
  export function deposit<T extends Func>(
37
54
  state: Transaction<T>,
38
55
  ): TransactionToken<T>
39
56
  export function deposit<T>(state: ReadableState<T>): ReadableToken<T>
40
57
  export function deposit<T>(
41
58
  state:
59
+ | Molecule<any>
60
+ | MoleculeFamily<any, any, any>
61
+ | ReadableState<T>
42
62
  | ReadonlySelector<T>
43
63
  | RegularAtom<T>
44
64
  | Transaction<T extends Func ? T : never>
45
65
  | WritableSelector<T>
46
66
  | (T extends Transceiver<any> ? MutableAtom<T, any> : never),
47
67
  ):
68
+ | MoleculeFamilyToken<any, any, any>
69
+ | MoleculeToken<any, any, any>
48
70
  | MutableAtomToken<T extends Transceiver<any> ? T : never, any>
49
71
  | RegularAtomToken<T>
50
72
  | SelectorToken<T>
51
73
  | TransactionToken<T extends Func ? T : never> {
52
- const token = {
53
- key: state.key,
54
- type: state.type,
55
- } as any
56
- if (`family` in state) {
57
- token.family = state.family
74
+ const { type } = state
75
+ switch (type) {
76
+ case `atom`:
77
+ case `molecule_family`:
78
+ case `mutable_atom`:
79
+ case `selector`:
80
+ case `readonly_selector`:
81
+ case `transaction`: {
82
+ const token = {
83
+ key: state.key,
84
+ type: state.type,
85
+ } as any
86
+ if (`family` in state) {
87
+ token.family = state.family
88
+ }
89
+ return token
90
+ }
91
+ case `molecule`:
92
+ return state.token
58
93
  }
59
- return token
60
94
  }
@@ -2,6 +2,8 @@ import type {
2
2
  AtomToken,
3
3
  Func,
4
4
  Logger,
5
+ MoleculeCreation,
6
+ MoleculeDisposal,
5
7
  MutableAtomFamily,
6
8
  ReadonlySelectorFamily,
7
9
  ReadonlySelectorToken,
@@ -13,7 +15,12 @@ import type {
13
15
  } from "atom.io"
14
16
  import { AtomIOLogger } from "atom.io"
15
17
  import type { Molecule } from "atom.io/immortal"
18
+ import type { Json } from "atom.io/json"
16
19
 
20
+ import type {
21
+ MoleculeFamily,
22
+ MoleculeToken,
23
+ } from "~/packages/atom.io/immortal/src/make-molecule"
17
24
  import { Junction } from "~/packages/rel8/junction/src"
18
25
 
19
26
  import type {
@@ -82,6 +89,7 @@ export class Store implements Lineage {
82
89
  )
83
90
 
84
91
  public molecules = new Map<string, Molecule<any>>()
92
+ public moleculeFamilies = new Map<string, MoleculeFamily<any, any, any>>()
85
93
  public miscResources = new Map<string, Disposable>()
86
94
 
87
95
  public on = {
@@ -99,6 +107,9 @@ export class Store implements Lineage {
99
107
  null,
100
108
  ),
101
109
  operationClose: new Subject<OperationProgress>(),
110
+ moleculeCreationStart: new Subject<MoleculeToken<any, any, any>>(),
111
+ moleculeCreationDone: new Subject<MoleculeToken<any, any, any>>(),
112
+ moleculeDisposal: new Subject<MoleculeToken<any, any, any>>(),
102
113
  }
103
114
  public operation: OperationProgress = { open: false }
104
115
  public transactionMeta: TransactionEpoch | TransactionProgress<Func> = {
@@ -24,7 +24,13 @@ import type {
24
24
  WritableSelectorToken,
25
25
  WritableToken,
26
26
  } from "atom.io"
27
- import type { Json } from "atom.io/json"
27
+ import type {
28
+ Molecule,
29
+ MoleculeFamily,
30
+ MoleculeFamilyToken,
31
+ MoleculeToken,
32
+ } from "atom.io/immortal"
33
+ import { type Json, stringifyJson } from "atom.io/json"
28
34
 
29
35
  import type {
30
36
  Atom,
@@ -45,6 +51,8 @@ import type { Store } from "./store"
45
51
  export type Withdrawable =
46
52
  | Atom<any>
47
53
  | AtomFamily<any, any>
54
+ | Molecule<any>
55
+ | MoleculeFamily<any, any, any>
48
56
  | MutableAtom<any, any>
49
57
  | MutableAtomFamily<any, any, any>
50
58
  | ReadableState<any>
@@ -116,6 +124,17 @@ export function withdraw<T, K extends Json.Serializable>(
116
124
  store: Store,
117
125
  ): SelectorFamily<T, any>
118
126
 
127
+ export function withdraw<
128
+ K extends Json.Serializable,
129
+ S extends { [key: string]: any },
130
+ P extends any[],
131
+ >(token: MoleculeToken<K, S, P>, store: Store): Molecule<K> & S
132
+ export function withdraw<
133
+ K extends Json.Serializable,
134
+ S extends { [key: string]: any },
135
+ P extends any[],
136
+ >(token: MoleculeFamilyToken<K, S, P>, store: Store): MoleculeFamily<K, S, P>
137
+
119
138
  export function withdraw<T extends Func>(
120
139
  token: TransactionToken<T>,
121
140
  store: Store,
@@ -126,6 +145,8 @@ export function withdraw<T>(
126
145
  ): Timeline<T extends TimelineManageable ? T : never>
127
146
  export function withdraw<T>(
128
147
  token:
148
+ | MoleculeFamilyToken<any, any, any>
149
+ | MoleculeToken<any, any, any>
129
150
  | RegularAtomFamilyToken<T, any>
130
151
  | RegularAtomToken<T>
131
152
  | SelectorFamilyToken<T, any>
@@ -163,6 +184,12 @@ export function withdraw<T>(
163
184
  case `transaction`:
164
185
  withdrawn = target.transactions.get(token.key)
165
186
  break
187
+ case `molecule`:
188
+ withdrawn = target.molecules.get(stringifyJson(token.key))
189
+ break
190
+ case `molecule_family`:
191
+ withdrawn = target.moleculeFamilies.get(token.key)
192
+ break
166
193
  }
167
194
  if (withdrawn) {
168
195
  return withdrawn
@@ -29,213 +29,237 @@ export const addAtomToTimeline = (
29
29
  const atom = maybeAtom
30
30
  store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key })
31
31
 
32
- atom.subject.subscribe(`timeline`, (update) => {
33
- const target = newest(store)
34
- const currentSelectorKey =
35
- store.operation.open && store.operation.token.type === `selector`
36
- ? store.operation.token.key
37
- : null
38
- const currentSelectorTime =
39
- store.operation.open && store.operation.token.type === `selector`
40
- ? store.operation.time
41
- : null
42
- const { transactionApplying } = target.on
43
- const currentTransactionKey = transactionApplying.state?.update.key
44
- const currentTransactionInstanceId = transactionApplying.state?.update.id
32
+ tl.subscriptions.set(
33
+ atom.key,
34
+ atom.subject.subscribe(`timeline`, (update) => {
35
+ const target = newest(store)
36
+ const currentSelectorKey =
37
+ store.operation.open && store.operation.token.type === `selector`
38
+ ? store.operation.token.key
39
+ : null
40
+ const currentSelectorTime =
41
+ store.operation.open && store.operation.token.type === `selector`
42
+ ? store.operation.time
43
+ : null
44
+ const { transactionApplying } = target.on
45
+ const currentTransactionKey = transactionApplying.state?.update.key
46
+ const currentTransactionInstanceId = transactionApplying.state?.update.id
45
47
 
46
- store.logger.info(
47
- `⏳`,
48
- `timeline`,
49
- tl.key,
50
- `atom`,
51
- atomToken.key,
52
- `went`,
53
- update.oldValue,
54
- `->`,
55
- update.newValue,
56
- currentTransactionKey
57
- ? `in transaction "${currentTransactionKey}"`
58
- : currentSelectorKey
59
- ? `in selector "${currentSelectorKey}"`
60
- : ``,
61
- )
62
- if (tl.timeTraveling === null) {
63
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
64
- const mostRecentUpdate: TimelineUpdate<any> | undefined =
65
- tl.history.at(-1)
66
- if (mostRecentUpdate === undefined) {
67
- throw new Error(
68
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`,
69
- )
70
- }
71
- }
72
- if (currentTransactionKey) {
73
- const txToken: TransactionToken<any> = {
74
- key: currentTransactionKey,
75
- type: `transaction`,
76
- }
77
- const currentTransaction = withdraw(txToken, store)
78
- if (tl.transactionKey !== currentTransactionKey) {
79
- if (tl.transactionKey) {
80
- store.logger.error(
81
- `🐞`,
82
- `timeline`,
83
- tl.key,
84
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`,
48
+ store.logger.info(
49
+ `⏳`,
50
+ `timeline`,
51
+ tl.key,
52
+ `atom`,
53
+ atomToken.key,
54
+ `went`,
55
+ update.oldValue,
56
+ `->`,
57
+ update.newValue,
58
+ currentTransactionKey
59
+ ? `in transaction "${currentTransactionKey}"`
60
+ : currentSelectorKey
61
+ ? `in selector "${currentSelectorKey}"`
62
+ : ``,
63
+ )
64
+ if (tl.timeTraveling === null) {
65
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
66
+ const mostRecentUpdate: TimelineUpdate<any> | undefined =
67
+ tl.history.at(-1)
68
+ if (mostRecentUpdate === undefined) {
69
+ throw new Error(
70
+ `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`,
85
71
  )
86
72
  }
87
- tl.transactionKey = currentTransactionKey
88
- const unsubscribe = currentTransaction.subject.subscribe(
89
- `timeline:${tl.key}`,
90
- (transactionUpdate) => {
91
- unsubscribe()
92
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
93
- if (tl.at !== tl.history.length) {
94
- tl.history.splice(tl.at)
95
- }
73
+ }
74
+ if (currentTransactionKey) {
75
+ const txToken: TransactionToken<any> = {
76
+ key: currentTransactionKey,
77
+ type: `transaction`,
78
+ }
79
+ const currentTransaction = withdraw(txToken, store)
80
+ if (tl.transactionKey !== currentTransactionKey) {
81
+ if (tl.transactionKey) {
82
+ store.logger.error(
83
+ `🐞`,
84
+ `timeline`,
85
+ tl.key,
86
+ `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`,
87
+ )
88
+ }
89
+ tl.transactionKey = currentTransactionKey
90
+ const unsubscribe = currentTransaction.subject.subscribe(
91
+ `timeline:${tl.key}`,
92
+ (transactionUpdate) => {
93
+ unsubscribe()
94
+ if (tl.timeTraveling === null && currentTransactionInstanceId) {
95
+ if (tl.at !== tl.history.length) {
96
+ tl.history.splice(tl.at)
97
+ }
96
98
 
97
- const filterUpdates = (
98
- updates: TransactionUpdate<Func>[`updates`],
99
- ) =>
100
- updates
101
- .filter((updateFromTx) => {
102
- const newestStore = newest(store)
103
- if (`updates` in updateFromTx) {
104
- return true
105
- }
106
- const atomOrFamilyKeys =
107
- newestStore.timelineAtoms.getRelatedKeys(tl.key)
99
+ const filterUpdates = (
100
+ updates: TransactionUpdate<Func>[`updates`],
101
+ ) =>
102
+ updates
103
+ .filter((updateFromTx) => {
104
+ const newestStore = newest(store)
105
+ if (`updates` in updateFromTx) {
106
+ return true
107
+ }
108
+ const atomOrFamilyKeys =
109
+ newestStore.timelineAtoms.getRelatedKeys(tl.key)
108
110
 
109
- return atomOrFamilyKeys
110
- ? [...atomOrFamilyKeys].some(
111
- (key) =>
112
- key === updateFromTx.key ||
113
- key === updateFromTx.family?.key,
114
- )
115
- : false
116
- })
117
- .map((updateFromTx) => {
118
- if (`updates` in updateFromTx) {
119
- return {
120
- ...updateFromTx,
121
- updates: filterUpdates(updateFromTx.updates),
111
+ if (!atomOrFamilyKeys) {
112
+ return false
113
+ }
114
+ let key: string | undefined
115
+ let familyKey: string | undefined
116
+ switch (updateFromTx.type) {
117
+ case `state_creation`:
118
+ case `state_disposal`:
119
+ key = updateFromTx.token.key
120
+ familyKey = updateFromTx.token.family?.key
121
+ break
122
+ case `molecule_creation`:
123
+ case `molecule_disposal`:
124
+ break
125
+ default:
126
+ key = updateFromTx.key
127
+ familyKey = updateFromTx.family?.key
128
+ break
129
+ }
130
+ if (key === undefined) {
131
+ return false
132
+ }
133
+ if (atomOrFamilyKeys.has(key)) {
134
+ return true
135
+ }
136
+ if (familyKey !== undefined) {
137
+ return atomOrFamilyKeys.has(familyKey)
138
+ }
139
+ return false
140
+ })
141
+ .map((updateFromTx) => {
142
+ if (`updates` in updateFromTx) {
143
+ return {
144
+ ...updateFromTx,
145
+ updates: filterUpdates(updateFromTx.updates),
146
+ }
122
147
  }
123
- }
124
- return updateFromTx
125
- })
148
+ return updateFromTx
149
+ })
126
150
 
127
- const updates = filterUpdates(transactionUpdate.updates)
151
+ const updates = filterUpdates(transactionUpdate.updates)
128
152
 
129
- const timelineTransactionUpdate: TimelineTransactionUpdate = {
130
- type: `transaction_update`,
131
- timestamp: Date.now(),
132
- ...transactionUpdate,
133
- updates,
153
+ const timelineTransactionUpdate: TimelineTransactionUpdate = {
154
+ timestamp: Date.now(),
155
+ ...transactionUpdate,
156
+ updates,
157
+ }
158
+ const willCapture =
159
+ tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true
160
+ if (willCapture) {
161
+ tl.history.push(timelineTransactionUpdate)
162
+ tl.at = tl.history.length
163
+ tl.subject.next(timelineTransactionUpdate)
164
+ }
134
165
  }
135
- const willCapture =
136
- tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true
137
- if (willCapture) {
138
- tl.history.push(timelineTransactionUpdate)
139
- tl.at = tl.history.length
140
- tl.subject.next(timelineTransactionUpdate)
141
- }
142
- }
143
- tl.transactionKey = null
166
+ tl.transactionKey = null
167
+ store.logger.info(
168
+ `⌛`,
169
+ `timeline`,
170
+ tl.key,
171
+ `got a transaction_update "${transactionUpdate.key}"`,
172
+ )
173
+ },
174
+ )
175
+ }
176
+ } else if (currentSelectorKey && currentSelectorTime) {
177
+ let latestUpdate: TimelineUpdate<any> | undefined = tl.history.at(-1)
178
+
179
+ if (currentSelectorTime !== tl.selectorTime) {
180
+ latestUpdate = {
181
+ type: `selector_update`,
182
+ timestamp: currentSelectorTime,
183
+ key: currentSelectorKey,
184
+ atomUpdates: [],
185
+ }
186
+ latestUpdate.atomUpdates.push({
187
+ key: atom.key,
188
+ type: `atom_update`,
189
+ ...update,
190
+ })
191
+ if (tl.at !== tl.history.length) {
192
+ tl.history.splice(tl.at)
193
+ }
194
+
195
+ tl.history.push(latestUpdate)
196
+
197
+ store.logger.info(
198
+ `⌛`,
199
+ `timeline`,
200
+ tl.key,
201
+ `got a selector_update "${currentSelectorKey}" with`,
202
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key),
203
+ )
204
+
205
+ tl.at = tl.history.length
206
+ tl.selectorTime = currentSelectorTime
207
+ } else {
208
+ if (latestUpdate?.type === `selector_update`) {
209
+ latestUpdate.atomUpdates.push({
210
+ key: atom.key,
211
+ type: `atom_update`,
212
+ ...update,
213
+ })
144
214
  store.logger.info(
145
215
  `⌛`,
146
216
  `timeline`,
147
217
  tl.key,
148
- `got a transaction_update "${transactionUpdate.key}"`,
218
+ `set selector_update "${currentSelectorKey}" to`,
219
+ latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key),
149
220
  )
150
- },
151
- )
152
- }
153
- } else if (currentSelectorKey && currentSelectorTime) {
154
- let latestUpdate: TimelineUpdate<any> | undefined = tl.history.at(-1)
155
-
156
- if (currentSelectorTime !== tl.selectorTime) {
157
- latestUpdate = {
158
- type: `selector_update`,
159
- timestamp: currentSelectorTime,
160
- key: currentSelectorKey,
161
- atomUpdates: [],
221
+ }
162
222
  }
163
- latestUpdate.atomUpdates.push({
164
- key: atom.key,
165
- type: `atom_update`,
166
- ...update,
167
- })
223
+ if (latestUpdate) {
224
+ const willCaptureSelectorUpdate =
225
+ tl.shouldCapture?.(latestUpdate, tl) ?? true
226
+ if (willCaptureSelectorUpdate) {
227
+ tl.subject.next(latestUpdate)
228
+ } else {
229
+ tl.history.pop()
230
+ tl.at = tl.history.length
231
+ }
232
+ }
233
+ } else {
234
+ const timestamp = Date.now()
235
+ tl.selectorTime = null
168
236
  if (tl.at !== tl.history.length) {
169
237
  tl.history.splice(tl.at)
170
238
  }
171
-
172
- tl.history.push(latestUpdate)
173
-
239
+ const atomUpdate: TimelineAtomUpdate<any> = {
240
+ type: `atom_update`,
241
+ timestamp,
242
+ key: atom.key,
243
+ oldValue: update.oldValue,
244
+ newValue: update.newValue,
245
+ }
246
+ if (atom.family) {
247
+ atomUpdate.family = atom.family
248
+ }
249
+ const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true
174
250
  store.logger.info(
175
251
  `⌛`,
176
252
  `timeline`,
177
253
  tl.key,
178
- `got a selector_update "${currentSelectorKey}" with`,
179
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key),
254
+ `got an atom_update to "${atom.key}"`,
180
255
  )
181
-
182
- tl.at = tl.history.length
183
- tl.selectorTime = currentSelectorTime
184
- } else {
185
- if (latestUpdate?.type === `selector_update`) {
186
- latestUpdate.atomUpdates.push({
187
- key: atom.key,
188
- type: `atom_update`,
189
- ...update,
190
- })
191
- store.logger.info(
192
- `⌛`,
193
- `timeline`,
194
- tl.key,
195
- `set selector_update "${currentSelectorKey}" to`,
196
- latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key),
197
- )
198
- }
199
- }
200
- if (latestUpdate) {
201
- const willCaptureSelectorUpdate =
202
- tl.shouldCapture?.(latestUpdate, tl) ?? true
203
- if (willCaptureSelectorUpdate) {
204
- tl.subject.next(latestUpdate)
205
- } else {
206
- tl.history.pop()
256
+ if (willCapture) {
257
+ tl.history.push(atomUpdate)
207
258
  tl.at = tl.history.length
259
+ tl.subject.next(atomUpdate)
208
260
  }
209
261
  }
210
- } else {
211
- const timestamp = Date.now()
212
- tl.selectorTime = null
213
- if (tl.at !== tl.history.length) {
214
- tl.history.splice(tl.at)
215
- }
216
- const atomUpdate: TimelineAtomUpdate<any> = {
217
- type: `atom_update`,
218
- timestamp,
219
- key: atom.key,
220
- oldValue: update.oldValue,
221
- newValue: update.newValue,
222
- }
223
- if (atom.family) {
224
- atomUpdate.family = atom.family
225
- }
226
- const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true
227
- store.logger.info(
228
- `⌛`,
229
- `timeline`,
230
- tl.key,
231
- `got an atom_update to "${atom.key}"`,
232
- )
233
- if (willCapture) {
234
- tl.history.push(atomUpdate)
235
- tl.at = tl.history.length
236
- tl.subject.next(atomUpdate)
237
- }
238
262
  }
239
- }
240
- })
263
+ }),
264
+ )
241
265
  }