atom.io 0.6.2 → 0.6.3

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 (110) hide show
  1. package/dist/index.d.mts +2 -2
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.js +7 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +7 -2
  6. package/dist/index.mjs.map +1 -1
  7. package/json/dist/index.d.mts +18 -0
  8. package/json/dist/index.d.ts +18 -0
  9. package/json/dist/index.js +51 -0
  10. package/json/dist/index.js.map +1 -0
  11. package/json/dist/index.mjs +15 -0
  12. package/json/dist/index.mjs.map +1 -0
  13. package/package.json +13 -3
  14. package/react/dist/index.d.mts +24 -0
  15. package/react/dist/index.d.ts +24 -0
  16. package/react/dist/index.js +83 -0
  17. package/react/dist/index.js.map +1 -0
  18. package/react/dist/index.mjs +41 -0
  19. package/react/dist/index.mjs.map +1 -0
  20. package/react-devtools/dist/index.css +26 -0
  21. package/react-devtools/dist/index.css.map +1 -0
  22. package/react-devtools/dist/index.d.mts +15 -0
  23. package/react-devtools/dist/index.d.ts +15 -0
  24. package/react-devtools/dist/index.js +1596 -0
  25. package/react-devtools/dist/index.js.map +1 -0
  26. package/react-devtools/dist/index.mjs +1568 -0
  27. package/react-devtools/dist/index.mjs.map +1 -0
  28. package/realtime/dist/index.d.mts +27 -0
  29. package/realtime/dist/index.d.ts +27 -0
  30. package/realtime/dist/index.js +191 -0
  31. package/realtime/dist/index.js.map +1 -0
  32. package/realtime/dist/index.mjs +152 -0
  33. package/realtime/dist/index.mjs.map +1 -0
  34. package/realtime-react/dist/index.d.mts +45 -0
  35. package/realtime-react/dist/index.d.ts +45 -0
  36. package/realtime-react/dist/index.js +213 -0
  37. package/realtime-react/dist/index.js.map +1 -0
  38. package/realtime-react/dist/index.mjs +168 -0
  39. package/realtime-react/dist/index.mjs.map +1 -0
  40. package/realtime-testing/dist/index.d.mts +49 -0
  41. package/realtime-testing/dist/index.d.ts +49 -0
  42. package/realtime-testing/dist/index.js +153 -0
  43. package/realtime-testing/dist/index.js.map +1 -0
  44. package/realtime-testing/dist/index.mjs +117 -0
  45. package/realtime-testing/dist/index.mjs.map +1 -0
  46. package/realtime-testing/package.json +15 -0
  47. package/src/atom.ts +15 -15
  48. package/src/index.ts +59 -59
  49. package/src/internal/atom-internal.ts +36 -36
  50. package/src/internal/families-internal.ts +114 -114
  51. package/src/internal/get.ts +83 -83
  52. package/src/internal/is-default.ts +17 -17
  53. package/src/internal/meta/attach-meta.ts +7 -7
  54. package/src/internal/meta/meta-state.ts +115 -115
  55. package/src/internal/operation.ts +93 -93
  56. package/src/internal/selector/create-read-write-selector.ts +46 -46
  57. package/src/internal/selector/create-readonly-selector.ts +37 -37
  58. package/src/internal/selector/lookup-selector-sources.ts +9 -9
  59. package/src/internal/selector/register-selector.ts +44 -44
  60. package/src/internal/selector/trace-selector-atoms.ts +30 -30
  61. package/src/internal/selector/update-selector-atoms.ts +25 -25
  62. package/src/internal/selector-internal.ts +37 -37
  63. package/src/internal/set.ts +78 -78
  64. package/src/internal/store.ts +118 -118
  65. package/src/internal/subscribe-internal.ts +62 -62
  66. package/src/internal/time-travel-internal.ts +76 -76
  67. package/src/internal/timeline/add-atom-to-timeline.ts +158 -153
  68. package/src/internal/timeline-internal.ts +80 -80
  69. package/src/internal/transaction/abort-transaction.ts +8 -8
  70. package/src/internal/transaction/apply-transaction.ts +41 -41
  71. package/src/internal/transaction/build-transaction.ts +28 -28
  72. package/src/internal/transaction/index.ts +7 -7
  73. package/src/internal/transaction/redo-transaction.ts +13 -13
  74. package/src/internal/transaction/undo-transaction.ts +13 -13
  75. package/src/internal/transaction-internal.ts +48 -48
  76. package/src/json/select-json.ts +12 -12
  77. package/src/logger.ts +30 -30
  78. package/src/react/store-context.tsx +4 -4
  79. package/src/react/store-hooks.ts +18 -18
  80. package/src/react-devtools/AtomIODevtools.tsx +83 -82
  81. package/src/react-devtools/StateEditor.tsx +53 -53
  82. package/src/react-devtools/TokenList.tsx +47 -42
  83. package/src/react-explorer/AtomIOExplorer.tsx +197 -185
  84. package/src/react-explorer/explorer-effects.ts +11 -11
  85. package/src/react-explorer/explorer-states.ts +186 -193
  86. package/src/react-explorer/index.ts +11 -11
  87. package/src/react-explorer/space-states.ts +48 -50
  88. package/src/react-explorer/view-states.ts +25 -25
  89. package/src/realtime/hook-composition/expose-family.ts +81 -81
  90. package/src/realtime/hook-composition/expose-single.ts +26 -26
  91. package/src/realtime/hook-composition/expose-timeline.ts +60 -0
  92. package/src/realtime/hook-composition/index.ts +2 -2
  93. package/src/realtime/hook-composition/receive-state.ts +18 -18
  94. package/src/realtime/hook-composition/receive-transaction.ts +8 -8
  95. package/src/realtime-react/realtime-context.tsx +17 -17
  96. package/src/realtime-react/realtime-hooks.ts +17 -17
  97. package/src/realtime-react/realtime-state.ts +4 -4
  98. package/src/realtime-react/use-pull-family-member.ts +15 -15
  99. package/src/realtime-react/use-pull-family.ts +13 -13
  100. package/src/realtime-react/use-pull.ts +12 -12
  101. package/src/realtime-react/use-push.ts +15 -15
  102. package/src/realtime-react/use-server-action.ts +21 -21
  103. package/src/realtime-testing/index.ts +1 -0
  104. package/src/realtime-testing/setup-realtime-test.tsx +160 -0
  105. package/src/selector.ts +25 -25
  106. package/src/silo.ts +38 -38
  107. package/src/subscribe.ts +68 -68
  108. package/src/timeline.ts +13 -13
  109. package/src/transaction.ts +28 -28
  110. package/src/web-effects/storage.ts +17 -17
@@ -1,164 +1,169 @@
1
1
  import { IMPLICIT, withdraw } from ".."
2
2
  import type {
3
- TimelineSelectorUpdate,
4
- Timeline,
5
- Store,
6
- TimelineTransactionUpdate,
7
- TimelineAtomUpdate,
3
+ TimelineSelectorUpdate,
4
+ Timeline,
5
+ Store,
6
+ TimelineTransactionUpdate,
7
+ TimelineAtomUpdate,
8
8
  } from ".."
9
9
  import type { AtomFamily, AtomToken, TimelineUpdate } from "../.."
10
10
 
11
11
  export const addAtomToTimeline = (
12
- atomToken: AtomToken<any>,
13
- atoms: (AtomFamily<any> | AtomToken<any>)[],
14
- tl: Timeline,
15
- store: Store = IMPLICIT.STORE
12
+ atomToken: AtomToken<any>,
13
+ atoms: (AtomFamily<any> | AtomToken<any>)[],
14
+ tl: Timeline,
15
+ store: Store = IMPLICIT.STORE,
16
16
  ): void => {
17
- const atom = withdraw(atomToken, store)
18
- if (atom === null) {
19
- throw new Error(
20
- `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
21
- )
22
- }
23
- atom.subject.subscribe((update) => {
24
- const currentSelectorKey =
25
- store.operation.open && store.operation.token.type === `selector`
26
- ? store.operation.token.key
27
- : null
28
- const currentSelectorTime =
29
- store.operation.open && store.operation.token.type === `selector`
30
- ? store.operation.time
31
- : null
32
- const currentTransactionKey =
33
- store.transactionStatus.phase === `applying`
34
- ? store.transactionStatus.key
35
- : null
36
- const currentTransactionTime =
37
- store.transactionStatus.phase === `applying`
38
- ? store.transactionStatus.time
39
- : null
17
+ const atom = withdraw(atomToken, store)
18
+ if (atom === null) {
19
+ throw new Error(
20
+ `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`,
21
+ )
22
+ }
23
+ atom.subject.subscribe((update) => {
24
+ const currentSelectorKey =
25
+ store.operation.open && store.operation.token.type === `selector`
26
+ ? store.operation.token.key
27
+ : null
28
+ const currentSelectorTime =
29
+ store.operation.open && store.operation.token.type === `selector`
30
+ ? store.operation.time
31
+ : null
32
+ const currentTransactionKey =
33
+ store.transactionStatus.phase === `applying`
34
+ ? store.transactionStatus.key
35
+ : null
36
+ const currentTransactionTime =
37
+ store.transactionStatus.phase === `applying`
38
+ ? store.transactionStatus.time
39
+ : null
40
40
 
41
- store.config.logger?.info(
42
- `⏳ timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
43
- update.oldValue,
44
- `->`,
45
- update.newValue,
46
- currentTransactionKey
47
- ? `) in transaction "${currentTransactionKey}"`
48
- : currentSelectorKey
49
- ? `) in selector "${currentSelectorKey}"`
50
- : `)`
51
- )
41
+ store.config.logger?.info(
42
+ `⏳ timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
43
+ update.oldValue,
44
+ `->`,
45
+ update.newValue,
46
+ currentTransactionKey
47
+ ? `) in transaction "${currentTransactionKey}"`
48
+ : currentSelectorKey
49
+ ? `) in selector "${currentSelectorKey}"`
50
+ : `)`,
51
+ )
52
52
 
53
- if (tl.timeTraveling === false) {
54
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
55
- const mostRecentUpdate: TimelineUpdate = tl.history.at(-1)!
56
- if (mostRecentUpdate.type === `selector_update`) {
57
- tl.subject.next(mostRecentUpdate)
58
- }
59
- }
60
- if (
61
- currentTransactionKey &&
62
- store.transactionStatus.phase === `applying`
63
- ) {
64
- const currentTransaction = withdraw(
65
- { key: currentTransactionKey, type: `transaction` },
66
- store
67
- )
68
- if (currentTransaction === null) {
69
- throw new Error(
70
- `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
71
- )
72
- }
73
- if (tl.transactionKey !== currentTransactionKey) {
74
- if (tl.transactionKey) {
75
- store.config.logger?.error(
76
- `Timeline "${tl.key}" was unable to resolve transaction "${tl.transactionKey}. This is probably a bug.`
77
- )
78
- }
79
- tl.transactionKey = currentTransactionKey
80
- const subscription = currentTransaction.subject.subscribe((update) => {
81
- if (tl.timeTraveling === false && currentTransactionTime) {
82
- if (tl.at !== tl.history.length) {
83
- tl.history.splice(tl.at)
84
- }
85
- const timelineTransactionUpdate: TimelineTransactionUpdate = {
86
- type: `transaction_update`,
87
- timestamp: currentTransactionTime,
88
- ...update,
89
- atomUpdates: update.atomUpdates.filter((atomUpdate) =>
90
- atoms.some((atom) => atom.key === atomUpdate.key)
91
- ),
92
- }
93
- tl.history.push(timelineTransactionUpdate)
94
- tl.subject.next(timelineTransactionUpdate)
95
- }
96
- tl.at = tl.history.length
97
- subscription.unsubscribe()
98
- tl.transactionKey = null
99
- store.config.logger?.info(
100
- `⌛ timeline "${tl.key}" got a transaction_update "${update.key}"`
101
- )
102
- })
103
- }
104
- } else if (currentSelectorKey && currentSelectorTime) {
105
- if (currentSelectorTime !== tl.selectorTime) {
106
- const newSelectorUpdate: TimelineSelectorUpdate = {
107
- type: `selector_update`,
108
- timestamp: currentSelectorTime,
109
- key: currentSelectorKey,
110
- atomUpdates: [],
111
- }
112
- newSelectorUpdate.atomUpdates.push({
113
- key: atom.key,
114
- type: `atom_update`,
115
- ...update,
116
- })
117
- if (tl.at !== tl.history.length) {
118
- tl.history.splice(tl.at)
119
- }
120
- tl.history.push(newSelectorUpdate)
53
+ if (tl.timeTraveling === false) {
54
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
55
+ const mostRecentUpdate: TimelineUpdate | undefined = tl.history.at(-1)
56
+ if (mostRecentUpdate === undefined) {
57
+ throw new Error(
58
+ `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`,
59
+ )
60
+ }
61
+ if (mostRecentUpdate.type === `selector_update`) {
62
+ tl.subject.next(mostRecentUpdate)
63
+ }
64
+ }
65
+ if (
66
+ currentTransactionKey &&
67
+ store.transactionStatus.phase === `applying`
68
+ ) {
69
+ const currentTransaction = withdraw(
70
+ { key: currentTransactionKey, type: `transaction` },
71
+ store,
72
+ )
73
+ if (currentTransaction === null) {
74
+ throw new Error(
75
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`,
76
+ )
77
+ }
78
+ if (tl.transactionKey !== currentTransactionKey) {
79
+ if (tl.transactionKey) {
80
+ store.config.logger?.error(
81
+ `Timeline "${tl.key}" was unable to resolve transaction "${tl.transactionKey}. This is probably a bug.`,
82
+ )
83
+ }
84
+ tl.transactionKey = currentTransactionKey
85
+ const subscription = currentTransaction.subject.subscribe((update) => {
86
+ if (tl.timeTraveling === false && currentTransactionTime) {
87
+ if (tl.at !== tl.history.length) {
88
+ tl.history.splice(tl.at)
89
+ }
90
+ const timelineTransactionUpdate: TimelineTransactionUpdate = {
91
+ type: `transaction_update`,
92
+ timestamp: currentTransactionTime,
93
+ ...update,
94
+ atomUpdates: update.atomUpdates.filter((atomUpdate) =>
95
+ atoms.some((atom) => atom.key === atomUpdate.key),
96
+ ),
97
+ }
98
+ tl.history.push(timelineTransactionUpdate)
99
+ tl.subject.next(timelineTransactionUpdate)
100
+ }
101
+ tl.at = tl.history.length
102
+ subscription.unsubscribe()
103
+ tl.transactionKey = null
104
+ store.config.logger?.info(
105
+ `⌛ timeline "${tl.key}" got a transaction_update "${update.key}"`,
106
+ )
107
+ })
108
+ }
109
+ } else if (currentSelectorKey && currentSelectorTime) {
110
+ if (currentSelectorTime !== tl.selectorTime) {
111
+ const newSelectorUpdate: TimelineSelectorUpdate = {
112
+ type: `selector_update`,
113
+ timestamp: currentSelectorTime,
114
+ key: currentSelectorKey,
115
+ atomUpdates: [],
116
+ }
117
+ newSelectorUpdate.atomUpdates.push({
118
+ key: atom.key,
119
+ type: `atom_update`,
120
+ ...update,
121
+ })
122
+ if (tl.at !== tl.history.length) {
123
+ tl.history.splice(tl.at)
124
+ }
125
+ tl.history.push(newSelectorUpdate)
121
126
 
122
- store.config.logger?.info(
123
- `⌛ timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
124
- newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
125
- )
126
- tl.at = tl.history.length
127
- tl.selectorTime = currentSelectorTime
128
- } else {
129
- const latestUpdate = tl.history.at(-1)
130
- if (latestUpdate?.type === `selector_update`) {
131
- latestUpdate.atomUpdates.push({
132
- key: atom.key,
133
- type: `atom_update`,
134
- ...update,
135
- })
136
- store.config.logger?.info(
137
- ` ⌛ timeline "${tl.key}" set selector_update "${currentSelectorKey}" to`,
138
- latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
139
- )
140
- }
141
- }
142
- } else {
143
- const timestamp = Date.now()
144
- tl.selectorTime = null
145
- if (tl.at !== tl.history.length) {
146
- tl.history.splice(tl.at)
147
- }
148
- const atomUpdate: TimelineAtomUpdate = {
149
- type: `atom_update`,
150
- timestamp,
151
- key: atom.key,
152
- oldValue: update.oldValue,
153
- newValue: update.newValue,
154
- }
155
- tl.history.push(atomUpdate)
156
- tl.subject.next(atomUpdate)
157
- store.config.logger?.info(
158
- `⌛ timeline "${tl.key}" got a state_update to "${atom.key}"`
159
- )
160
- tl.at = tl.history.length
161
- }
162
- }
163
- })
127
+ store.config.logger?.info(
128
+ `⌛ timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
129
+ newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key),
130
+ )
131
+ tl.at = tl.history.length
132
+ tl.selectorTime = currentSelectorTime
133
+ } else {
134
+ const latestUpdate = tl.history.at(-1)
135
+ if (latestUpdate?.type === `selector_update`) {
136
+ latestUpdate.atomUpdates.push({
137
+ key: atom.key,
138
+ type: `atom_update`,
139
+ ...update,
140
+ })
141
+ store.config.logger?.info(
142
+ ` ⌛ timeline "${tl.key}" set selector_update "${currentSelectorKey}" to`,
143
+ latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key),
144
+ )
145
+ }
146
+ }
147
+ } else {
148
+ const timestamp = Date.now()
149
+ tl.selectorTime = null
150
+ if (tl.at !== tl.history.length) {
151
+ tl.history.splice(tl.at)
152
+ }
153
+ const atomUpdate: TimelineAtomUpdate = {
154
+ type: `atom_update`,
155
+ timestamp,
156
+ key: atom.key,
157
+ oldValue: update.oldValue,
158
+ newValue: update.newValue,
159
+ }
160
+ tl.history.push(atomUpdate)
161
+ tl.subject.next(atomUpdate)
162
+ store.config.logger?.info(
163
+ `⌛ timeline "${tl.key}" got a state_update to "${atom.key}"`,
164
+ )
165
+ tl.at = tl.history.length
166
+ }
167
+ }
168
+ })
164
169
  }
@@ -7,100 +7,100 @@ import type { Store } from "."
7
7
  import { target, IMPLICIT } from "."
8
8
  import { addAtomToTimeline } from "./timeline/add-atom-to-timeline"
9
9
  import type {
10
- StateUpdate,
11
- TimelineOptions,
12
- TimelineToken,
13
- TimelineUpdate,
14
- TransactionUpdate,
10
+ StateUpdate,
11
+ TimelineOptions,
12
+ TimelineToken,
13
+ TimelineUpdate,
14
+ TransactionUpdate,
15
15
  } from ".."
16
16
 
17
17
  export type TimelineAtomUpdate = StateUpdate<unknown> & {
18
- key: string
19
- type: `atom_update`
20
- timestamp: number
18
+ key: string
19
+ type: `atom_update`
20
+ timestamp: number
21
21
  }
22
22
  export type TimelineSelectorUpdate = {
23
- key: string
24
- type: `selector_update`
25
- timestamp: number
26
- atomUpdates: Omit<TimelineAtomUpdate, `timestamp`>[]
23
+ key: string
24
+ type: `selector_update`
25
+ timestamp: number
26
+ atomUpdates: Omit<TimelineAtomUpdate, `timestamp`>[]
27
27
  }
28
28
  export type TimelineTransactionUpdate = TransactionUpdate<ƒn> & {
29
- key: string
30
- type: `transaction_update`
31
- timestamp: number
29
+ key: string
30
+ type: `transaction_update`
31
+ timestamp: number
32
32
  }
33
33
 
34
34
  export type Timeline = {
35
- key: string
36
- at: number
37
- timeTraveling: boolean
38
- history: TimelineUpdate[]
39
- selectorTime: number | null
40
- transactionKey: string | null
41
- install: (store: Store) => void
42
- subject: Rx.Subject<
43
- TimelineAtomUpdate | TimelineSelectorUpdate | TimelineTransactionUpdate
44
- >
35
+ key: string
36
+ at: number
37
+ timeTraveling: boolean
38
+ history: TimelineUpdate[]
39
+ selectorTime: number | null
40
+ transactionKey: string | null
41
+ install: (store: Store) => void
42
+ subject: Rx.Subject<
43
+ TimelineAtomUpdate | TimelineSelectorUpdate | TimelineTransactionUpdate
44
+ >
45
45
  }
46
46
 
47
47
  export function timeline__INTERNAL(
48
- options: TimelineOptions,
49
- store: Store = IMPLICIT.STORE,
50
- data: Timeline | null = null
48
+ options: TimelineOptions,
49
+ store: Store = IMPLICIT.STORE,
50
+ data: Timeline | null = null,
51
51
  ): TimelineToken {
52
- const tl: Timeline = {
53
- key: options.key,
54
- at: 0,
55
- timeTraveling: false,
56
- selectorTime: null,
57
- transactionKey: null,
58
- ...data,
59
- history: data?.history.map((update) => ({ ...update })) ?? [],
60
- install: (store) => timeline__INTERNAL(options, store, tl),
61
- subject: new Rx.Subject(),
62
- }
52
+ const tl: Timeline = {
53
+ key: options.key,
54
+ at: 0,
55
+ timeTraveling: false,
56
+ selectorTime: null,
57
+ transactionKey: null,
58
+ ...data,
59
+ history: data?.history.map((update) => ({ ...update })) ?? [],
60
+ install: (store) => timeline__INTERNAL(options, store, tl),
61
+ subject: new Rx.Subject(),
62
+ }
63
63
 
64
- const core = target(store)
65
- for (const tokenOrFamily of options.atoms) {
66
- const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key)
67
- if (timelineKey) {
68
- store.config.logger?.error(
69
- `❌ Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
70
- )
71
- continue
72
- }
73
- if (tokenOrFamily.type === `atom_family`) {
74
- const family = tokenOrFamily
75
- family.subject.subscribe((token) =>
76
- addAtomToTimeline(token, options.atoms, tl, store)
77
- )
78
- } else {
79
- const token = tokenOrFamily
80
- if (`family` in token && token.family) {
81
- const familyTimelineKey = core.timelineAtoms.getRelatedId(
82
- token.family.key
83
- )
84
- if (familyTimelineKey) {
85
- store.config.logger?.error(
86
- `❌ Failed to add atom "${token.key}" to timeline "${options.key}" because its family "${token.family.key}" belongs to timeline "${familyTimelineKey}"`
87
- )
88
- continue
89
- }
90
- }
91
- addAtomToTimeline(token, options.atoms, tl, store)
92
- }
93
- core.timelineAtoms = core.timelineAtoms.set({
94
- atomKey: tokenOrFamily.key,
95
- timelineKey: options.key,
96
- })
97
- }
64
+ const core = target(store)
65
+ for (const tokenOrFamily of options.atoms) {
66
+ const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key)
67
+ if (timelineKey) {
68
+ store.config.logger?.error(
69
+ `❌ Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`,
70
+ )
71
+ continue
72
+ }
73
+ if (tokenOrFamily.type === `atom_family`) {
74
+ const family = tokenOrFamily
75
+ family.subject.subscribe((token) =>
76
+ addAtomToTimeline(token, options.atoms, tl, store),
77
+ )
78
+ } else {
79
+ const token = tokenOrFamily
80
+ if (`family` in token && token.family) {
81
+ const familyTimelineKey = core.timelineAtoms.getRelatedId(
82
+ token.family.key,
83
+ )
84
+ if (familyTimelineKey) {
85
+ store.config.logger?.error(
86
+ `❌ Failed to add atom "${token.key}" to timeline "${options.key}" because its family "${token.family.key}" belongs to timeline "${familyTimelineKey}"`,
87
+ )
88
+ continue
89
+ }
90
+ }
91
+ addAtomToTimeline(token, options.atoms, tl, store)
92
+ }
93
+ core.timelineAtoms = core.timelineAtoms.set({
94
+ atomKey: tokenOrFamily.key,
95
+ timelineKey: options.key,
96
+ })
97
+ }
98
98
 
99
- store.timelines = HAMT.set(options.key, tl, store.timelines)
100
- const token: TimelineToken = {
101
- key: options.key,
102
- type: `timeline`,
103
- }
104
- store.subject.timelineCreation.next(token)
105
- return token
99
+ store.timelines = HAMT.set(options.key, tl, store.timelines)
100
+ const token: TimelineToken = {
101
+ key: options.key,
102
+ type: `timeline`,
103
+ }
104
+ store.subject.timelineCreation.next(token)
105
+ return token
106
106
  }
@@ -1,12 +1,12 @@
1
1
  import type { Store } from ".."
2
2
 
3
3
  export const abortTransaction = (store: Store): void => {
4
- if (store.transactionStatus.phase === `idle`) {
5
- store.config.logger?.warn(
6
- `abortTransaction called outside of a transaction. This is probably a bug.`
7
- )
8
- return
9
- }
10
- store.transactionStatus = { phase: `idle` }
11
- store.config.logger?.info(`🪂`, `transaction fail`)
4
+ if (store.transactionStatus.phase === `idle`) {
5
+ store.config.logger?.warn(
6
+ `abortTransaction called outside of a transaction. This is probably a bug.`,
7
+ )
8
+ return
9
+ }
10
+ store.transactionStatus = { phase: `idle` }
11
+ store.config.logger?.info(`🪂`, `transaction fail`)
12
12
  }
@@ -8,47 +8,47 @@ import type { AtomToken } from "../.."
8
8
  import { setState } from "../.."
9
9
 
10
10
  export const applyTransaction = <ƒ extends ƒn>(
11
- output: ReturnType<ƒ>,
12
- store: Store
11
+ output: ReturnType<ƒ>,
12
+ store: Store,
13
13
  ): void => {
14
- if (store.transactionStatus.phase !== `building`) {
15
- store.config.logger?.warn(
16
- `abortTransaction called outside of a transaction. This is probably a bug.`
17
- )
18
- return
19
- }
20
- store.config.logger?.info(
21
- `🛃 apply transaction "${store.transactionStatus.key}"`
22
- )
23
- store.transactionStatus.phase = `applying`
24
- store.transactionStatus.output = output
25
- const { atomUpdates } = store.transactionStatus
14
+ if (store.transactionStatus.phase !== `building`) {
15
+ store.config.logger?.warn(
16
+ `abortTransaction called outside of a transaction. This is probably a bug.`,
17
+ )
18
+ return
19
+ }
20
+ store.config.logger?.info(
21
+ `🛃 apply transaction "${store.transactionStatus.key}"`,
22
+ )
23
+ store.transactionStatus.phase = `applying`
24
+ store.transactionStatus.output = output
25
+ const { atomUpdates } = store.transactionStatus
26
26
 
27
- for (const { key, newValue } of atomUpdates) {
28
- const token: AtomToken<unknown> = { key, type: `atom` }
29
- if (!HAMT.has(token.key, store.valueMap)) {
30
- const newAtom = HAMT.get(token.key, store.transactionStatus.core.atoms)
31
- store.atoms = HAMT.set(newAtom.key, newAtom, store.atoms)
32
- store.valueMap = HAMT.set(newAtom.key, newAtom.default, store.valueMap)
33
- store.config.logger?.info(`🔧`, `add atom "${newAtom.key}"`)
34
- }
35
- setState(token, newValue, store)
36
- }
37
- const myTransaction = withdraw<ƒ>(
38
- { key: store.transactionStatus.key, type: `transaction` },
39
- store
40
- )
41
- if (myTransaction === null) {
42
- throw new Error(
43
- `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
44
- )
45
- }
46
- myTransaction.subject.next({
47
- key: store.transactionStatus.key,
48
- atomUpdates,
49
- output,
50
- params: store.transactionStatus.params as Parameters<ƒ>,
51
- })
52
- store.transactionStatus = { phase: `idle` }
53
- store.config.logger?.info(`🛬`, `transaction done`)
27
+ for (const { key, newValue } of atomUpdates) {
28
+ const token: AtomToken<unknown> = { key, type: `atom` }
29
+ if (!HAMT.has(token.key, store.valueMap)) {
30
+ const newAtom = HAMT.get(token.key, store.transactionStatus.core.atoms)
31
+ store.atoms = HAMT.set(newAtom.key, newAtom, store.atoms)
32
+ store.valueMap = HAMT.set(newAtom.key, newAtom.default, store.valueMap)
33
+ store.config.logger?.info(`🔧`, `add atom "${newAtom.key}"`)
34
+ }
35
+ setState(token, newValue, store)
36
+ }
37
+ const myTransaction = withdraw<ƒ>(
38
+ { key: store.transactionStatus.key, type: `transaction` },
39
+ store,
40
+ )
41
+ if (myTransaction === null) {
42
+ throw new Error(
43
+ `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`,
44
+ )
45
+ }
46
+ myTransaction.subject.next({
47
+ key: store.transactionStatus.key,
48
+ atomUpdates,
49
+ output,
50
+ params: store.transactionStatus.params as Parameters<ƒ>,
51
+ })
52
+ store.transactionStatus = { phase: `idle` }
53
+ store.config.logger?.info(`🛬`, `transaction done`)
54
54
  }