atom.io 0.36.2 → 0.37.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 (120) hide show
  1. package/dist/data/index.d.ts.map +1 -1
  2. package/dist/data/index.js.map +1 -1
  3. package/dist/eslint-plugin/index.js +1 -2
  4. package/dist/eslint-plugin/index.js.map +1 -1
  5. package/dist/internal/index.d.ts +66 -98
  6. package/dist/internal/index.d.ts.map +1 -1
  7. package/dist/internal/index.js +544 -507
  8. package/dist/internal/index.js.map +1 -1
  9. package/dist/introspection/index.d.ts +2 -2
  10. package/dist/introspection/index.d.ts.map +1 -1
  11. package/dist/introspection/index.js +1 -1
  12. package/dist/introspection/index.js.map +1 -1
  13. package/dist/json/index.d.ts +2 -1
  14. package/dist/json/index.d.ts.map +1 -1
  15. package/dist/json/index.js.map +1 -1
  16. package/dist/main/index.d.ts +154 -139
  17. package/dist/main/index.d.ts.map +1 -1
  18. package/dist/main/index.js.map +1 -1
  19. package/dist/react/index.d.ts.map +1 -1
  20. package/dist/react/index.js.map +1 -1
  21. package/dist/react-devtools/index.d.ts.map +1 -1
  22. package/dist/react-devtools/index.js +54 -56
  23. package/dist/react-devtools/index.js.map +1 -1
  24. package/dist/realtime/index.d.ts.map +1 -1
  25. package/dist/realtime/index.js.map +1 -1
  26. package/dist/realtime-client/index.d.ts +3 -3
  27. package/dist/realtime-client/index.d.ts.map +1 -1
  28. package/dist/realtime-client/index.js +6 -6
  29. package/dist/realtime-client/index.js.map +1 -1
  30. package/dist/realtime-react/index.d.ts.map +1 -1
  31. package/dist/realtime-react/index.js.map +1 -1
  32. package/dist/realtime-server/index.d.ts +5 -5
  33. package/dist/realtime-server/index.d.ts.map +1 -1
  34. package/dist/realtime-server/index.js +10 -12
  35. package/dist/realtime-server/index.js.map +1 -1
  36. package/dist/realtime-testing/index.d.ts.map +1 -1
  37. package/dist/realtime-testing/index.js.map +1 -1
  38. package/dist/transceivers/set-rtx/index.d.ts +1 -1
  39. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  40. package/dist/transceivers/set-rtx/index.js +1 -3
  41. package/dist/transceivers/set-rtx/index.js.map +1 -1
  42. package/dist/use-o-DXPncKmZ.js.map +1 -1
  43. package/dist/web/index.d.ts +2 -2
  44. package/dist/web/index.d.ts.map +1 -1
  45. package/dist/web/index.js.map +1 -1
  46. package/package.json +14 -14
  47. package/src/internal/atom/dispose-atom.ts +5 -4
  48. package/src/internal/caching.ts +3 -3
  49. package/src/internal/families/create-readonly-held-selector-family.ts +3 -5
  50. package/src/internal/families/create-readonly-pure-selector-family.ts +3 -5
  51. package/src/internal/families/create-regular-atom-family.ts +3 -6
  52. package/src/internal/families/create-writable-held-selector-family.ts +3 -5
  53. package/src/internal/families/create-writable-pure-selector-family.ts +3 -5
  54. package/src/internal/families/find-in-store.ts +17 -34
  55. package/src/internal/families/init-family-member.ts +5 -87
  56. package/src/internal/families/mint-in-store.ts +74 -0
  57. package/src/internal/get-state/read-or-compute-value.ts +4 -2
  58. package/src/internal/index.ts +19 -18
  59. package/src/internal/ingest-updates/ingest-atom-update.ts +7 -7
  60. package/src/internal/ingest-updates/ingest-creation-disposal.ts +11 -11
  61. package/src/internal/ingest-updates/ingest-selector-update.ts +8 -4
  62. package/src/internal/ingest-updates/ingest-transaction-update.ts +5 -6
  63. package/src/internal/install-into-store.ts +2 -2
  64. package/src/internal/join/join-internal.ts +1 -1
  65. package/src/internal/molecule.ts +12 -9
  66. package/src/internal/mutable/create-mutable-atom-family.ts +3 -6
  67. package/src/internal/mutable/tracker.ts +2 -2
  68. package/src/internal/mutable/transceiver.ts +6 -4
  69. package/src/internal/operation.ts +17 -14
  70. package/src/internal/selector/create-readonly-held-selector.ts +9 -7
  71. package/src/internal/selector/create-readonly-pure-selector.ts +8 -5
  72. package/src/internal/selector/create-writable-held-selector.ts +12 -21
  73. package/src/internal/selector/create-writable-pure-selector.ts +16 -29
  74. package/src/internal/selector/dispose-selector.ts +6 -1
  75. package/src/internal/selector/get-selector-dependency-keys.ts +2 -6
  76. package/src/internal/selector/register-selector.ts +64 -74
  77. package/src/internal/selector/trace-selector-atoms.ts +2 -2
  78. package/src/internal/selector/update-selector-atoms.ts +2 -2
  79. package/src/internal/set-state/dispatch-state-update.ts +101 -0
  80. package/src/internal/set-state/operate-on-store.ts +126 -0
  81. package/src/internal/set-state/reset-atom-or-selector.ts +24 -15
  82. package/src/internal/set-state/set-atom-or-selector.ts +9 -4
  83. package/src/internal/set-state/set-atom.ts +4 -49
  84. package/src/internal/set-state/set-into-store.ts +11 -77
  85. package/src/internal/set-state/set-selector.ts +35 -0
  86. package/src/internal/store/store.ts +4 -4
  87. package/src/internal/subscribe/subscribe-in-store.ts +3 -3
  88. package/src/internal/subscribe/subscribe-to-timeline.ts +2 -2
  89. package/src/internal/timeline/create-timeline.ts +57 -101
  90. package/src/internal/timeline/time-travel.ts +1 -1
  91. package/src/internal/transaction/abort-transaction.ts +1 -1
  92. package/src/internal/transaction/apply-transaction.ts +7 -7
  93. package/src/internal/transaction/build-transaction.ts +10 -9
  94. package/src/internal/transaction/create-transaction.ts +4 -3
  95. package/src/internal/transaction/index.ts +6 -2
  96. package/src/introspection/attach-introspection-states.ts +2 -2
  97. package/src/introspection/attach-transaction-logs.ts +13 -6
  98. package/src/json/index.ts +3 -1
  99. package/src/main/atom.ts +2 -1
  100. package/src/main/events.ts +109 -0
  101. package/src/main/get-state.ts +1 -1
  102. package/src/main/index.ts +3 -0
  103. package/src/main/subscribe.ts +9 -19
  104. package/src/main/timeline.ts +3 -21
  105. package/src/main/transaction.ts +0 -65
  106. package/src/main/validators.ts +8 -2
  107. package/src/react-devtools/TimelineIndex.tsx +1 -1
  108. package/src/react-devtools/TransactionIndex.tsx +5 -3
  109. package/src/react-devtools/Updates.tsx +54 -46
  110. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +20 -10
  111. package/src/realtime-client/realtime-client-stores/client-sync-store.ts +4 -4
  112. package/src/realtime-client/sync-continuity.ts +1 -1
  113. package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +14 -8
  114. package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +5 -2
  115. package/src/realtime-server/continuity/subscribe-to-continuity-actions.ts +1 -1
  116. package/src/realtime-server/realtime-action-receiver.ts +6 -3
  117. package/src/realtime-server/realtime-server-stores/server-sync-store.ts +13 -16
  118. package/src/transceivers/set-rtx/set-rtx.ts +1 -3
  119. package/src/web/persist-sync.ts +2 -2
  120. package/src/internal/set-state/emit-update.ts +0 -40
@@ -9,9 +9,10 @@ import type {
9
9
  ReadonlyPureSelectorToken,
10
10
  RegularAtomFamilyToken,
11
11
  RegularAtomToken,
12
- StateCreation,
13
- StateDisposal,
12
+ StateCreationEvent,
13
+ StateDisposalEvent,
14
14
  StateLifecycleEvent,
15
+ StateUpdate,
15
16
  WritableHeldSelectorFamilyToken,
16
17
  WritableHeldSelectorToken,
17
18
  WritablePureSelectorFamilyToken,
@@ -62,7 +63,7 @@ export type AtomIOState = {
62
63
  key: string
63
64
  family?: FamilyMetadata
64
65
  install: (store: Store) => void
65
- subject: Subject<{ newValue: any; oldValue: any }>
66
+ subject: Subject<StateUpdate<any>>
66
67
  }
67
68
  export type RegularAtom<T> = Flat<
68
69
  AtomIOState & {
@@ -87,28 +88,28 @@ export type WritableHeldSelector<T> = Flat<
87
88
  AtomIOState & {
88
89
  type: `writable_held_selector`
89
90
  const: T
90
- get: () => T
91
- set: (newValue: T | ((oldValue: T) => T)) => void
91
+ getFrom: (target: Store) => T
92
+ setSelf: (newValue: T) => void
92
93
  }
93
94
  >
94
95
  export type ReadonlyHeldSelector<T> = Flat<
95
96
  AtomIOState & {
96
97
  type: `readonly_held_selector`
97
98
  const: T
98
- get: () => T
99
+ getFrom: (target: Store) => T
99
100
  }
100
101
  >
101
102
  export type WritablePureSelector<T> = Flat<
102
103
  AtomIOState & {
103
104
  type: `writable_pure_selector`
104
- get: () => T
105
- set: (newValue: T | ((oldValue: T) => T)) => void
105
+ getFrom: (target: Store) => T
106
+ setSelf: (newValue: T) => void
106
107
  }
107
108
  >
108
109
  export type ReadonlyPureSelector<T> = Flat<
109
110
  AtomIOState & {
110
111
  type: `readonly_pure_selector`
111
- get: () => T
112
+ getFrom: (target: Store) => T
112
113
  }
113
114
  >
114
115
  export type ReadonlySelector<T> =
@@ -135,7 +136,7 @@ export type RegularAtomFamily<T, K extends Canonical> =
135
136
  (key: K): RegularAtomToken<T>
136
137
  install: (store: Store) => void
137
138
  internalRoles: string[] | undefined
138
- subject: Subject<StateCreation<AtomToken<T>> | StateDisposal<AtomToken<T>>>
139
+ subject: Subject<StateCreationEvent<AtomToken<T>> | StateDisposalEvent<AtomToken<T>>>
139
140
  }
140
141
 
141
142
  // biome-ignore format: intersection
@@ -167,8 +168,8 @@ export type WritablePureSelectorFamily<T, K extends Canonical> =
167
168
  install: (store: Store) => void
168
169
  internalRoles: string[] | undefined
169
170
  subject: Subject<
170
- | StateCreation<WritablePureSelectorToken<T>>
171
- | StateDisposal<WritablePureSelectorToken<T>>
171
+ | StateCreationEvent<WritablePureSelectorToken<T>>
172
+ | StateDisposalEvent<WritablePureSelectorToken<T>>
172
173
  >
173
174
  }
174
175
  >
@@ -183,8 +184,8 @@ export type WritableHeldSelectorFamily<T , K extends Canonical> =
183
184
  install: (store: Store) => void
184
185
  internalRoles: string[] | undefined
185
186
  subject: Subject<
186
- | StateCreation<WritableHeldSelectorToken<T>>
187
- | StateDisposal<WritableHeldSelectorToken<T>>
187
+ | StateCreationEvent<WritableHeldSelectorToken<T>>
188
+ | StateDisposalEvent<WritableHeldSelectorToken<T>>
188
189
  >
189
190
  }
190
191
  >
@@ -199,8 +200,8 @@ export type ReadonlyPureSelectorFamily<T, K extends Canonical> =
199
200
  install: (store: Store) => void
200
201
  internalRoles: string[] | undefined
201
202
  subject: Subject<
202
- | StateCreation<ReadonlyPureSelectorToken<T>>
203
- | StateDisposal<ReadonlyPureSelectorToken<T>>
203
+ | StateCreationEvent<ReadonlyPureSelectorToken<T>>
204
+ | StateDisposalEvent<ReadonlyPureSelectorToken<T>>
204
205
  >
205
206
  }
206
207
  >
@@ -215,8 +216,8 @@ export type ReadonlyHeldSelectorFamily<T , K extends Canonical> =
215
216
  install: (store: Store) => void
216
217
  internalRoles: string[] | undefined
217
218
  subject: Subject<
218
- | StateCreation<ReadonlyHeldSelectorToken<T>>
219
- | StateDisposal<ReadonlyHeldSelectorToken<T>>
219
+ | StateCreationEvent<ReadonlyHeldSelectorToken<T>>
220
+ | StateDisposalEvent<ReadonlyHeldSelectorToken<T>>
220
221
  >
221
222
  }
222
223
  >
@@ -1,18 +1,18 @@
1
- import type { KeyedStateUpdate, RegularAtomToken } from "atom.io"
1
+ import type { AtomUpdateEvent } from "atom.io"
2
2
 
3
3
  import { setIntoStore } from "../set-state"
4
4
  import type { Store } from "../store"
5
5
 
6
6
  export function ingestAtomUpdate(
7
7
  applying: `newValue` | `oldValue`,
8
- atomUpdate: KeyedStateUpdate<any>,
8
+ atomUpdate: AtomUpdateEvent<any>,
9
9
  store: Store,
10
10
  ): void {
11
- const { key, newValue, oldValue } = atomUpdate
11
+ const {
12
+ token,
13
+ update: { newValue, oldValue },
14
+ } = atomUpdate
12
15
  const value = applying === `newValue` ? newValue : oldValue
13
- const token: RegularAtomToken<unknown> = { key, type: `atom` }
14
- if (atomUpdate.family) {
15
- Object.assign(token, { family: atomUpdate.family })
16
- }
16
+
17
17
  setIntoStore(store, token, value)
18
18
  }
@@ -1,10 +1,10 @@
1
1
  import type {
2
- MoleculeCreation,
3
- MoleculeDisposal,
4
- MoleculeTransfer,
2
+ MoleculeCreationEvent,
3
+ MoleculeDisposalEvent,
4
+ MoleculeTransferEvent,
5
5
  ReadableToken,
6
- StateCreation,
7
- StateDisposal,
6
+ StateCreationEvent,
7
+ StateDisposalEvent,
8
8
  } from "atom.io"
9
9
  import { parseJson, stringifyJson } from "atom.io/json"
10
10
 
@@ -17,7 +17,7 @@ import {
17
17
  import type { Store } from "../store"
18
18
 
19
19
  export function ingestCreationEvent(
20
- update: StateCreation<any>,
20
+ update: StateCreationEvent<any>,
21
21
  applying: `newValue` | `oldValue`,
22
22
  store: Store,
23
23
  ): void {
@@ -34,7 +34,7 @@ export function ingestCreationEvent(
34
34
  }
35
35
 
36
36
  export function ingestDisposalEvent(
37
- update: StateDisposal<ReadableToken<any>>,
37
+ update: StateDisposalEvent<ReadableToken<any>>,
38
38
  applying: `newValue` | `oldValue`,
39
39
  store: Store,
40
40
  ): void {
@@ -54,7 +54,7 @@ export function ingestDisposalEvent(
54
54
  }
55
55
 
56
56
  function createInStore(
57
- update: StateCreation<any> | StateDisposal<any>,
57
+ update: StateCreationEvent<any> | StateDisposalEvent<any>,
58
58
  store: Store,
59
59
  ): void {
60
60
  const { family: familyMeta } = update.token
@@ -67,7 +67,7 @@ function createInStore(
67
67
  }
68
68
 
69
69
  export function ingestMoleculeCreationEvent(
70
- update: MoleculeCreation,
70
+ update: MoleculeCreationEvent,
71
71
  applying: `newValue` | `oldValue`,
72
72
  store: Store,
73
73
  ): void {
@@ -82,7 +82,7 @@ export function ingestMoleculeCreationEvent(
82
82
  }
83
83
  }
84
84
  export function ingestMoleculeDisposalEvent(
85
- update: MoleculeDisposal,
85
+ update: MoleculeDisposalEvent,
86
86
  applying: `newValue` | `oldValue`,
87
87
  store: Store,
88
88
  ): void {
@@ -108,7 +108,7 @@ export function ingestMoleculeDisposalEvent(
108
108
  }
109
109
  }
110
110
  export function ingestMoleculeTransferEvent(
111
- update: MoleculeTransfer,
111
+ update: MoleculeTransferEvent,
112
112
  applying: `newValue` | `oldValue`,
113
113
  store: Store,
114
114
  ): void {
@@ -1,15 +1,19 @@
1
- import type { TimelineManageable } from "atom.io"
1
+ import type {
2
+ AtomOnly,
3
+ AtomUpdateEvent,
4
+ TimelineManageable,
5
+ TimelineSelectorUpdateEvent,
6
+ } from "atom.io"
2
7
 
3
8
  import type { Store } from "../store"
4
- import type { TimelineAtomUpdate, TimelineSelectorUpdate } from "../timeline"
5
9
  import { ingestAtomUpdate } from "./ingest-atom-update"
6
10
 
7
11
  export function ingestSelectorUpdate(
8
12
  applying: `newValue` | `oldValue`,
9
- selectorUpdate: TimelineSelectorUpdate<any>,
13
+ selectorUpdate: TimelineSelectorUpdateEvent<any>,
10
14
  store: Store,
11
15
  ): void {
12
- let updates: Omit<TimelineAtomUpdate<TimelineManageable>, `timestamp`>[]
16
+ let updates: AtomUpdateEvent<AtomOnly<TimelineManageable>>[]
13
17
  if (applying === `newValue`) {
14
18
  updates = selectorUpdate.atomUpdates
15
19
  } else {
@@ -1,4 +1,4 @@
1
- import type { TransactionUpdate } from "atom.io"
1
+ import type { TransactionOutcomeEvent } from "atom.io"
2
2
 
3
3
  import type { Store } from "../store"
4
4
  import { ingestAtomUpdate } from "./ingest-atom-update"
@@ -12,17 +12,16 @@ import {
12
12
 
13
13
  export function ingestTransactionUpdate(
14
14
  applying: `newValue` | `oldValue`,
15
- transactionUpdate: TransactionUpdate<any>,
15
+ transactionUpdate: TransactionOutcomeEvent<any>,
16
16
  store: Store,
17
17
  ): void {
18
18
  const updates =
19
19
  applying === `newValue`
20
- ? transactionUpdate.updates
21
- : [...transactionUpdate.updates].reverse()
20
+ ? transactionUpdate.subEvents
21
+ : [...transactionUpdate.subEvents].reverse()
22
22
  for (const updateFromTransaction of updates) {
23
23
  switch (updateFromTransaction.type) {
24
24
  case `atom_update`:
25
- case `selector_update`:
26
25
  ingestAtomUpdate(applying, updateFromTransaction, store)
27
26
  break
28
27
  case `state_creation`:
@@ -40,7 +39,7 @@ export function ingestTransactionUpdate(
40
39
  case `molecule_transfer`:
41
40
  ingestMoleculeTransferEvent(updateFromTransaction, applying, store)
42
41
  break
43
- case `transaction_update`:
42
+ case `transaction_outcome`:
44
43
  ingestTransactionUpdate(applying, updateFromTransaction, store)
45
44
  break
46
45
  }
@@ -22,7 +22,7 @@ export function installIntoStore(
22
22
  source.logger.error(
23
23
  `❌`,
24
24
  `transaction`,
25
- sourceNewest.transactionMeta.update.key,
25
+ sourceNewest.transactionMeta.update.token.key,
26
26
  `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`,
27
27
  tokens,
28
28
  `${sourceNewest.config.name} is undergoing a transaction.`,
@@ -34,7 +34,7 @@ export function installIntoStore(
34
34
  target.logger.error(
35
35
  `❌`,
36
36
  `transaction`,
37
- targetNewest.transactionMeta.update.key,
37
+ targetNewest.transactionMeta.update.token.key,
38
38
  `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`,
39
39
  tokens,
40
40
  `${targetNewest.config.name} is undergoing a transaction.`,
@@ -8,6 +8,7 @@ import type {
8
8
  ReadonlyPureSelectorFamilyToken,
9
9
  RegularAtomFamilyToken,
10
10
  setState,
11
+ ViewOf,
11
12
  Write,
12
13
  WriterToolkit,
13
14
  } from "atom.io"
@@ -29,7 +30,6 @@ import type {
29
30
  } from "../junction"
30
31
  import { Junction } from "../junction"
31
32
  import type { Molecule } from "../molecule"
32
- import type { ViewOf } from "../mutable"
33
33
  import { createMutableAtomFamily, getJsonFamily, getJsonToken } from "../mutable"
34
34
  import { setIntoStore } from "../set-state"
35
35
  import type { Store } from "../store"
@@ -4,9 +4,9 @@ import type {
4
4
  CompoundFrom,
5
5
  CompoundTypedKey,
6
6
  Hierarchy,
7
- MoleculeCreation,
8
- MoleculeDisposal,
9
- MoleculeTransfer,
7
+ MoleculeCreationEvent,
8
+ MoleculeDisposalEvent,
9
+ MoleculeTransferEvent,
10
10
  SingularTypedKey,
11
11
  Vassal,
12
12
  } from "atom.io"
@@ -77,15 +77,16 @@ export function allocateIntoStore<
77
77
  target.molecules.set(stringKey, { key, stringKey, dependsOn })
78
78
  }
79
79
 
80
- const creationEvent: MoleculeCreation = {
80
+ const creationEvent: MoleculeCreationEvent = {
81
81
  type: `molecule_creation`,
82
82
  key,
83
83
  provenance: origin,
84
+ timestamp: Date.now(),
84
85
  }
85
86
  const isTransaction =
86
87
  isChildStore(target) && target.transactionMeta.phase === `building`
87
88
  if (isTransaction) {
88
- target.transactionMeta.update.updates.push(creationEvent)
89
+ target.transactionMeta.update.subEvents.push(creationEvent)
89
90
  } else {
90
91
  target.on.moleculeCreation.next(creationEvent)
91
92
  }
@@ -174,18 +175,19 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
174
175
  const provenance: stringified<Canonical>[] = []
175
176
 
176
177
  const values: [string, any][] = []
177
- const disposalEvent: MoleculeDisposal = {
178
+ const disposalEvent: MoleculeDisposalEvent = {
178
179
  type: `molecule_disposal`,
179
180
  key: molecule.key,
180
181
  values,
181
182
  provenance,
183
+ timestamp: Date.now(),
182
184
  }
183
185
  const target = newest(store)
184
186
  target.molecules.delete(stringKey)
185
187
  const isTransaction =
186
188
  isChildStore(target) && target.transactionMeta.phase === `building`
187
189
  if (isTransaction) {
188
- target.transactionMeta.update.updates.push(disposalEvent)
190
+ target.transactionMeta.update.subEvents.push(disposalEvent)
189
191
  }
190
192
  const relatedMolecules = store.moleculeGraph.getRelationEntries({
191
193
  downstreamMoleculeKey: molecule.stringKey,
@@ -290,17 +292,18 @@ export function claimWithinStore<
290
292
  source: newProvenanceMolecule.stringKey,
291
293
  },
292
294
  )
293
- const transferEvent: MoleculeTransfer = {
295
+ const transferEvent: MoleculeTransferEvent = {
294
296
  type: `molecule_transfer`,
295
297
  key: molecule.key,
296
298
  exclusive: Boolean(exclusive),
297
299
  from: priorProvenance,
298
300
  to: [newProvenanceMolecule.key],
301
+ timestamp: Date.now(),
299
302
  }
300
303
  const isTransaction =
301
304
  isChildStore(target) && target.transactionMeta.phase === `building`
302
305
  if (isTransaction) {
303
- target.transactionMeta.update.updates.push(transferEvent)
306
+ target.transactionMeta.update.subEvents.push(transferEvent)
304
307
  }
305
308
 
306
309
  return claim
@@ -4,8 +4,7 @@ import type {
4
4
  MutableAtomFamilyToken,
5
5
  MutableAtomOptions,
6
6
  MutableAtomToken,
7
- StateCreation,
8
- StateDisposal,
7
+ StateLifecycleEvent,
9
8
  } from "atom.io"
10
9
  import type { Canonical } from "atom.io/json"
11
10
  import { stringifyJson } from "atom.io/json"
@@ -48,9 +47,7 @@ export function createMutableAtomFamily<
48
47
  )
49
48
  }
50
49
 
51
- const subject = new Subject<
52
- StateCreation<MutableAtomToken<T>> | StateDisposal<MutableAtomToken<T>>
53
- >()
50
+ const subject = new Subject<StateLifecycleEvent<MutableAtomToken<T>>>()
54
51
 
55
52
  const familyFunction = (key: K): MutableAtomToken<T> => {
56
53
  const subKey = stringifyJson(key)
@@ -68,7 +65,7 @@ export function createMutableAtomFamily<
68
65
 
69
66
  const token = createMutableAtom(target, individualOptions, family)
70
67
 
71
- subject.next({ type: `state_creation`, token })
68
+ subject.next({ type: `state_creation`, token, timestamp: Date.now() })
72
69
  return token
73
70
  }
74
71
 
@@ -58,7 +58,7 @@ export class Tracker<T extends Transceiver<any, any, any>> {
58
58
  const stateKey = mutableState.key
59
59
  const storeName = target.config.name
60
60
  const storeStatus = isChildStore(target)
61
- ? target.transactionMeta.update.key
61
+ ? target.transactionMeta.update.token.key
62
62
  : `main`
63
63
  const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`
64
64
  const trackerCapturesOutboundSignal = (update: SignalFrom<T>) => {
@@ -91,7 +91,7 @@ export class Tracker<T extends Transceiver<any, any, any>> {
91
91
  target: Store,
92
92
  ): void {
93
93
  const subscriptionKey = `tracker:${target.config.name}:${
94
- isChildStore(target) ? target.transactionMeta.update.key : `main`
94
+ isChildStore(target) ? target.transactionMeta.update.token.key : `main`
95
95
  }:${mutableState.key}`
96
96
  subscribeToState(
97
97
  target,
@@ -5,12 +5,12 @@ export interface Transceiver<
5
5
  S extends Json.Serializable,
6
6
  J extends Json.Serializable,
7
7
  > {
8
+ READONLY_VIEW: V
8
9
  do: (update: S) => number | `OUT_OF_RANGE` | null
9
10
  undo: (update: S) => void
10
11
  subscribe: (key: string, fn: (update: S) => void) => () => void
11
12
  cacheUpdateNumber: number
12
13
  getUpdateNumber: (update: S) => number
13
- view: () => V
14
14
  toJSON: () => J
15
15
  }
16
16
 
@@ -30,14 +30,16 @@ export function isTransceiver(
30
30
  value !== null &&
31
31
  `do` in value &&
32
32
  `undo` in value &&
33
- `subscribe` in value
33
+ `subscribe` in value &&
34
+ `cacheUpdateNumber` in value &&
35
+ `getUpdateNumber` in value &&
36
+ `READONLY_VIEW` in value &&
37
+ `toJSON` in value
34
38
  )
35
39
  }
36
40
 
37
41
  export type TransceiverMode = `playback` | `record` | `transaction`
38
42
 
39
- export type ViewOf<T> = T extends Transceiver<infer V, any, any> ? V : T
40
-
41
43
  export type SignalFrom<T extends Transceiver<any, any, any>> =
42
44
  T extends Transceiver<any, infer S, any> ? S : never
43
45
 
@@ -4,21 +4,22 @@ import type { Store } from "./store"
4
4
  import { isChildStore } from "./transaction/is-root-store"
5
5
 
6
6
  export type OperationProgress =
7
+ | OpenOperation<any>
7
8
  | {
8
9
  open: false
9
10
  }
10
- | {
11
- open: true
12
- done: Set<string>
13
- prev: Map<string, any>
14
- time: number
15
- token: ReadableToken<any>
16
- }
11
+ export type OpenOperation<R extends ReadableToken<any> = ReadableToken<any>> = {
12
+ open: true
13
+ token: R
14
+ done: Set<string>
15
+ prev: Map<string, any>
16
+ timestamp: number
17
+ }
17
18
 
18
- export const openOperation = (
19
+ export function openOperation(
19
20
  store: Store,
20
21
  token: ReadableToken<any>,
21
- ): number | undefined => {
22
+ ): number | (Store & { operation: OpenOperation }) {
22
23
  if (store.operation.open) {
23
24
  const rejectionTime = performance.now()
24
25
  store.logger.info(
@@ -33,7 +34,7 @@ export const openOperation = (
33
34
  open: true,
34
35
  done: new Set(),
35
36
  prev: new Map(),
36
- time: Date.now(),
37
+ timestamp: Date.now(),
37
38
  token,
38
39
  }
39
40
  store.logger.info(
@@ -41,13 +42,15 @@ export const openOperation = (
41
42
  token.type,
42
43
  token.key,
43
44
  `operation start in store "${store.config.name}"${
44
- !isChildStore(store)
45
- ? ``
46
- : ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`
45
+ isChildStore(store)
46
+ ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"`
47
+ : ``
47
48
  }`,
48
49
  )
50
+ return store as Store & { operation: OpenOperation }
49
51
  }
50
- export const closeOperation = (store: Store): void => {
52
+
53
+ export function closeOperation(store: Store): void {
51
54
  if (store.operation.open) {
52
55
  store.logger.info(
53
56
  `🔴`,
@@ -11,19 +11,19 @@ import type { Store } from "../store"
11
11
  import { Subject } from "../subject"
12
12
  import { registerSelector } from "./register-selector"
13
13
 
14
- export const createReadonlyHeldSelector = <T extends object>(
14
+ export function createReadonlyHeldSelector<T extends object>(
15
15
  store: Store,
16
16
  options: ReadonlyHeldSelectorOptions<T>,
17
17
  family: FamilyMetadata | undefined,
18
- ): ReadonlyHeldSelectorToken<T> => {
18
+ ): ReadonlyHeldSelectorToken<T> {
19
19
  const target = newest(store)
20
20
  const subject = new Subject<{ newValue: T; oldValue: T }>()
21
21
  const covered = new Set<string>()
22
22
  const { key, const: constant } = options
23
23
  const type = `readonly_held_selector` as const
24
24
  const { get, find, json } = registerSelector(target, type, key, covered)
25
- const getSelf = () => {
26
- const innerTarget = newest(store)
25
+
26
+ const getFrom = (innerTarget: Store) => {
27
27
  const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
28
28
  downstreamSelectorKey: key,
29
29
  })
@@ -34,7 +34,7 @@ export const createReadonlyHeldSelector = <T extends object>(
34
34
  }
35
35
  innerTarget.selectorAtoms.delete(key)
36
36
  options.get({ get, find, json }, constant)
37
- writeToCache(newest(store), readonlySelector, constant)
37
+ writeToCache(innerTarget, readonlySelector, constant)
38
38
  covered.clear()
39
39
  return constant
40
40
  }
@@ -43,9 +43,11 @@ export const createReadonlyHeldSelector = <T extends object>(
43
43
  ...options,
44
44
  type,
45
45
  subject,
46
+ getFrom,
46
47
  install: (s: Store) => createReadonlyHeldSelector(s, options, family),
47
- get: getSelf,
48
- ...(family && { family }),
48
+ }
49
+ if (family) {
50
+ readonlySelector.family = family
49
51
  }
50
52
  target.readonlySelectors.set(key, readonlySelector)
51
53
  store.logger.info(`✨`, type, key, `=`, constant)
@@ -11,18 +11,19 @@ import type { Store } from "../store"
11
11
  import { Subject } from "../subject"
12
12
  import { registerSelector } from "./register-selector"
13
13
 
14
- export const createReadonlyPureSelector = <T>(
14
+ export function createReadonlyPureSelector<T>(
15
15
  store: Store,
16
16
  options: ReadonlyPureSelectorOptions<T>,
17
17
  family: FamilyMetadata | undefined,
18
- ): ReadonlyPureSelectorToken<T> => {
18
+ ): ReadonlyPureSelectorToken<T> {
19
19
  const target = newest(store)
20
20
  const subject = new Subject<{ newValue: T; oldValue: T }>()
21
21
  const covered = new Set<string>()
22
22
  const key = options.key
23
23
  const type = `readonly_pure_selector` as const
24
24
  const { get, find, json } = registerSelector(target, type, key, covered)
25
- const getSelf = () => {
25
+
26
+ const getFrom = () => {
26
27
  const innerTarget = newest(store)
27
28
  const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
28
29
  downstreamSelectorKey: key,
@@ -44,9 +45,11 @@ export const createReadonlyPureSelector = <T>(
44
45
  ...options,
45
46
  type,
46
47
  subject,
48
+ getFrom,
47
49
  install: (s: Store) => createReadonlyPureSelector(s, options, family),
48
- get: getSelf,
49
- ...(family && { family }),
50
+ }
51
+ if (family) {
52
+ readonlySelector.family = family
50
53
  }
51
54
  target.readonlySelectors.set(key, readonlySelector)
52
55
  const token: ReadonlyPureSelectorToken<T> = {
@@ -7,18 +7,15 @@ import type {
7
7
  import type { WritableHeldSelector } from ".."
8
8
  import { writeToCache } from "../caching"
9
9
  import { newest } from "../lineage"
10
- import { markDone } from "../operation"
11
- import { become } from "../set-state"
12
10
  import type { Store } from "../store"
13
11
  import { Subject } from "../subject"
14
- import { isRootStore } from "../transaction"
15
12
  import { registerSelector } from "./register-selector"
16
13
 
17
- export const createWritableHeldSelector = <T extends object>(
14
+ export function createWritableHeldSelector<T extends object>(
18
15
  store: Store,
19
16
  options: WritableHeldSelectorOptions<T>,
20
17
  family: FamilyMetadata | undefined,
21
- ): WritableHeldSelectorToken<T> => {
18
+ ): WritableHeldSelectorToken<T> {
22
19
  const target = newest(store)
23
20
  const subject = new Subject<{ newValue: T; oldValue: T }>()
24
21
  const covered = new Set<string>()
@@ -28,7 +25,7 @@ export const createWritableHeldSelector = <T extends object>(
28
25
  const { find, get, json } = setterToolkit
29
26
  const getterToolkit = { find, get, json }
30
27
 
31
- const getSelf = (getFn = options.get, innerTarget = newest(store)): T => {
28
+ const getFrom = (innerTarget: Store): T => {
32
29
  const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
33
30
  downstreamSelectorKey: key,
34
31
  })
@@ -38,33 +35,27 @@ export const createWritableHeldSelector = <T extends object>(
38
35
  }
39
36
  }
40
37
  innerTarget.selectorAtoms.delete(key)
41
- getFn(getterToolkit, constant)
38
+ options.get(getterToolkit, constant)
42
39
  writeToCache(innerTarget, mySelector, constant)
43
40
  store.logger.info(`✨`, type, key, `=`, constant)
44
41
  covered.clear()
45
42
  return constant
46
43
  }
47
44
 
48
- const setSelf = (next: T | ((oldValue: T) => T)): void => {
49
- const innerTarget = newest(store)
50
- const oldValue = getSelf(options.get, innerTarget)
51
- const newValue = become(next)(oldValue)
52
- store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`)
53
- writeToCache(innerTarget, mySelector, newValue)
54
- markDone(innerTarget, key)
55
- if (isRootStore(innerTarget)) {
56
- subject.next({ newValue, oldValue })
57
- }
58
- options.set(setterToolkit, newValue)
45
+ const setSelf = (): void => {
46
+ options.set(setterToolkit, constant)
59
47
  }
48
+
60
49
  const mySelector: WritableHeldSelector<T> = {
61
50
  ...options,
62
51
  type,
63
52
  subject,
53
+ getFrom,
54
+ setSelf,
64
55
  install: (s: Store) => createWritableHeldSelector(s, options, family),
65
- get: getSelf,
66
- set: setSelf,
67
- ...(family && { family }),
56
+ }
57
+ if (family) {
58
+ mySelector.family = family
68
59
  }
69
60
  target.writableSelectors.set(key, mySelector)
70
61