atom.io 0.36.3 → 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 +543 -504
  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 +5 -5
  47. package/src/internal/atom/dispose-atom.ts +5 -4
  48. package/src/internal/caching.ts +1 -1
  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 +15 -28
  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
@@ -3,14 +3,10 @@ import { isStateKey } from "../keys"
3
3
  import { newest } from "../lineage"
4
4
  import type { Store } from "../store"
5
5
 
6
- export const getSelectorDependencyKeys = (
6
+ export function getSelectorDependencyKeys(
7
7
  store: Store,
8
8
  key: string,
9
- ): (
10
- | AtomKey<unknown>
11
- | ReadonlySelectorKey<unknown>
12
- | SelectorKey<unknown>
13
- )[] => {
9
+ ): (AtomKey<unknown> | ReadonlySelectorKey<unknown> | SelectorKey<unknown>)[] {
14
10
  const sources = newest(store)
15
11
  .selectorGraph.getRelationEntries({ downstreamSelectorKey: key })
16
12
  .filter(([_, { source }]) => source !== key)
@@ -7,18 +7,18 @@ import type {
7
7
  WritableToken,
8
8
  WriterToolkit,
9
9
  } from "atom.io"
10
- import type { Json } from "atom.io/json"
10
+ import type { Canonical, Json } from "atom.io/json"
11
11
 
12
12
  import { findInStore } from "../families"
13
13
  import { readOrComputeValue } from "../get-state/read-or-compute-value"
14
14
  import { newest } from "../lineage"
15
15
  import { getJsonToken } from "../mutable"
16
- import { setAtomOrSelector } from "../set-state"
16
+ import { operateOnStore } from "../set-state/operate-on-store"
17
17
  import type { Store } from "../store"
18
18
  import { withdraw } from "../store"
19
19
  import { updateSelectorAtoms } from "./update-selector-atoms"
20
20
 
21
- export const registerSelector = (
21
+ export function registerSelector(
22
22
  store: Store,
23
23
  selectorType:
24
24
  | `readonly_held_selector`
@@ -27,78 +27,68 @@ export const registerSelector = (
27
27
  | `writable_pure_selector`,
28
28
  selectorKey: string,
29
29
  covered: Set<string>,
30
- ): WriterToolkit => ({
31
- get: (
32
- ...params:
33
- | [ReadableFamilyToken<any, any>, Json.Serializable]
34
- | [ReadableToken<any>]
35
- ) => {
36
- const target = newest(store)
37
- let dependency: ReadableToken<any>
30
+ ): WriterToolkit {
31
+ return {
32
+ get: (
33
+ ...params:
34
+ | [ReadableFamilyToken<any, any>, Json.Serializable]
35
+ | [ReadableToken<any>]
36
+ ) => {
37
+ const target = newest(store)
38
+ let dependency: ReadableToken<any>
38
39
 
39
- if (params.length === 2) {
40
- const [family, key] = params
41
- dependency = findInStore(store, family, key)
42
- } else {
43
- ;[dependency] = params
44
- }
40
+ if (params.length === 2) {
41
+ const [family, key] = params
42
+ dependency = findInStore(store, family, key)
43
+ } else {
44
+ ;[dependency] = params
45
+ }
45
46
 
46
- const dependencyState = withdraw(store, dependency)
47
- const dependencyValue = readOrComputeValue(store, dependencyState)
48
- const dependencyKey = dependency.key
47
+ const dependencyState = withdraw(store, dependency)
48
+ const dependencyValue = readOrComputeValue(store, dependencyState)
49
+ const dependencyKey = dependency.key
49
50
 
50
- store.logger.info(
51
- `🔌`,
52
- selectorType,
53
- selectorKey,
54
- `registers dependency ( "${dependencyKey}" =`,
55
- dependencyValue,
56
- `)`,
57
- )
51
+ store.logger.info(
52
+ `🔌`,
53
+ selectorType,
54
+ selectorKey,
55
+ `registers dependency ( "${dependencyKey}" =`,
56
+ dependencyValue,
57
+ `)`,
58
+ )
58
59
 
59
- target.selectorGraph.set(
60
- {
61
- upstreamSelectorKey: dependencyKey,
62
- downstreamSelectorKey: selectorKey,
63
- },
64
- {
65
- source: dependency.key,
66
- },
67
- )
68
- updateSelectorAtoms(
69
- store,
70
- selectorType,
71
- selectorKey,
72
- dependency as any,
73
- covered,
74
- )
75
- return dependencyValue
76
- },
77
- set: (<T, New extends T>(
78
- ...params:
79
- | [
80
- token: WritableFamilyToken<T, any>,
81
- key: Json.Serializable,
82
- value: New | ((oldValue: any) => New),
83
- ]
84
- | [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
85
- ) => {
86
- let token: WritableToken<T>
87
- let value: New | ((oldValue: T) => New)
88
- if (params.length === 2) {
89
- token = params[0]
90
- value = params[1]
91
- } else {
92
- const family = params[0]
93
- const key = params[1]
94
- value = params[2]
95
- token = findInStore(store, family, key)
96
- }
97
- const target = newest(store)
98
- const state = withdraw(target, token)
99
- setAtomOrSelector(target, state, value)
100
- }) as typeof setState,
101
- find: ((...args: Parameters<typeof findState>) =>
102
- findInStore(store, ...args)) as typeof findState,
103
- json: (token) => getJsonToken(store, token),
104
- })
60
+ target.selectorGraph.set(
61
+ {
62
+ upstreamSelectorKey: dependencyKey,
63
+ downstreamSelectorKey: selectorKey,
64
+ },
65
+ {
66
+ source: dependency.key,
67
+ },
68
+ )
69
+ updateSelectorAtoms(
70
+ store,
71
+ selectorType,
72
+ selectorKey,
73
+ dependency as any,
74
+ covered,
75
+ )
76
+ return dependencyValue
77
+ },
78
+ set: (<T, K extends Canonical, New extends T, Key extends K>(
79
+ ...params:
80
+ | [
81
+ token: WritableFamilyToken<T, K>,
82
+ key: Key,
83
+ value: New | ((oldValue: any) => New),
84
+ ]
85
+ | [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
86
+ ) => {
87
+ const target = newest(store)
88
+ operateOnStore(target, false, ...params)
89
+ }) as typeof setState,
90
+ find: ((...args: Parameters<typeof findState>) =>
91
+ findInStore(store, ...args)) as typeof findState,
92
+ json: (token) => getJsonToken(store, token),
93
+ }
94
+ }
@@ -2,11 +2,11 @@ import type { Atom, Store } from ".."
2
2
  import { isAtomKey } from "../keys"
3
3
  import { getSelectorDependencyKeys } from "./get-selector-dependency-keys"
4
4
 
5
- export const traceRootSelectorAtoms = (
5
+ export function traceRootSelectorAtoms(
6
6
  store: Store,
7
7
  selectorKey: string,
8
8
  covered: Set<string> = new Set<string>(),
9
- ): Map<string, Atom<unknown>> => {
9
+ ): Map<string, Atom<unknown>> {
10
10
  const dependencies = getSelectorDependencyKeys(store, selectorKey)
11
11
 
12
12
  const roots = new Map<string, Atom<unknown>>()
@@ -4,7 +4,7 @@ import { newest } from "../lineage"
4
4
  import type { Store } from "../store"
5
5
  import { traceRootSelectorAtoms } from "./trace-selector-atoms"
6
6
 
7
- export const updateSelectorAtoms = (
7
+ export function updateSelectorAtoms(
8
8
  store: Store,
9
9
  selectorType:
10
10
  | `readonly_held_selector`
@@ -14,7 +14,7 @@ export const updateSelectorAtoms = (
14
14
  selectorKey: string,
15
15
  dependency: ReadonlyPureSelectorToken<unknown> | WritableToken<unknown>,
16
16
  covered: Set<string>,
17
- ): void => {
17
+ ): void {
18
18
  const target = newest(store)
19
19
  const { type: dependencyType, key: dependencyKey } = dependency
20
20
  if (dependencyType === `atom` || dependencyType === `mutable_atom`) {
@@ -0,0 +1,101 @@
1
+ import type {
2
+ AtomToken,
3
+ AtomUpdateEvent,
4
+ StateUpdate,
5
+ WritableToken,
6
+ } from "atom.io"
7
+
8
+ import type { MutableAtom, WritableState } from ".."
9
+ import { hasRole } from "../atom"
10
+ import { readOrComputeValue } from "../get-state"
11
+ import type { Transceiver } from "../mutable"
12
+ import { isTransceiver } from "../mutable"
13
+ import type { OpenOperation } from "../operation"
14
+ import { deposit, type Store } from "../store"
15
+ import { isChildStore, isRootStore } from "../transaction"
16
+ import { evictDownstreamFromAtom } from "./evict-downstream"
17
+
18
+ export function dispatchOrDeferStateUpdate<T>(
19
+ target: Store & { operation: OpenOperation<any> },
20
+ state: WritableState<T>,
21
+ [oldValue, newValue]: [T, T],
22
+ _stateIsNewlyCreated: boolean,
23
+ ): void {
24
+ const { key, subject, type } = state
25
+
26
+ const update: StateUpdate<T> = {
27
+ oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
28
+ newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue,
29
+ }
30
+
31
+ if (isRootStore(target)) {
32
+ switch (type) {
33
+ case `mutable_atom`:
34
+ target.logger.info(
35
+ `📢`,
36
+ type,
37
+ key,
38
+ `is now (`,
39
+ newValue,
40
+ `) subscribers:`,
41
+ subject.subscribers,
42
+ )
43
+ break
44
+ case `atom`:
45
+ case `writable_pure_selector`:
46
+ case `writable_held_selector`:
47
+ target.logger.info(
48
+ `📢`,
49
+ type,
50
+ key,
51
+ `went (`,
52
+ oldValue,
53
+ `->`,
54
+ newValue,
55
+ `) subscribers:`,
56
+ subject.subscribers,
57
+ )
58
+ }
59
+ subject.next(update)
60
+ }
61
+
62
+ if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
63
+ if (target.on.transactionApplying.state === null) {
64
+ const token: WritableToken<T> = deposit(state)
65
+
66
+ if (isTransceiver(newValue)) {
67
+ return
68
+ }
69
+ const { timestamp } = target.operation
70
+ const atomUpdate: AtomUpdateEvent<AtomToken<T>> = {
71
+ type: `atom_update`,
72
+ token,
73
+ timestamp,
74
+ update,
75
+ }
76
+ target.transactionMeta.update.subEvents.push(atomUpdate)
77
+ target.logger.info(
78
+ `📁`,
79
+ `atom`,
80
+ key,
81
+ `stowed (`,
82
+ oldValue,
83
+ `->`,
84
+ newValue,
85
+ `)`,
86
+ )
87
+ return
88
+ }
89
+ if (hasRole(state, `tracker:signal`)) {
90
+ const keyOfMutable = key.slice(1)
91
+ const mutable = target.atoms.get(keyOfMutable) as MutableAtom<
92
+ Transceiver<unknown, any, any>
93
+ >
94
+ const transceiver = readOrComputeValue(target, mutable, `mut`)
95
+ const accepted = transceiver.do(update.newValue) === null
96
+ if (accepted === true) {
97
+ evictDownstreamFromAtom(target, mutable)
98
+ }
99
+ }
100
+ }
101
+ }
@@ -0,0 +1,126 @@
1
+ import type { WritableFamilyToken, WritableToken } from "atom.io"
2
+ import { type Canonical, parseJson } from "atom.io/json"
3
+
4
+ import { seekInStore } from "../families"
5
+ import { getFamilyOfToken } from "../families/get-family-of-token"
6
+ import { mintInStore } from "../families/mint-in-store"
7
+ import type { OpenOperation } from "../operation"
8
+ import { closeOperation, openOperation } from "../operation"
9
+ import { type Store, withdraw } from "../store"
10
+ import { dispatchOrDeferStateUpdate } from "./dispatch-state-update"
11
+ import { resetAtomOrSelector } from "./reset-atom-or-selector"
12
+ import { RESET_STATE } from "./reset-in-store"
13
+ import { setAtomOrSelector } from "./set-atom-or-selector"
14
+
15
+ export function operateOnStore<T, New extends T>(
16
+ store: Store,
17
+ ownOp: boolean,
18
+ ...params:
19
+ | [
20
+ token: WritableFamilyToken<T, Canonical>,
21
+ key: Canonical,
22
+ value: New | typeof RESET_STATE | ((oldValue: T) => New),
23
+ ]
24
+ | [
25
+ token: WritableToken<T>,
26
+ value: New | typeof RESET_STATE | ((oldValue: T) => New),
27
+ ]
28
+ ): void {
29
+ let existingToken: WritableToken<T> | undefined
30
+ let brandNewToken: WritableToken<T> | undefined
31
+ let token: WritableToken<T>
32
+ let family: WritableFamilyToken<T, Canonical> | null
33
+ let key: Canonical | null
34
+ let value: New | typeof RESET_STATE | ((oldValue: T) => New)
35
+ if (params.length === 2) {
36
+ token = params[0]
37
+ value = params[1]
38
+ if (token.family) {
39
+ // biome-ignore lint/style/noNonNullAssertion: this token belongs to a family
40
+ family = getFamilyOfToken(store, token)!
41
+ key = parseJson(token.family.subKey)
42
+ existingToken = seekInStore(store, family, key)
43
+ if (!existingToken) {
44
+ brandNewToken = mintInStore(store, family, key)
45
+ token = brandNewToken
46
+ } else {
47
+ token = existingToken
48
+ }
49
+ }
50
+ } else {
51
+ family = params[0]
52
+ key = params[1]
53
+ value = params[2]
54
+ existingToken = seekInStore(store, family, key)
55
+ if (!existingToken) {
56
+ brandNewToken = mintInStore(store, family, key)
57
+ token = brandNewToken
58
+ } else {
59
+ token = existingToken
60
+ }
61
+ }
62
+
63
+ const action = value === RESET_STATE ? `reset` : `set`
64
+
65
+ let target: Store & { operation: OpenOperation }
66
+
67
+ if (ownOp) {
68
+ const result = openOperation(store, token)
69
+ const rejected = typeof result === `number`
70
+ if (rejected) {
71
+ const rejectionTime = result
72
+ const unsubscribe = store.on.operationClose.subscribe(
73
+ `waiting to ${action} "${token.key}" at T-${rejectionTime}`,
74
+ function waitUntilOperationCloseToSetState() {
75
+ unsubscribe()
76
+ store.logger.info(
77
+ `🟢`,
78
+ token.type,
79
+ token.key,
80
+ `resuming deferred`,
81
+ action,
82
+ `from T-${rejectionTime}`,
83
+ )
84
+ operateOnStore(store, ownOp, token, value)
85
+ },
86
+ )
87
+ return
88
+ }
89
+ target = result
90
+ } else {
91
+ target = store as Store & { operation: OpenOperation }
92
+ }
93
+
94
+ if (`counterfeit` in token && `family` in token) {
95
+ const subKey = token.family.subKey
96
+ const disposal = store.disposalTraces.buffer.find(
97
+ (item) => item?.key === subKey,
98
+ )
99
+ store.logger.error(
100
+ `❌`,
101
+ token.type,
102
+ token.key,
103
+ `could not be`,
104
+ action,
105
+ `because it was not found in the store "${store.config.name}".`,
106
+ disposal
107
+ ? `This state was previously disposed:\n${disposal.trace}`
108
+ : `No previous disposal trace was found.`,
109
+ )
110
+ return
111
+ }
112
+
113
+ const state = withdraw(target, token)
114
+ let protoUpdate: [T, T]
115
+ if (value === RESET_STATE) {
116
+ protoUpdate = resetAtomOrSelector(target, state)
117
+ } else {
118
+ protoUpdate = setAtomOrSelector(target, state, value)
119
+ }
120
+ const isNewlyCreated = Boolean(brandNewToken)
121
+ dispatchOrDeferStateUpdate(target, state, protoUpdate, isNewlyCreated)
122
+
123
+ if (ownOp) {
124
+ closeOperation(target)
125
+ }
126
+ }
@@ -1,40 +1,49 @@
1
- import type { Atom, WritableState } from ".."
1
+ import type { Atom, OpenOperation, Store, WritableState } from ".."
2
2
  import { traceRootSelectorAtoms } from ".."
3
- import type { Store } from "../store"
3
+ import { dispatchOrDeferStateUpdate } from "./dispatch-state-update"
4
4
  import { setAtom } from "./set-atom"
5
5
 
6
- function resetAtom(store: Store, state: Atom<any>) {
7
- switch (state.type) {
6
+ function resetAtom<T>(
7
+ target: Store & { operation: OpenOperation },
8
+ atom: Atom<T>,
9
+ ): [oldValue: T, newValue: T] {
10
+ switch (atom.type) {
8
11
  case `mutable_atom`:
9
- setAtom(store, state, new state.class())
10
- return
12
+ return setAtom(target, atom, new atom.class())
11
13
  case `atom`: {
12
- let def = state.default
14
+ let def = atom.default
13
15
  if (def instanceof Function) {
14
16
  def = def()
15
17
  }
16
- setAtom(store, state, def)
18
+ return setAtom(target, atom, def)
17
19
  }
18
20
  }
19
21
  }
20
22
 
21
- export function resetAtomOrSelector(
22
- store: Store,
23
- state: WritableState<any>,
24
- ): void {
23
+ export function resetAtomOrSelector<T>(
24
+ target: Store & { operation: OpenOperation },
25
+ state: WritableState<T>,
26
+ ): [oldValue: T, newValue: T] {
27
+ let protoUpdate: [T, T]
25
28
  switch (state.type) {
26
29
  case `atom`:
27
30
  case `mutable_atom`:
28
- resetAtom(store, state)
31
+ protoUpdate = resetAtom(target, state)
29
32
  break
30
33
  case `writable_pure_selector`:
31
34
  case `writable_held_selector`:
32
35
  {
33
- const atoms = traceRootSelectorAtoms(store, state.key)
36
+ const oldValue = state.getFrom(target)
37
+ const atoms = traceRootSelectorAtoms(target, state.key)
34
38
  for (const atom of atoms.values()) {
35
- resetAtom(store, atom)
39
+ const rootProtoUpdate = resetAtom(target, atom)
40
+ dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false)
36
41
  }
42
+ const newValue = state.getFrom(target)
43
+ protoUpdate = [oldValue, newValue]
37
44
  }
38
45
  break
39
46
  }
47
+
48
+ return protoUpdate
40
49
  }
@@ -1,20 +1,25 @@
1
1
  import type { WritableState } from ".."
2
+ import type { OpenOperation } from "../operation"
2
3
  import type { Store } from "../store"
3
4
  import { setAtom } from "./set-atom"
5
+ import { setSelector } from "./set-selector"
4
6
 
5
7
  export const setAtomOrSelector = <T>(
6
- store: Store,
8
+ target: Store & { operation: OpenOperation },
7
9
  state: WritableState<T>,
8
10
  value: T | ((oldValue: T) => T),
9
- ): void => {
11
+ ): [oldValue: T, newValue: T] => {
12
+ let protoUpdate: [T, T]
10
13
  switch (state.type) {
11
14
  case `atom`:
12
15
  case `mutable_atom`:
13
- setAtom(store, state, value)
16
+ protoUpdate = setAtom(target, state, value)
14
17
  break
15
18
  case `writable_pure_selector`:
16
19
  case `writable_held_selector`:
17
- state.set(value)
20
+ protoUpdate = setSelector(target, state, value)
18
21
  break
19
22
  }
23
+
24
+ return protoUpdate
20
25
  }
@@ -1,65 +1,20 @@
1
- import type { KeyedStateUpdate } from "atom.io"
2
-
3
- import type { Atom, MutableAtom, Store } from ".."
4
- import { hasRole } from "../atom/has-role"
1
+ import type { Atom, OpenOperation, Store } from ".."
5
2
  import { writeToCache } from "../caching"
6
3
  import { readOrComputeValue } from "../get-state/read-or-compute-value"
7
- import { isTransceiver, type Transceiver } from "../mutable"
8
4
  import { markDone } from "../operation"
9
- import { isChildStore } from "../transaction/is-root-store"
10
5
  import { become } from "./become"
11
- import { emitUpdate } from "./emit-update"
12
6
  import { evictDownstreamFromAtom } from "./evict-downstream"
13
7
 
14
8
  export const setAtom = <T>(
15
- target: Store,
9
+ target: Store & { operation: OpenOperation<any> },
16
10
  atom: Atom<T>,
17
11
  next: T | ((oldValue: T) => T),
18
- ): void => {
12
+ ): [oldValue: T, newValue: T] => {
19
13
  const oldValue = readOrComputeValue(target, atom, `mut`)
20
14
  let newValue = become(next)(oldValue)
21
15
  target.logger.info(`📝`, `atom`, atom.key, `set to`, newValue)
22
16
  newValue = writeToCache(target, atom, newValue)
23
17
  markDone(target, atom.key)
24
18
  evictDownstreamFromAtom(target, atom)
25
- const update = { oldValue, newValue }
26
- if (!isChildStore(target)) {
27
- emitUpdate(target, atom, update)
28
- return
29
- }
30
- if (target.on.transactionApplying.state === null) {
31
- const { key } = atom
32
- if (isTransceiver(update.newValue)) {
33
- return
34
- }
35
- const atomUpdate: KeyedStateUpdate<T> = {
36
- type: `atom_update`,
37
- key,
38
- ...update,
39
- }
40
- if (atom.family) {
41
- atomUpdate.family = atom.family
42
- }
43
- target.transactionMeta.update.updates.push(atomUpdate)
44
- target.logger.info(
45
- `📁`,
46
- `atom`,
47
- key,
48
- `stowed (`,
49
- update.oldValue,
50
- `->`,
51
- update.newValue,
52
- `)`,
53
- )
54
- } else if (hasRole(atom, `tracker:signal`)) {
55
- const key = atom.key.slice(1)
56
- const mutable = target.atoms.get(key) as MutableAtom<
57
- Transceiver<unknown, any, any>
58
- >
59
- const transceiver = readOrComputeValue(target, mutable, `mut`)
60
- const accepted = transceiver.do(update.newValue) === null
61
- if (accepted === true) {
62
- evictDownstreamFromAtom(target, mutable)
63
- }
64
- }
19
+ return [oldValue, newValue]
65
20
  }