atom.io 0.39.1 → 0.40.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 (88) hide show
  1. package/dist/internal/index.d.ts +68 -63
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +171 -161
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/introspection/index.d.ts +2 -2
  6. package/dist/introspection/index.d.ts.map +1 -1
  7. package/dist/introspection/index.js.map +1 -1
  8. package/dist/main/index.d.ts +19 -15
  9. package/dist/main/index.d.ts.map +1 -1
  10. package/dist/main/index.js +16 -13
  11. package/dist/main/index.js.map +1 -1
  12. package/dist/react/index.d.ts +3 -3
  13. package/dist/react/index.d.ts.map +1 -1
  14. package/dist/react/index.js.map +1 -1
  15. package/dist/react-devtools/index.js +9 -6
  16. package/dist/react-devtools/index.js.map +1 -1
  17. package/dist/realtime-client/index.d.ts +3 -3
  18. package/dist/realtime-client/index.d.ts.map +1 -1
  19. package/dist/realtime-client/index.js +3 -4
  20. package/dist/realtime-client/index.js.map +1 -1
  21. package/dist/realtime-server/index.d.ts +2 -2
  22. package/dist/realtime-server/index.d.ts.map +1 -1
  23. package/package.json +2 -2
  24. package/src/internal/atom/create-regular-atom.ts +3 -2
  25. package/src/internal/atom/dispose-atom.ts +6 -6
  26. package/src/internal/events/ingest-selector-update.ts +13 -4
  27. package/src/internal/families/create-readonly-held-selector-family.ts +3 -4
  28. package/src/internal/families/create-readonly-pure-selector-family.ts +4 -9
  29. package/src/internal/families/create-regular-atom-family.ts +3 -4
  30. package/src/internal/families/create-selector-family.ts +6 -6
  31. package/src/internal/families/create-writable-held-selector-family.ts +2 -2
  32. package/src/internal/families/create-writable-pure-selector-family.ts +3 -7
  33. package/src/internal/families/dispose-from-store.ts +9 -2
  34. package/src/internal/get-state/get-from-store.ts +10 -3
  35. package/src/internal/get-state/reduce-reference.ts +15 -2
  36. package/src/internal/index.ts +8 -8
  37. package/src/internal/install-into-store.ts +2 -1
  38. package/src/internal/join/create-join.ts +2 -2
  39. package/src/internal/join/find-relations-in-store.ts +2 -2
  40. package/src/internal/join/get-internal-relations-from-store.ts +2 -2
  41. package/src/internal/join/get-join.ts +5 -2
  42. package/src/internal/join/join-internal.ts +15 -20
  43. package/src/internal/lineage.ts +12 -1
  44. package/src/internal/molecule.ts +64 -36
  45. package/src/internal/mutable/create-mutable-atom-family.ts +4 -4
  46. package/src/internal/mutable/create-mutable-atom.ts +2 -2
  47. package/src/internal/mutable/tracker-family.ts +3 -3
  48. package/src/internal/operation.ts +3 -1
  49. package/src/internal/selector/create-readonly-held-selector.ts +2 -2
  50. package/src/internal/selector/create-readonly-pure-selector.ts +2 -2
  51. package/src/internal/selector/create-writable-held-selector.ts +2 -2
  52. package/src/internal/selector/create-writable-pure-selector.ts +2 -2
  53. package/src/internal/set-state/become.ts +1 -3
  54. package/src/internal/set-state/dispatch-state-update.ts +13 -11
  55. package/src/internal/set-state/reset-in-store.ts +11 -13
  56. package/src/internal/set-state/set-into-store.ts +27 -3
  57. package/src/internal/store/store.ts +14 -12
  58. package/src/internal/timeline/create-timeline.ts +136 -100
  59. package/src/internal/timeline/time-travel.ts +43 -31
  60. package/src/internal/transaction/abort-transaction.ts +3 -15
  61. package/src/internal/transaction/act-upon-store.ts +1 -5
  62. package/src/internal/transaction/apply-transaction.ts +5 -17
  63. package/src/internal/transaction/assign-transaction-to-continuity.ts +2 -7
  64. package/src/internal/transaction/build-transaction.ts +3 -4
  65. package/src/internal/transaction/create-transaction.ts +5 -6
  66. package/src/internal/transaction/get-epoch-number.ts +1 -7
  67. package/src/internal/transaction/set-epoch-number.ts +4 -12
  68. package/src/introspection/attach-introspection-states.ts +4 -2
  69. package/src/introspection/attach-timeline-family.ts +2 -2
  70. package/src/introspection/attach-transaction-logs.ts +2 -2
  71. package/src/introspection/attach-type-selectors.ts +2 -2
  72. package/src/main/dispose-state.ts +1 -5
  73. package/src/main/events.ts +8 -4
  74. package/src/main/get-state.ts +3 -6
  75. package/src/main/logger.ts +1 -1
  76. package/src/main/realm.ts +36 -12
  77. package/src/main/reset-state.ts +1 -5
  78. package/src/main/set-state.ts +4 -11
  79. package/src/main/silo.ts +4 -3
  80. package/src/main/timeline.ts +1 -7
  81. package/src/react/store-context.tsx +3 -3
  82. package/src/react-devtools/Button.tsx +3 -2
  83. package/src/react-devtools/TimelineIndex.tsx +0 -2
  84. package/src/react-devtools/Updates.tsx +14 -9
  85. package/src/react-devtools/store.ts +2 -2
  86. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +4 -8
  87. package/src/realtime-client/sync-continuity.ts +2 -2
  88. package/src/realtime-server/index.ts +2 -2
@@ -23,12 +23,36 @@ export function setIntoStore<
23
23
  value: New | typeof RESET_STATE | ((oldValue: T) => New),
24
24
  ): void
25
25
 
26
- export function setIntoStore<T, New extends T>(
26
+ export function setIntoStore<
27
+ T,
28
+ K extends Canonical,
29
+ New extends T,
30
+ Key extends K,
31
+ >(
32
+ store: Store,
33
+ ...params:
34
+ | [
35
+ token: WritableFamilyToken<T, K>,
36
+ key: Key,
37
+ value: New | typeof RESET_STATE | ((oldValue: T) => New),
38
+ ]
39
+ | [
40
+ token: WritableToken<T>,
41
+ value: New | typeof RESET_STATE | ((oldValue: T) => New),
42
+ ]
43
+ ): void
44
+
45
+ export function setIntoStore<
46
+ T,
47
+ K extends Canonical,
48
+ New extends T,
49
+ Key extends K,
50
+ >(
27
51
  store: Store,
28
52
  ...params:
29
53
  | [
30
- token: WritableFamilyToken<T, Canonical>,
31
- key: Canonical,
54
+ token: WritableFamilyToken<T, K>,
55
+ key: Key,
32
56
  value: New | typeof RESET_STATE | ((oldValue: T) => New),
33
57
  ]
34
58
  | [
@@ -30,6 +30,8 @@ import type { OperationProgress } from "../operation"
30
30
  import { StatefulSubject, Subject } from "../subject"
31
31
  import type { Timeline } from "../timeline"
32
32
  import type {
33
+ ChildStore,
34
+ RootStore,
33
35
  Transaction,
34
36
  TransactionEpoch,
35
37
  TransactionProgress,
@@ -39,8 +41,8 @@ import type { Fn } from "../utility-types"
39
41
  import { CircularBuffer } from "./circular-buffer"
40
42
 
41
43
  export class Store implements Lineage {
42
- public parent: Store | null = null
43
- public child: Store | null = null
44
+ public parent: ChildStore | RootStore | null = null
45
+ public child: ChildStore | null = null
44
46
 
45
47
  public valueMap: Map<string, any> = new Map()
46
48
  public defaults: Map<string, any> = new Map()
@@ -210,14 +212,14 @@ export class Store implements Lineage {
210
212
  ) {
211
213
  continue
212
214
  }
213
- family.install(this)
215
+ family.install(this as RootStore)
214
216
  }
215
217
  const mutableHelpers = new Set<string>()
216
218
  for (const [, atom] of store.atoms) {
217
219
  if (mutableHelpers.has(atom.key)) {
218
220
  continue
219
221
  }
220
- atom.install(this)
222
+ atom.install(this as RootStore)
221
223
  if (atom.type === `mutable_atom`) {
222
224
  const originalJsonToken = getJsonToken(store, atom)
223
225
  const originalUpdateToken = getUpdateToken(atom)
@@ -226,19 +228,19 @@ export class Store implements Lineage {
226
228
  }
227
229
  }
228
230
  for (const [, selector] of store.readonlySelectors) {
229
- selector.install(this)
231
+ selector.install(this as RootStore)
230
232
  }
231
233
  for (const [, selector] of store.writableSelectors) {
232
234
  if (mutableHelpers.has(selector.key)) {
233
235
  continue
234
236
  }
235
- selector.install(this)
237
+ selector.install(this as RootStore)
236
238
  }
237
239
  for (const [, tx] of store.transactions) {
238
- tx.install(this)
240
+ tx.install(this as RootStore)
239
241
  }
240
242
  for (const [, timeline] of store.timelines) {
241
- timeline.install(this)
243
+ timeline.install(this as RootStore)
242
244
  }
243
245
  }
244
246
  }
@@ -258,15 +260,15 @@ export type StoreEventCarrier = {
258
260
  }
259
261
 
260
262
  declare global {
261
- var ATOM_IO_IMPLICIT_STORE: Store | undefined
263
+ var ATOM_IO_IMPLICIT_STORE: RootStore | undefined
262
264
  }
263
265
 
264
- export const IMPLICIT: { readonly STORE: Store } = {
265
- get STORE(): Store {
266
+ export const IMPLICIT: { readonly STORE: RootStore } = {
267
+ get STORE(): RootStore {
266
268
  globalThis.ATOM_IO_IMPLICIT_STORE ??= new Store({
267
269
  name: `IMPLICIT_STORE`,
268
270
  lifespan: `ephemeral`,
269
- })
271
+ }) as RootStore
270
272
  return globalThis.ATOM_IO_IMPLICIT_STORE
271
273
  },
272
274
  }
@@ -4,13 +4,16 @@ import type {
4
4
  AtomUpdateEvent,
5
5
  StateCreationEvent,
6
6
  StateDisposalEvent,
7
+ StateUpdate,
7
8
  TimelineEvent,
8
9
  TimelineManageable,
9
10
  TimelineOptions,
11
+ TimelineSelectorUpdateEvent,
10
12
  TimelineToken,
11
13
  TransactionOutcomeEvent,
12
14
  TransactionSubEvent,
13
15
  TransactionToken,
16
+ WritablePureSelectorToken,
14
17
  } from "atom.io"
15
18
 
16
19
  import { reduceReference } from "../get-state/reduce-reference"
@@ -18,27 +21,24 @@ import { newest } from "../lineage"
18
21
  import { getUpdateToken } from "../mutable"
19
22
  import { deposit, type Store, withdraw } from "../store"
20
23
  import { Subject } from "../subject"
24
+ import type { RootStore } from "../transaction"
21
25
  import { isChildStore } from "../transaction"
22
26
 
23
27
  export type Timeline<ManagedAtom extends TimelineManageable> = {
24
28
  type: `timeline`
25
29
  key: string
26
30
  at: number
27
- shouldCapture?: (
28
- update: TimelineEvent<ManagedAtom>,
29
- timeline: Timeline<ManagedAtom>,
30
- ) => boolean
31
31
  timeTraveling: `into_future` | `into_past` | null
32
32
  history: TimelineEvent<ManagedAtom>[]
33
33
  selectorTime: number | null
34
34
  transactionKey: string | null
35
- install: (store: Store) => void
35
+ install: (store: RootStore) => void
36
36
  subject: Subject<TimelineEvent<ManagedAtom> | `redo` | `undo`>
37
37
  subscriptions: Map<string, () => void>
38
38
  }
39
39
 
40
40
  export function createTimeline<ManagedAtom extends TimelineManageable>(
41
- store: Store,
41
+ store: RootStore,
42
42
  options: TimelineOptions<ManagedAtom>,
43
43
  data?: Timeline<ManagedAtom>,
44
44
  ): TimelineToken<ManagedAtom> {
@@ -46,7 +46,6 @@ export function createTimeline<ManagedAtom extends TimelineManageable>(
46
46
  type: `timeline`,
47
47
  key: options.key,
48
48
  at: 0,
49
-
50
49
  timeTraveling: null,
51
50
  selectorTime: null,
52
51
  transactionKey: null,
@@ -56,9 +55,7 @@ export function createTimeline<ManagedAtom extends TimelineManageable>(
56
55
  subject: new Subject(),
57
56
  subscriptions: new Map(),
58
57
  }
59
- if (options.shouldCapture) {
60
- tl.shouldCapture = options.shouldCapture
61
- }
58
+
62
59
  const timelineKey = options.key
63
60
  const target = newest(store)
64
61
  for (const initialTopic of options.scope) {
@@ -182,93 +179,32 @@ function addAtomToTimeline(
182
179
  if (txUpdateInProgress) {
183
180
  joinTransaction(store, tl, txUpdateInProgress)
184
181
  } else if (currentSelectorToken && currentSelectorTime) {
185
- let latestUpdate: TimelineEvent<any> | undefined = tl.history.at(-1)
186
-
187
- if (currentSelectorTime !== tl.selectorTime) {
188
- latestUpdate = {
189
- type: `selector_update`,
190
- timestamp: currentSelectorTime,
191
- // key: currentSelectorKey,
192
- token: currentSelectorToken,
193
- atomUpdates: [],
194
- }
195
- latestUpdate.atomUpdates.push({
196
- type: `atom_update`,
197
- token: atomToken,
198
- update,
199
- timestamp: Date.now(), // 👺 use store operation
200
- })
201
- if (tl.at !== tl.history.length) {
202
- tl.history.splice(tl.at)
203
- }
204
-
205
- tl.history.push(latestUpdate)
206
-
207
- store.logger.info(
208
- `⌛`,
209
- `timeline`,
210
- tl.key,
211
- `got a selector_update "${currentSelectorToken.key}" with`,
212
- latestUpdate.atomUpdates.map(
213
- (atomUpdate) => atomUpdate.token.key,
214
- ),
215
- )
216
-
217
- tl.at = tl.history.length
218
- tl.selectorTime = currentSelectorTime
219
- } else {
220
- if (latestUpdate?.type === `selector_update`) {
221
- latestUpdate.atomUpdates.push({
222
- type: `atom_update`,
223
- token: atomToken,
224
- update,
225
- timestamp: Date.now(), // 👺 use store operation
226
- })
227
- store.logger.info(
228
- `⌛`,
229
- `timeline`,
230
- tl.key,
231
- `set selector_update "${currentSelectorToken.key}" to`,
232
- latestUpdate?.atomUpdates.map(
233
- (atomUpdate) => atomUpdate.token.key,
234
- ),
235
- )
236
- }
237
- }
238
- if (latestUpdate) {
239
- const willCaptureSelectorUpdate =
240
- tl.shouldCapture?.(latestUpdate, tl) ?? true
241
- if (willCaptureSelectorUpdate) {
242
- tl.subject.next(latestUpdate)
243
- } else {
244
- tl.history.pop()
245
- tl.at = tl.history.length
246
- }
247
- }
182
+ buildSelectorUpdate(
183
+ store,
184
+ tl,
185
+ atomToken,
186
+ update,
187
+ currentSelectorToken,
188
+ currentSelectorTime,
189
+ )
248
190
  } else {
249
191
  const timestamp = Date.now()
250
192
  tl.selectorTime = null
251
- if (tl.at !== tl.history.length) {
252
- tl.history.splice(tl.at)
253
- }
254
- const atomUpdate: AtomUpdateEvent<any> = {
193
+
194
+ const atomUpdate: AtomUpdateEvent<any> & TimelineEvent<any> = {
195
+ checkpoint: true,
255
196
  type: `atom_update`,
256
197
  token: deposit(atom),
257
198
  update,
258
199
  timestamp,
259
200
  }
260
- const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true
261
201
  store.logger.info(
262
202
  `⌛`,
263
203
  `timeline`,
264
204
  tl.key,
265
205
  `got an atom_update to "${atom.key}"`,
266
206
  )
267
- if (willCapture) {
268
- tl.history.push(atomUpdate)
269
- tl.at = tl.history.length
270
- tl.subject.next(atomUpdate)
271
- }
207
+ addToHistory(tl, atomUpdate)
272
208
  }
273
209
  }
274
210
  },
@@ -322,10 +258,6 @@ function joinTransaction(
322
258
  unsubscribe()
323
259
  tl.transactionKey = null
324
260
  if (tl.timeTraveling === null && currentTxInstanceId) {
325
- if (tl.at !== tl.history.length) {
326
- tl.history.splice(tl.at)
327
- }
328
-
329
261
  // biome-ignore lint/style/noNonNullAssertion: we are in the context of this timeline
330
262
  const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key)!
331
263
 
@@ -334,22 +266,96 @@ function joinTransaction(
334
266
  timelineTopics,
335
267
  )
336
268
 
337
- const timelineTransactionUpdate: TransactionOutcomeEvent<
338
- TransactionToken<any>
339
- > = {
269
+ const timelineTransactionUpdate: TimelineEvent<any> &
270
+ TransactionOutcomeEvent<TransactionToken<any>> = {
271
+ checkpoint: true,
340
272
  ...transactionUpdate,
341
273
  subEvents: subEventsFiltered,
342
274
  }
343
- const willCapture =
344
- tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true
345
- if (willCapture) {
346
- tl.history.push(timelineTransactionUpdate)
347
- tl.at = tl.history.length
348
- tl.subject.next(timelineTransactionUpdate)
349
- }
275
+
276
+ addToHistory(tl, timelineTransactionUpdate)
277
+ }
278
+ },
279
+ )
280
+ }
281
+ }
282
+
283
+ function buildSelectorUpdate(
284
+ store: Store,
285
+ tl: Timeline<any>,
286
+ atomToken: AtomToken<any>,
287
+ eventOrUpdate: StateCreationEvent<any> | StateUpdate<any>,
288
+ currentSelectorToken: WritablePureSelectorToken<any>,
289
+ currentSelectorTime: number,
290
+ ) {
291
+ let latestUpdate: TimelineEvent<any> | undefined = tl.history.at(-1)
292
+ if (currentSelectorTime !== tl.selectorTime) {
293
+ const selectorUpdate: TimelineEvent<any> & TimelineSelectorUpdateEvent<any> =
294
+ (latestUpdate = {
295
+ checkpoint: true,
296
+ type: `selector_update`,
297
+ timestamp: currentSelectorTime,
298
+ token: currentSelectorToken,
299
+ subEvents: [],
300
+ })
301
+ if (`type` in eventOrUpdate) {
302
+ latestUpdate.subEvents.push(eventOrUpdate)
303
+ } else {
304
+ latestUpdate.subEvents.push({
305
+ type: `atom_update`,
306
+ token: atomToken,
307
+ update: eventOrUpdate,
308
+ timestamp: Date.now(), // 👺 use store operation
309
+ })
310
+ }
311
+
312
+ addToHistory(tl, latestUpdate)
313
+ tl.selectorTime = currentSelectorTime
314
+
315
+ store.logger.info(
316
+ `⌛`,
317
+ `timeline`,
318
+ tl.key,
319
+ `got a selector_update "${currentSelectorToken.key}" with`,
320
+ latestUpdate.subEvents.map((event) => event.token.key),
321
+ )
322
+
323
+ const operation = store.operation
324
+ const unsub = store.on.operationClose.subscribe(
325
+ `timeline:${tl.key} (needs to gather nested selector creations)`,
326
+ () => {
327
+ unsub()
328
+ if (operation.open) {
329
+ selectorUpdate.subEvents = [
330
+ ...operation.subEvents,
331
+ ...selectorUpdate.subEvents,
332
+ ]
350
333
  }
351
334
  },
352
335
  )
336
+ } else {
337
+ if (latestUpdate?.type === `selector_update`) {
338
+ if (`type` in eventOrUpdate) {
339
+ latestUpdate.subEvents.push(eventOrUpdate)
340
+ } else {
341
+ latestUpdate.subEvents.push({
342
+ type: `atom_update`,
343
+ token: atomToken,
344
+ update: eventOrUpdate,
345
+ timestamp: Date.now(), // 👺 use store operation
346
+ })
347
+ }
348
+ store.logger.info(
349
+ `⌛`,
350
+ `timeline`,
351
+ tl.key,
352
+ `set selector_update "${currentSelectorToken.key}" to`,
353
+ latestUpdate?.subEvents.map((event) => event.token.key),
354
+ )
355
+ }
356
+ }
357
+ if (latestUpdate) {
358
+ tl.subject.next(latestUpdate)
353
359
  }
354
360
  }
355
361
 
@@ -402,6 +408,16 @@ function handleStateLifecycleEvent(
402
408
  event: StateCreationEvent<any> | StateDisposalEvent<any>,
403
409
  tl: Timeline<any>,
404
410
  ): void {
411
+ const currentSelectorToken =
412
+ store.operation.open &&
413
+ store.operation.token.type === `writable_pure_selector`
414
+ ? store.operation.token
415
+ : null
416
+ const currentSelectorTime =
417
+ store.operation.open &&
418
+ store.operation.token.type === `writable_pure_selector`
419
+ ? store.operation.timestamp
420
+ : null
405
421
  if (!tl.timeTraveling) {
406
422
  const target = newest(store)
407
423
  if (isChildStore(target)) {
@@ -410,10 +426,21 @@ function handleStateLifecycleEvent(
410
426
  const txUpdateInProgress = target.on.transactionApplying.state
411
427
  if (txUpdateInProgress) {
412
428
  joinTransaction(store, tl, txUpdateInProgress.update)
429
+ } else if (
430
+ currentSelectorToken &&
431
+ currentSelectorTime &&
432
+ event.type === `state_creation`
433
+ ) {
434
+ buildSelectorUpdate(
435
+ store,
436
+ tl,
437
+ event.token,
438
+ event,
439
+ currentSelectorToken,
440
+ currentSelectorTime,
441
+ )
413
442
  } else {
414
- tl.history.push(event)
415
- tl.at = tl.history.length
416
- tl.subject.next(event)
443
+ addToHistory(tl, event)
417
444
  }
418
445
  }
419
446
  }
@@ -427,3 +454,12 @@ function handleStateLifecycleEvent(
427
454
  break
428
455
  }
429
456
  }
457
+
458
+ function addToHistory(tl: Timeline<any>, event: TimelineEvent<any>): void {
459
+ if (tl.at !== tl.history.length) {
460
+ tl.history.splice(tl.at)
461
+ }
462
+ tl.history.push(event)
463
+ tl.at = tl.history.length
464
+ tl.subject.next(event)
465
+ }
@@ -1,4 +1,4 @@
1
- import type { TimelineToken } from "atom.io"
1
+ import type { TimelineEvent, TimelineToken } from "atom.io"
2
2
 
3
3
  import {
4
4
  ingestAtomUpdateEvent,
@@ -30,6 +30,7 @@ export const timeTravel = (
30
30
  )
31
31
  return
32
32
  }
33
+
33
34
  if (
34
35
  (action === `redo` && timelineData.at === timelineData.history.length) ||
35
36
  (action === `undo` && timelineData.at === 0)
@@ -46,46 +47,57 @@ export const timeTravel = (
46
47
  }
47
48
 
48
49
  timelineData.timeTraveling = action === `redo` ? `into_future` : `into_past`
49
- if (action === `undo`) {
50
- --timelineData.at
50
+ let nextIndex = timelineData.at
51
+ let events: TimelineEvent<any>[]
52
+ switch (action) {
53
+ case `undo`:
54
+ --nextIndex
55
+ while (
56
+ nextIndex !== 0 &&
57
+ timelineData.history[nextIndex].checkpoint !== true
58
+ ) {
59
+ --nextIndex
60
+ }
61
+ events = timelineData.history.slice(nextIndex, timelineData.at).reverse()
62
+
63
+ break
64
+ case `redo`:
65
+ ++nextIndex
66
+ events = timelineData.history.slice(timelineData.at, nextIndex)
51
67
  }
68
+ timelineData.at = nextIndex
52
69
 
53
- const event = timelineData.history[timelineData.at]
54
70
  const applying = action === `redo` ? `newValue` : `oldValue`
55
71
 
56
- switch (event.type) {
57
- case `atom_update`: {
58
- ingestAtomUpdateEvent(store, event, applying)
59
- break
60
- }
61
- case `selector_update`: {
62
- ingestSelectorUpdateEvent(store, event, applying)
63
- break
64
- }
65
- case `transaction_outcome`: {
66
- ingestTransactionOutcomeEvent(store, event, applying)
67
- break
68
- }
69
- case `state_creation`: {
70
- ingestCreationEvent(store, event, applying)
71
- break
72
+ for (const event of events) {
73
+ switch (event.type) {
74
+ case `atom_update`: {
75
+ ingestAtomUpdateEvent(store, event, applying)
76
+ break
77
+ }
78
+ case `selector_update`: {
79
+ ingestSelectorUpdateEvent(store, event, applying)
80
+ break
81
+ }
82
+ case `transaction_outcome`: {
83
+ ingestTransactionOutcomeEvent(store, event, applying)
84
+ break
85
+ }
86
+ case `state_creation`: {
87
+ ingestCreationEvent(store, event, applying)
88
+ break
89
+ }
90
+ case `state_disposal`: {
91
+ ingestDisposalEvent(store, event, applying)
92
+ break
93
+ }
72
94
  }
73
- case `state_disposal`: {
74
- ingestDisposalEvent(store, event, applying)
75
- break
76
- }
77
- case `molecule_creation`:
78
- case `molecule_disposal`:
79
- }
80
-
81
- if (action === `redo`) {
82
- ++timelineData.at
83
95
  }
84
96
 
85
97
  timelineData.subject.next(action)
86
98
  timelineData.timeTraveling = null
87
99
  store.logger.info(
88
- `⏹️`,
100
+ `⏸️`,
89
101
  `timeline`,
90
102
  token.key,
91
103
  `"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
@@ -1,19 +1,7 @@
1
- import { newest } from "../lineage"
2
- import type { Store } from "../store"
3
- import { isChildStore } from "./is-root-store"
1
+ import type { ChildStore } from "./is-root-store"
4
2
 
5
- export const abortTransaction = (store: Store): void => {
6
- const target = newest(store)
7
- if (!isChildStore(target)) {
8
- store.logger.warn(
9
- `🐞`,
10
- `transaction`,
11
- `???`,
12
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`,
13
- )
14
- return
15
- }
16
- store.logger.info(
3
+ export const abortTransaction = (target: ChildStore): void => {
4
+ target.logger.info(
17
5
  `🪂`,
18
6
  `transaction`,
19
7
  target.transactionMeta.update.token.key,
@@ -1,6 +1,5 @@
1
1
  import type { TransactionToken } from "atom.io"
2
2
 
3
- import { NotFoundError } from "../not-found-error"
4
3
  import type { Store } from "../store"
5
4
  import { withdraw } from "../store"
6
5
  import type { Fn } from "../utility-types"
@@ -12,9 +11,6 @@ export function actUponStore<F extends Fn>(
12
11
  ): (...parameters: Parameters<F>) => ReturnType<F> {
13
12
  return (...parameters: Parameters<F>): ReturnType<F> => {
14
13
  const tx = withdraw(store, token)
15
- if (tx) {
16
- return tx.run(parameters, id)
17
- }
18
- throw new NotFoundError(token, store)
14
+ return tx.run(parameters, id)
19
15
  }
20
16
  }
@@ -1,30 +1,18 @@
1
1
  import { ingestTransactionOutcomeEvent } from "../events"
2
2
  import { newest } from "../lineage"
3
- import type { Store } from "../store"
4
3
  import { withdraw } from "../store"
5
4
  import type { Fn } from "../utility-types"
5
+ import type { ChildStore } from "./is-root-store"
6
6
  import { isChildStore, isRootStore } from "./is-root-store"
7
7
  import { setEpochNumberOfAction } from "./set-epoch-number"
8
8
 
9
9
  export function applyTransaction<F extends Fn>(
10
- store: Store,
10
+ store: ChildStore,
11
11
  output: ReturnType<F>,
12
12
  ): void {
13
13
  const child = newest(store)
14
14
  const { parent } = child
15
- if (
16
- parent === null ||
17
- !isChildStore(child) ||
18
- child.transactionMeta?.phase !== `building`
19
- ) {
20
- store.logger.warn(
21
- `🐞`,
22
- `transaction`,
23
- `???`,
24
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`,
25
- )
26
- return
27
- }
15
+
28
16
  child.transactionMeta.phase = `applying`
29
17
  child.transactionMeta.update.output = output
30
18
  parent.child = null
@@ -34,7 +22,7 @@ export function applyTransaction<F extends Fn>(
34
22
  `🛄`,
35
23
  `transaction`,
36
24
  child.transactionMeta.update.token.key,
37
- `Applying transaction with ${updates.length} updates:`,
25
+ `applying ${updates.length} subEvents:`,
38
26
  updates,
39
27
  )
40
28
 
@@ -55,7 +43,7 @@ export function applyTransaction<F extends Fn>(
55
43
  `🛬`,
56
44
  `transaction`,
57
45
  child.transactionMeta.update.token.key,
58
- `Finished applying transaction.`,
46
+ `applied`,
59
47
  )
60
48
  } else if (isChildStore(parent)) {
61
49
  parent.transactionMeta.update.subEvents.push(child.transactionMeta.update)
@@ -1,15 +1,10 @@
1
- import type { Store } from "../store"
2
- import { isRootStore } from "./is-root-store"
1
+ import type { RootStore } from "./is-root-store"
3
2
 
4
3
  export function assignTransactionToContinuity(
5
- store: Store,
4
+ store: RootStore,
6
5
  continuityKey: string,
7
6
  transactionKey: string,
8
7
  ): void {
9
- const isRoot = isRootStore(store)
10
- if (!isRoot) {
11
- return
12
- }
13
8
  const { epoch, actionContinuities } = store.transactionMeta
14
9
  actionContinuities.set(continuityKey, transactionKey)
15
10
  if (!epoch.has(continuityKey)) {