atom.io 0.6.8 → 0.7.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 (214) hide show
  1. package/README.md +21 -2
  2. package/dist/index.d.mts +42 -461
  3. package/dist/index.d.ts +42 -461
  4. package/dist/index.js +128 -1792
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +75 -1742
  7. package/dist/index.mjs.map +1 -1
  8. package/internal/dist/index.d.mts +342 -0
  9. package/internal/dist/index.d.ts +342 -0
  10. package/internal/dist/index.js +1873 -0
  11. package/internal/dist/index.js.map +1 -0
  12. package/internal/dist/index.mjs +1798 -0
  13. package/internal/dist/index.mjs.map +1 -0
  14. package/internal/package.json +15 -0
  15. package/internal/src/atom/create-atom.ts +75 -0
  16. package/internal/src/atom/delete-atom.ts +10 -0
  17. package/internal/src/atom/index.ts +3 -0
  18. package/{src/internal → internal/src/atom}/is-default.ts +4 -2
  19. package/internal/src/caching.ts +21 -0
  20. package/internal/src/families/create-atom-family.ts +59 -0
  21. package/internal/src/families/create-readonly-selector-family.ts +45 -0
  22. package/internal/src/families/create-selector-family.ts +67 -0
  23. package/internal/src/families/index.ts +3 -0
  24. package/internal/src/get-state-internal.ts +23 -0
  25. package/internal/src/index.ts +13 -0
  26. package/internal/src/mutable/create-mutable-atom-family.ts +25 -0
  27. package/internal/src/mutable/create-mutable-atom.ts +49 -0
  28. package/internal/src/mutable/get-json-token.ts +22 -0
  29. package/internal/src/mutable/get-update-token.ts +20 -0
  30. package/internal/src/mutable/index.ts +17 -0
  31. package/internal/src/mutable/is-atom-token-mutable.ts +7 -0
  32. package/internal/src/mutable/tracker-family.ts +61 -0
  33. package/internal/src/mutable/tracker.ts +164 -0
  34. package/internal/src/mutable/transceiver.ts +110 -0
  35. package/internal/src/operation.ts +68 -0
  36. package/{src/internal → internal/src}/selector/create-read-write-selector.ts +10 -13
  37. package/{src/internal → internal/src}/selector/create-readonly-selector.ts +9 -8
  38. package/internal/src/selector/create-selector.ts +65 -0
  39. package/{src/internal → internal/src}/selector/index.ts +1 -0
  40. package/internal/src/selector/lookup-selector-sources.ts +20 -0
  41. package/{src/internal → internal/src}/selector/register-selector.ts +13 -9
  42. package/{src/internal → internal/src}/selector/trace-selector-atoms.ts +4 -2
  43. package/{src/internal → internal/src}/selector/update-selector-atoms.ts +4 -3
  44. package/internal/src/set-state/become.ts +10 -0
  45. package/internal/src/set-state/copy-mutable-if-needed.ts +23 -0
  46. package/internal/src/set-state/copy-mutable-in-transaction.ts +59 -0
  47. package/internal/src/set-state/copy-mutable-into-new-store.ts +34 -0
  48. package/internal/src/set-state/emit-update.ts +23 -0
  49. package/internal/src/set-state/evict-downstream.ts +39 -0
  50. package/internal/src/set-state/index.ts +2 -0
  51. package/internal/src/set-state/set-atom-state.ts +38 -0
  52. package/internal/src/set-state/set-selector-state.ts +19 -0
  53. package/internal/src/set-state/set-state-internal.ts +18 -0
  54. package/internal/src/set-state/stow-update.ts +42 -0
  55. package/internal/src/store/deposit.ts +43 -0
  56. package/internal/src/store/index.ts +5 -0
  57. package/internal/src/store/lookup.ts +26 -0
  58. package/internal/src/store/store.ts +154 -0
  59. package/internal/src/store/withdraw-new-family-member.ts +53 -0
  60. package/internal/src/store/withdraw.ts +113 -0
  61. package/internal/src/subject.ts +21 -0
  62. package/internal/src/subscribe/index.ts +1 -0
  63. package/internal/src/subscribe/recall-state.ts +19 -0
  64. package/internal/src/subscribe/subscribe-to-root-atoms.ts +47 -0
  65. package/{src/internal → internal/src}/timeline/add-atom-to-timeline.ts +50 -29
  66. package/internal/src/timeline/index.ts +3 -0
  67. package/{src/internal → internal/src/timeline}/time-travel-internal.ts +6 -6
  68. package/{src/internal → internal/src/timeline}/timeline-internal.ts +20 -12
  69. package/{src/internal → internal/src}/transaction/abort-transaction.ts +1 -1
  70. package/{src/internal → internal/src}/transaction/apply-transaction.ts +25 -18
  71. package/{src/internal → internal/src}/transaction/build-transaction.ts +12 -6
  72. package/{src/internal → internal/src}/transaction/index.ts +3 -2
  73. package/{src/internal → internal/src}/transaction/redo-transaction.ts +4 -5
  74. package/{src/internal → internal/src/transaction}/transaction-internal.ts +16 -13
  75. package/{src/internal → internal/src}/transaction/undo-transaction.ts +4 -5
  76. package/introspection/dist/index.d.mts +12 -260
  77. package/introspection/dist/index.d.ts +12 -260
  78. package/introspection/dist/index.js +125 -140
  79. package/introspection/dist/index.js.map +1 -1
  80. package/introspection/dist/index.mjs +103 -116
  81. package/introspection/dist/index.mjs.map +1 -1
  82. package/{src/introspection → introspection/src}/attach-atom-index.ts +41 -30
  83. package/{src/introspection → introspection/src}/attach-introspection-states.ts +6 -10
  84. package/introspection/src/attach-selector-index.ts +90 -0
  85. package/{src/introspection → introspection/src}/attach-timeline-family.ts +16 -16
  86. package/introspection/src/attach-timeline-index.ts +38 -0
  87. package/introspection/src/attach-transaction-index.ts +40 -0
  88. package/{src/introspection → introspection/src}/attach-transaction-logs.ts +11 -8
  89. package/json/dist/index.d.mts +41 -2
  90. package/json/dist/index.d.ts +41 -2
  91. package/json/dist/index.js +88 -48
  92. package/json/dist/index.js.map +1 -1
  93. package/json/dist/index.mjs +76 -13
  94. package/json/dist/index.mjs.map +1 -1
  95. package/json/src/index.ts +5 -0
  96. package/json/src/select-json-family.ts +35 -0
  97. package/json/src/select-json.ts +22 -0
  98. package/package.json +105 -57
  99. package/react/dist/index.d.mts +9 -17
  100. package/react/dist/index.d.ts +9 -17
  101. package/react/dist/index.js +45 -77
  102. package/react/dist/index.js.map +1 -1
  103. package/react/dist/index.mjs +18 -34
  104. package/react/dist/index.mjs.map +1 -1
  105. package/react/src/store-context.tsx +12 -0
  106. package/react/src/store-hooks.ts +36 -0
  107. package/react-devtools/dist/index.css +1 -1
  108. package/react-devtools/dist/index.css.map +1 -1
  109. package/react-devtools/dist/index.d.mts +199 -230
  110. package/react-devtools/dist/index.d.ts +199 -230
  111. package/react-devtools/dist/index.js +610 -2466
  112. package/react-devtools/dist/index.js.map +1 -1
  113. package/react-devtools/dist/index.mjs +543 -2401
  114. package/react-devtools/dist/index.mjs.map +1 -1
  115. package/{src/react-devtools → react-devtools/src}/AtomIODevtools.tsx +5 -3
  116. package/{src/react-devtools → react-devtools/src}/Button.tsx +2 -3
  117. package/{src/react-devtools → react-devtools/src}/StateEditor.tsx +3 -2
  118. package/{src/react-devtools → react-devtools/src}/StateIndex.tsx +7 -4
  119. package/{src/react-devtools → react-devtools/src}/TimelineIndex.tsx +7 -11
  120. package/{src/react-devtools → react-devtools/src}/TransactionIndex.tsx +4 -4
  121. package/{src/react-devtools → react-devtools/src}/Updates.tsx +9 -4
  122. package/{src/react-devtools → react-devtools/src}/index.ts +5 -5
  123. package/realtime-react/dist/index.d.mts +9 -25
  124. package/realtime-react/dist/index.d.ts +9 -25
  125. package/realtime-react/dist/index.js +75 -193
  126. package/realtime-react/dist/index.js.map +1 -1
  127. package/realtime-react/dist/index.mjs +44 -148
  128. package/realtime-react/dist/index.mjs.map +1 -1
  129. package/realtime-react/src/index.ts +7 -0
  130. package/{src/realtime-react → realtime-react/src}/realtime-context.tsx +3 -4
  131. package/realtime-react/src/use-pull-family-member.ts +15 -0
  132. package/realtime-react/src/use-pull-mutable-family-member.ts +20 -0
  133. package/realtime-react/src/use-pull-mutable.ts +17 -0
  134. package/realtime-react/src/use-pull.ts +15 -0
  135. package/realtime-react/src/use-push.ts +19 -0
  136. package/realtime-react/src/use-server-action.ts +18 -0
  137. package/realtime-testing/dist/index.d.mts +49 -0
  138. package/realtime-testing/dist/index.d.ts +49 -0
  139. package/realtime-testing/dist/index.js +147 -0
  140. package/realtime-testing/dist/index.js.map +1 -0
  141. package/realtime-testing/dist/index.mjs +116 -0
  142. package/realtime-testing/dist/index.mjs.map +1 -0
  143. package/{src/realtime-testing → realtime-testing/src}/setup-realtime-test.tsx +10 -8
  144. package/src/atom.ts +64 -8
  145. package/src/index.ts +36 -29
  146. package/src/logger.ts +7 -7
  147. package/src/selector.ts +5 -5
  148. package/src/silo.ts +49 -43
  149. package/src/subscribe.ts +27 -22
  150. package/src/timeline.ts +9 -4
  151. package/src/transaction.ts +3 -4
  152. package/transceivers/set-rtx/dist/index.d.mts +39 -0
  153. package/transceivers/set-rtx/dist/index.d.ts +39 -0
  154. package/transceivers/set-rtx/dist/index.js +213 -0
  155. package/transceivers/set-rtx/dist/index.js.map +1 -0
  156. package/transceivers/set-rtx/dist/index.mjs +211 -0
  157. package/transceivers/set-rtx/dist/index.mjs.map +1 -0
  158. package/{realtime → transceivers/set-rtx}/package.json +1 -1
  159. package/transceivers/set-rtx/src/index.ts +1 -0
  160. package/transceivers/set-rtx/src/set-rtx.ts +242 -0
  161. package/realtime/dist/index.d.mts +0 -25
  162. package/realtime/dist/index.d.ts +0 -25
  163. package/realtime/dist/index.js +0 -190
  164. package/realtime/dist/index.js.map +0 -1
  165. package/realtime/dist/index.mjs +0 -151
  166. package/realtime/dist/index.mjs.map +0 -1
  167. package/src/internal/atom-internal.ts +0 -54
  168. package/src/internal/families-internal.ts +0 -144
  169. package/src/internal/get.ts +0 -129
  170. package/src/internal/index.ts +0 -15
  171. package/src/internal/operation.ts +0 -139
  172. package/src/internal/selector/lookup-selector-sources.ts +0 -16
  173. package/src/internal/selector-internal.ts +0 -58
  174. package/src/internal/set.ts +0 -99
  175. package/src/internal/store.ts +0 -151
  176. package/src/internal/subscribe-internal.ts +0 -88
  177. package/src/internal/timeline/index.ts +0 -1
  178. package/src/introspection/attach-selector-index.ts +0 -77
  179. package/src/introspection/attach-timeline-index.ts +0 -36
  180. package/src/introspection/attach-transaction-index.ts +0 -38
  181. package/src/json/index.ts +0 -1
  182. package/src/json/select-json.ts +0 -18
  183. package/src/react/store-context.tsx +0 -13
  184. package/src/react/store-hooks.ts +0 -47
  185. package/src/react-explorer/AtomIOExplorer.tsx +0 -218
  186. package/src/react-explorer/explorer-effects.ts +0 -20
  187. package/src/react-explorer/explorer-states.ts +0 -217
  188. package/src/react-explorer/index.ts +0 -23
  189. package/src/react-explorer/space-states.ts +0 -72
  190. package/src/react-explorer/view-states.ts +0 -41
  191. package/src/realtime/README.md +0 -33
  192. package/src/realtime/hook-composition/expose-family.ts +0 -101
  193. package/src/realtime/hook-composition/expose-single.ts +0 -38
  194. package/src/realtime/hook-composition/expose-timeline.ts +0 -60
  195. package/src/realtime/hook-composition/index.ts +0 -12
  196. package/src/realtime/hook-composition/receive-state.ts +0 -29
  197. package/src/realtime/hook-composition/receive-transaction.ts +0 -18
  198. package/src/realtime/index.ts +0 -1
  199. package/src/realtime-react/index.ts +0 -3
  200. package/src/realtime-react/realtime-hooks.ts +0 -39
  201. package/src/realtime-react/realtime-state.ts +0 -10
  202. package/src/realtime-react/use-pull-family-member.ts +0 -26
  203. package/src/realtime-react/use-pull-family.ts +0 -24
  204. package/src/realtime-react/use-pull.ts +0 -24
  205. package/src/realtime-react/use-push.ts +0 -27
  206. package/src/realtime-react/use-server-action.ts +0 -33
  207. package/src/tracker/index.ts +0 -3
  208. package/src/tracker/tracker.ts +0 -61
  209. package/src/web-effects/index.ts +0 -1
  210. package/src/web-effects/storage.ts +0 -30
  211. /package/{src/introspection → introspection/src}/index.ts +0 -0
  212. /package/{src/react → react/src}/index.ts +0 -0
  213. /package/{src/react-devtools → react-devtools/src}/devtools.scss +0 -0
  214. /package/{src/realtime-testing → realtime-testing/src}/index.ts +0 -0
@@ -1,16 +1,13 @@
1
- import { become } from "~/packages/anvl/src/function"
1
+ import type { FamilyMetadata, SelectorOptions, SelectorToken } from "atom.io"
2
2
 
3
- import { Subject } from ".."
4
- import {
5
- type Store,
6
- type Selector,
7
- type StoreCore,
8
- registerSelector,
9
- selector__INTERNAL,
10
- } from ".."
11
- import type { FamilyMetadata, SelectorToken } from "../.."
12
- import type { SelectorOptions } from "../../selector"
13
- import { cacheValue, markDone } from "../operation"
3
+ import { cacheValue } from "../caching"
4
+ import { markDone } from "../operation"
5
+ import { become } from "../set-state/become"
6
+ import type { Store, StoreCore } from "../store"
7
+ import { Subject } from "../subject"
8
+ import type { Selector } from "./create-selector"
9
+ import { createSelector } from "./create-selector"
10
+ import { registerSelector } from "./register-selector"
14
11
 
15
12
  export const createReadWriteSelector = <T>(
16
13
  options: SelectorOptions<T>,
@@ -47,7 +44,7 @@ export const createReadWriteSelector = <T>(
47
44
  const mySelector: Selector<T> = {
48
45
  ...options,
49
46
  subject,
50
- install: (s: Store) => selector__INTERNAL(options, family, s),
47
+ install: (s: Store) => createSelector(options, family, s),
51
48
  get: getSelf,
52
49
  set: setSelf,
53
50
  type: `selector`,
@@ -1,14 +1,15 @@
1
- import { registerSelector } from "./register-selector"
2
- import { Subject } from ".."
3
1
  import type {
4
2
  FamilyMetadata,
5
3
  ReadonlySelectorOptions,
6
4
  ReadonlySelectorToken,
7
- Store,
8
- } from "../.."
9
- import { cacheValue } from "../operation"
10
- import { selector__INTERNAL, type ReadonlySelector } from "../selector-internal"
11
- import type { StoreCore } from "../store"
5
+ } from "atom.io"
6
+
7
+ import { cacheValue } from "../caching"
8
+ import type { Store, StoreCore } from "../store"
9
+ import { Subject } from "../subject"
10
+ import type { ReadonlySelector } from "./create-selector"
11
+ import { createSelector } from "./create-selector"
12
+ import { registerSelector } from "./register-selector"
12
13
 
13
14
  export const createReadonlySelector = <T>(
14
15
  options: ReadonlySelectorOptions<T>,
@@ -28,7 +29,7 @@ export const createReadonlySelector = <T>(
28
29
  const readonlySelector: ReadonlySelector<T> = {
29
30
  ...options,
30
31
  subject,
31
- install: (s: Store) => selector__INTERNAL(options, family, s),
32
+ install: (s: Store) => createSelector(options, family, s),
32
33
  get: getSelf,
33
34
  type: `readonly_selector`,
34
35
  ...(family && { family }),
@@ -0,0 +1,65 @@
1
+ import type {
2
+ FamilyMetadata,
3
+ ReadonlySelectorOptions,
4
+ ReadonlySelectorToken,
5
+ SelectorOptions,
6
+ SelectorToken,
7
+ } from "atom.io"
8
+
9
+ import type { Store } from "../store"
10
+ import { IMPLICIT } from "../store"
11
+ import type { Subject } from "../subject"
12
+ import { target } from "../transaction"
13
+ import { createReadWriteSelector } from "./create-read-write-selector"
14
+ import { createReadonlySelector } from "./create-readonly-selector"
15
+
16
+ export type Selector<T> = {
17
+ key: string
18
+ type: `selector`
19
+ family?: FamilyMetadata
20
+ install: (store: Store) => void
21
+ subject: Subject<{ newValue: T; oldValue: T }>
22
+ get: () => T
23
+ set: (newValue: T | ((oldValue: T) => T)) => void
24
+ }
25
+ export type ReadonlySelector<T> = {
26
+ key: string
27
+ type: `readonly_selector`
28
+ family?: FamilyMetadata
29
+ install: (store: Store) => void
30
+ subject: Subject<{ newValue: T; oldValue: T }>
31
+ get: () => T
32
+ }
33
+
34
+ export function createSelector<T>(
35
+ options: SelectorOptions<T>,
36
+ family?: FamilyMetadata,
37
+ store?: Store,
38
+ ): SelectorToken<T>
39
+ export function createSelector<T>(
40
+ options: ReadonlySelectorOptions<T>,
41
+ family?: FamilyMetadata,
42
+ store?: Store,
43
+ ): ReadonlySelectorToken<T>
44
+ export function createSelector<T>(
45
+ options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
46
+ family?: FamilyMetadata,
47
+ store: Store = IMPLICIT.STORE,
48
+ ): ReadonlySelectorToken<T> | SelectorToken<T> {
49
+ const core = target(store)
50
+ const existingWritable = core.selectors.get(options.key)
51
+ const existingReadonly = core.readonlySelectors.get(options.key)
52
+
53
+ if (existingWritable || existingReadonly) {
54
+ store.config.logger?.error?.(
55
+ `Tried to create ${existingReadonly ? `readonly selector` : `selector`}`,
56
+ `"${options.key}", but it already exists in the store.`,
57
+ `(Ignore if you are using hot module replacement.)`,
58
+ )
59
+ }
60
+
61
+ if (`set` in options) {
62
+ return createReadWriteSelector(options, family, store, core)
63
+ }
64
+ return createReadonlySelector(options, family, store, core)
65
+ }
@@ -1,4 +1,5 @@
1
1
  export * from "./lookup-selector-sources"
2
2
  export * from "./register-selector"
3
+ export * from "./create-selector"
3
4
  export * from "./trace-selector-atoms"
4
5
  export * from "./update-selector-atoms"
@@ -0,0 +1,20 @@
1
+ import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "atom.io"
2
+
3
+ import type { Store } from "../store"
4
+ import { lookup } from "../store"
5
+ import { target } from "../transaction"
6
+
7
+ export const lookupSelectorSources = (
8
+ key: string,
9
+ store: Store,
10
+ ): (
11
+ | AtomToken<unknown>
12
+ | ReadonlySelectorToken<unknown>
13
+ | SelectorToken<unknown>
14
+ )[] => {
15
+ const sources = target(store)
16
+ .selectorGraph.getRelationEntries({ downstreamSelectorKey: key })
17
+ .filter(([_, { source }]) => source !== key)
18
+ .map(([_, { source }]) => lookup(source, store))
19
+ return sources
20
+ }
@@ -1,10 +1,11 @@
1
- import { updateSelectorAtoms } from "./update-selector-atoms"
2
- import type { Transactors } from "../../transaction"
3
- import { getState__INTERNAL, withdraw } from "../get"
4
- import { setState__INTERNAL } from "../set"
1
+ import type { Transactors } from "atom.io"
2
+
3
+ import { getState__INTERNAL } from "../get-state-internal"
4
+ import { setState__INTERNAL } from "../set-state"
5
5
  import type { Store } from "../store"
6
- import { IMPLICIT } from "../store"
7
- import { target } from "../transaction-internal"
6
+ import { IMPLICIT, withdraw } from "../store"
7
+ import { target } from "../transaction/transaction-internal"
8
+ import { updateSelectorAtoms } from "./update-selector-atoms"
8
9
 
9
10
  export const registerSelector = (
10
11
  selectorKey: string,
@@ -13,8 +14,8 @@ export const registerSelector = (
13
14
  get: (dependency) => {
14
15
  const core = target(store)
15
16
  const alreadyRegistered = core.selectorGraph
16
- .getRelations(selectorKey)
17
- .some(({ source }) => source === dependency.key)
17
+ .getRelationEntries({ downstreamSelectorKey: selectorKey })
18
+ .some(([_, { source }]) => source === dependency.key)
18
19
 
19
20
  const dependencyState = withdraw(dependency, store)
20
21
  if (dependencyState === null) {
@@ -36,7 +37,10 @@ export const registerSelector = (
36
37
  `)`,
37
38
  )
38
39
  core.selectorGraph = core.selectorGraph.set(
39
- { from: dependency.key, to: selectorKey },
40
+ {
41
+ upstreamSelectorKey: dependency.key,
42
+ downstreamSelectorKey: selectorKey,
43
+ },
40
44
  {
41
45
  source: dependency.key,
42
46
  },
@@ -1,5 +1,7 @@
1
+ import type { AtomToken, ReadonlySelectorToken, StateToken } from "atom.io"
2
+
3
+ import type { Store } from ".."
1
4
  import { lookupSelectorSources } from "./lookup-selector-sources"
2
- import type { Store, AtomToken, ReadonlySelectorToken, StateToken } from "../.."
3
5
 
4
6
  export const traceSelectorAtoms = (
5
7
  selectorKey: string,
@@ -11,7 +13,7 @@ export const traceSelectorAtoms = (
11
13
  const sources = lookupSelectorSources(dependency.key, store)
12
14
  let depth = 0
13
15
  while (sources.length > 0) {
14
- // rome-ignore lint/style/noNonNullAssertion: just checked length ^^^
16
+ // biome-ignore lint/style/noNonNullAssertion: just checked length ^^^
15
17
  const source = sources.shift()!
16
18
  ++depth
17
19
  if (depth > 999) {
@@ -1,7 +1,8 @@
1
+ import type { ReadonlySelectorToken, StateToken } from "atom.io"
2
+
3
+ import type { Store } from "../store"
4
+ import { target } from "../transaction"
1
5
  import { traceSelectorAtoms } from "./trace-selector-atoms"
2
- import type { Store } from ".."
3
- import { target } from ".."
4
- import type { ReadonlySelectorToken, StateToken } from "../.."
5
6
 
6
7
  export const updateSelectorAtoms = (
7
8
  selectorKey: string,
@@ -0,0 +1,10 @@
1
+ export type Modify<T> = (thing: T) => T
2
+
3
+ export const become =
4
+ <T>(nextVersionOfThing: Modify<T> | T) =>
5
+ (originalThing: T): T =>
6
+ nextVersionOfThing instanceof Function
7
+ ? nextVersionOfThing(
8
+ originalThing instanceof Function ? originalThing() : originalThing,
9
+ )
10
+ : nextVersionOfThing
@@ -0,0 +1,23 @@
1
+ import type { JsonInterface } from "atom.io/json"
2
+
3
+ import type { Atom } from "../atom"
4
+ import { Tracker } from "../mutable"
5
+ import type { Store, StoreCore } from "../store"
6
+
7
+ export function copyMutableIfNeeded<T>(
8
+ atom: Atom<T>,
9
+ transform: JsonInterface<T>,
10
+ origin: Store,
11
+ target: StoreCore,
12
+ ): T {
13
+ const originValue = origin.valueMap.get(atom.key)
14
+ const targetValue = target.valueMap.get(atom.key)
15
+ if (originValue === targetValue) {
16
+ origin.config.logger?.info(`📃 copying`, `${atom.key}`)
17
+ const copiedValue = transform.fromJson(transform.toJson(originValue))
18
+ target.valueMap.set(atom.key, copiedValue)
19
+ new Tracker(atom, origin)
20
+ return copiedValue
21
+ }
22
+ return targetValue
23
+ }
@@ -0,0 +1,59 @@
1
+ import type { AtomFamily } from "atom.io"
2
+ import type { Json, JsonInterface } from "atom.io/json"
3
+ import { getState__INTERNAL } from ".."
4
+ import type { Store, StoreCore } from ".."
5
+ import type { Atom } from "../atom"
6
+ import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
7
+
8
+ export function copyMutableIfWithinTransaction<T>(
9
+ atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
10
+ store: Store,
11
+ ): T {
12
+ if (
13
+ store.transactionStatus.phase === `building` ||
14
+ store.transactionStatus.phase === `applying`
15
+ ) {
16
+ if (`toJson` in atom && `fromJson` in atom) {
17
+ store.config.logger?.info(
18
+ `📄 copyMutableIfWithinTransaction: ${atom.key} is mutable`,
19
+ )
20
+ const copiedValue = copyMutableIfNeeded(
21
+ atom,
22
+ atom,
23
+ store,
24
+ store.transactionStatus.core,
25
+ )
26
+ return copiedValue
27
+ }
28
+ if (`family` in atom) {
29
+ const family = store.transactionStatus.core.families.get(atom.family.key)
30
+ if (family && family.type === `atom_family`) {
31
+ const result = copyMutableFamilyMemberWithinTransaction<T>(
32
+ atom,
33
+ family,
34
+ store,
35
+ store.transactionStatus.core,
36
+ )
37
+ if (result) {
38
+ return result
39
+ }
40
+ }
41
+ }
42
+ }
43
+ return getState__INTERNAL(atom, store)
44
+ }
45
+
46
+ export function copyMutableFamilyMemberWithinTransaction<T>(
47
+ atom: Atom<T>,
48
+ family:
49
+ | AtomFamily<T, any>
50
+ | (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
51
+ origin: Store,
52
+ target: StoreCore,
53
+ ): T | null {
54
+ if (`toJson` in family && `fromJson` in family) {
55
+ const copyCreated = copyMutableIfNeeded(atom, family, origin, target)
56
+ return copyCreated
57
+ }
58
+ return null
59
+ }
@@ -0,0 +1,34 @@
1
+ import type { AtomFamily } from "atom.io"
2
+ import type { Json, JsonInterface } from "atom.io/json"
3
+ import type { Store, StoreCore } from ".."
4
+ import type { Atom } from "../atom"
5
+ import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
6
+
7
+ export function copyMutableIntoNewStore<T>(
8
+ atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
9
+ origin: Store,
10
+ target: Store,
11
+ ): void {
12
+ if (`toJson` in atom && `fromJson` in atom) {
13
+ copyMutableIfNeeded(atom, atom, origin, target)
14
+ }
15
+ if (`family` in atom) {
16
+ const family = target.families.get(atom.family.key)
17
+ if (family && family.type === `atom_family`) {
18
+ copyMutableFamilyMemberIntoNewStore(atom, family, origin, target)
19
+ }
20
+ }
21
+ }
22
+
23
+ export function copyMutableFamilyMemberIntoNewStore<T>(
24
+ atom: Atom<T>,
25
+ family:
26
+ | AtomFamily<T, any>
27
+ | (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
28
+ origin: Store,
29
+ target: Store,
30
+ ): void {
31
+ if (`toJson` in family && `fromJson` in family) {
32
+ copyMutableIfNeeded(atom, family, origin, target)
33
+ }
34
+ }
@@ -0,0 +1,23 @@
1
+ import type { StateUpdate } from "atom.io"
2
+ import type { Store } from "atom.io/internal"
3
+
4
+ import type { Atom } from "../atom"
5
+ import type { ReadonlySelector, Selector } from "../selector"
6
+
7
+ export const emitUpdate = <T>(
8
+ state: Atom<T> | ReadonlySelector<T> | Selector<T>,
9
+ update: StateUpdate<T>,
10
+ store: Store,
11
+ ): void => {
12
+ const { key } = state
13
+ const { logger } = store.config
14
+ logger?.info(
15
+ `📢 ${state.type} "${key}" went (`,
16
+ update.oldValue,
17
+ `->`,
18
+ update.newValue,
19
+ `)`,
20
+ )
21
+ logger?.info(`📢 notifying subscribers:`, state.subject.subscribers)
22
+ state.subject.next(update)
23
+ }
@@ -0,0 +1,39 @@
1
+ import type { Atom } from "../atom"
2
+ import { isDone, markDone } from "../operation"
3
+ import type { Store } from "../store"
4
+ import { IMPLICIT } from "../store"
5
+ import { target } from "../transaction"
6
+
7
+ export const evictDownStream = <T>(
8
+ state: Atom<T>,
9
+ store: Store = IMPLICIT.STORE,
10
+ ): void => {
11
+ const core = target(store)
12
+ const downstreamKeys = core.selectorAtoms.getRelatedKeys(state.key)
13
+ store.config.logger?.info(
14
+ ` || ${downstreamKeys?.size ?? `none`} downstream:`,
15
+ downstreamKeys,
16
+ )
17
+ if (core.operation.open) {
18
+ store.config.logger?.info(` ||`, [...core.operation.done], `already done`)
19
+ }
20
+ if (downstreamKeys) {
21
+ for (const key of downstreamKeys) {
22
+ if (isDone(key, store)) {
23
+ store.config.logger?.info(` || ${key} already done`)
24
+ continue
25
+ }
26
+ const state = core.selectors.get(key) ?? core.readonlySelectors.get(key)
27
+ if (!state) {
28
+ store.config.logger?.info(
29
+ ` || ${key} was not found in selectors or readonlySelectors`,
30
+ )
31
+ return
32
+ }
33
+ core.valueMap.delete(key)
34
+ store.config.logger?.info(` xx evicted "${key}"`)
35
+
36
+ markDone(key, store)
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./become"
2
+ export * from "./set-state-internal"
@@ -0,0 +1,38 @@
1
+ import type { Atom } from "../atom"
2
+ import { isAtomDefault, markAtomAsNotDefault } from "../atom"
3
+ import { cacheValue } from "../caching"
4
+ import { getState__INTERNAL } from "../get-state-internal"
5
+ import { markDone } from "../operation"
6
+ import type { Store } from "../store"
7
+ import { IMPLICIT } from "../store"
8
+ import { become } from "./become"
9
+ import { copyMutableIfWithinTransaction } from "./copy-mutable-in-transaction"
10
+ import { emitUpdate } from "./emit-update"
11
+ import { evictDownStream } from "./evict-downstream"
12
+ import { stowUpdate } from "./stow-update"
13
+
14
+ export const setAtomState = <T>(
15
+ atom: Atom<T>,
16
+ next: T | ((oldValue: T) => T),
17
+ store: Store = IMPLICIT.STORE,
18
+ ): void => {
19
+ const oldValue = getState__INTERNAL(atom, store)
20
+ let newValue = copyMutableIfWithinTransaction(atom, store)
21
+ newValue = become(next)(newValue)
22
+ store.config.logger?.info(`<< setting atom "${atom.key}" to`, newValue)
23
+ cacheValue(atom.key, newValue, store)
24
+ if (isAtomDefault(atom.key, store)) {
25
+ markAtomAsNotDefault(atom.key, store)
26
+ }
27
+ markDone(atom.key, store)
28
+ store.config.logger?.info(
29
+ ` || evicting caches downstream from "${atom.key}"`,
30
+ )
31
+ evictDownStream(atom, store)
32
+ const update = { oldValue, newValue }
33
+ if (store.transactionStatus.phase !== `building`) {
34
+ emitUpdate(atom, update, store)
35
+ } else {
36
+ stowUpdate(atom, update, store)
37
+ }
38
+ }
@@ -0,0 +1,19 @@
1
+ import { getState__INTERNAL } from "../get-state-internal"
2
+ import type { Selector } from "../selector"
3
+ import type { Store } from "../store"
4
+ import { IMPLICIT } from "../store"
5
+ import { become } from "./become"
6
+
7
+ export const setSelectorState = <T>(
8
+ selector: Selector<T>,
9
+ next: T | ((oldValue: T) => T),
10
+ store: Store = IMPLICIT.STORE,
11
+ ): void => {
12
+ const oldValue = getState__INTERNAL(selector, store)
13
+ const newValue = become(next)(oldValue)
14
+
15
+ store.config.logger?.info(`<< setting selector "${selector.key}" to`, newValue)
16
+ store.config.logger?.info(` || propagating change made to "${selector.key}"`)
17
+
18
+ selector.set(newValue)
19
+ }
@@ -0,0 +1,18 @@
1
+ import type { Atom } from "../atom"
2
+ import type { Selector } from "../selector"
3
+ import type { Store } from "../store"
4
+ import { IMPLICIT } from "../store"
5
+ import { setAtomState } from "./set-atom-state"
6
+ import { setSelectorState } from "./set-selector-state"
7
+
8
+ export const setState__INTERNAL = <T>(
9
+ state: Atom<T> | Selector<T>,
10
+ value: T | ((oldValue: T) => T),
11
+ store: Store = IMPLICIT.STORE,
12
+ ): void => {
13
+ if (`set` in state) {
14
+ setSelectorState(state, value, store)
15
+ } else {
16
+ setAtomState(state, value, store)
17
+ }
18
+ }
@@ -0,0 +1,42 @@
1
+ import type { KeyedStateUpdate, StateUpdate } from "atom.io"
2
+
3
+ import type { Atom } from "../atom"
4
+ import { isTransceiver } from "../mutable"
5
+ import type { Store } from "../store"
6
+
7
+ function shouldUpdateBeStowed(key: string, update: StateUpdate<any>): boolean {
8
+ // do not stow updates that aren't json, unless they're not equal by reference
9
+ if (isTransceiver(update.newValue)) {
10
+ return false
11
+ }
12
+ // do not stow updates where the key contains 👁‍🗨
13
+ if (key.includes(`👁‍🗨`)) {
14
+ return false
15
+ }
16
+ return true
17
+ }
18
+
19
+ export const stowUpdate = <T>(
20
+ state: Atom<T>,
21
+ update: StateUpdate<T>,
22
+ store: Store,
23
+ ): void => {
24
+ const { key } = state
25
+ const { logger } = store.config
26
+ if (store.transactionStatus.phase !== `building`) {
27
+ store.config.logger?.warn(
28
+ `stowUpdate called outside of a transaction. This is probably a bug.`,
29
+ )
30
+ return
31
+ }
32
+ const shouldStow = shouldUpdateBeStowed(key, update)
33
+ if (!shouldStow) {
34
+ return
35
+ }
36
+ const atomUpdate: KeyedStateUpdate<T> = { key, ...update }
37
+ if (state.family) {
38
+ atomUpdate.family = state.family
39
+ }
40
+ store.transactionStatus.atomUpdates.push(atomUpdate)
41
+ logger?.info(`📝 ${key} stowed (`, update.oldValue, `->`, update.newValue, `)`)
42
+ }
@@ -0,0 +1,43 @@
1
+ import type {
2
+ AtomToken,
3
+ ReadonlySelectorToken,
4
+ SelectorToken,
5
+ StateToken,
6
+ TransactionToken,
7
+ ƒn,
8
+ } from "atom.io"
9
+
10
+ import type { Atom } from "../atom"
11
+ import type { ReadonlySelector, Selector } from "../selector"
12
+ import type { Transaction } from "../transaction"
13
+
14
+ export function deposit<T>(state: Atom<T>): AtomToken<T>
15
+ export function deposit<T>(state: Selector<T>): SelectorToken<T>
16
+ export function deposit<T>(state: Atom<T> | Selector<T>): StateToken<T>
17
+ export function deposit<T>(state: ReadonlySelector<T>): ReadonlySelectorToken<T>
18
+ export function deposit<T>(
19
+ state: Transaction<T extends ƒn ? T : never>,
20
+ ): TransactionToken<T>
21
+ export function deposit<T>(
22
+ state: Atom<T> | ReadonlySelector<T> | Selector<T>,
23
+ ): ReadonlySelectorToken<T> | StateToken<T>
24
+ export function deposit<T>(
25
+ state:
26
+ | Atom<T>
27
+ | ReadonlySelector<T>
28
+ | Selector<T>
29
+ | Transaction<T extends ƒn ? T : never>,
30
+ ):
31
+ | AtomToken<T>
32
+ | ReadonlySelectorToken<T>
33
+ | SelectorToken<T>
34
+ | TransactionToken<T> {
35
+ const token = {
36
+ key: state.key,
37
+ type: state.type,
38
+ } as any
39
+ if (`family` in state) {
40
+ token.family = state.family
41
+ }
42
+ return token
43
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./deposit"
2
+ export * from "./lookup"
3
+ export * from "./store"
4
+ export * from "./withdraw"
5
+ export * from "./withdraw-new-family-member"
@@ -0,0 +1,26 @@
1
+ import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "atom.io"
2
+
3
+ import { target } from "../transaction"
4
+ import type { Store } from "./store"
5
+
6
+ export function lookup(
7
+ key: string,
8
+ store: Store,
9
+ ): AtomToken<unknown> | ReadonlySelectorToken<unknown> | SelectorToken<unknown> {
10
+ const core = target(store)
11
+ let type: string = core.atoms.has(key)
12
+ ? `atom`
13
+ : core.selectors.has(key)
14
+ ? `selector`
15
+ : core.readonlySelectors.has(key)
16
+ ? `readonly_selector`
17
+ : ``
18
+ if (!type) {
19
+ const errorId = Math.random().toString(36)
20
+ type = `🚨 This state could not be found by lookup! Check the console for "${errorId}"`
21
+ store.config.logger?.error(
22
+ `${errorId}: Key "${key}" does not exist in the store.`,
23
+ )
24
+ }
25
+ return { key, type } as any
26
+ }