atom.io 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/data/dist/index.cjs +62 -40
  2. package/data/dist/index.cjs.map +1 -1
  3. package/data/dist/index.d.ts +8 -2
  4. package/data/dist/index.js +64 -42
  5. package/data/dist/index.js.map +1 -1
  6. package/data/src/dict.ts +8 -4
  7. package/data/src/join.ts +74 -33
  8. package/data/src/struct-family.ts +18 -17
  9. package/dist/chunk-IZHOMSXA.js +331 -0
  10. package/dist/chunk-IZHOMSXA.js.map +1 -0
  11. package/dist/chunk-JDUNWJFB.js +18 -0
  12. package/dist/chunk-JDUNWJFB.js.map +1 -0
  13. package/dist/index.cjs +4 -10
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +66 -51
  16. package/dist/index.js +5 -11
  17. package/dist/index.js.map +1 -1
  18. package/internal/dist/index.cjs +187 -58
  19. package/internal/dist/index.cjs.map +1 -1
  20. package/internal/dist/index.d.ts +95 -71
  21. package/internal/dist/index.js +179 -53
  22. package/internal/dist/index.js.map +1 -1
  23. package/internal/src/arbitrary.ts +3 -0
  24. package/internal/src/atom/delete-atom.ts +7 -6
  25. package/internal/src/caching.ts +6 -4
  26. package/internal/src/families/find-in-store.ts +16 -0
  27. package/internal/src/get-environment-data.ts +4 -7
  28. package/internal/src/index.ts +6 -5
  29. package/internal/src/ingest-updates/ingest-atom-update.ts +6 -2
  30. package/internal/src/ingest-updates/ingest-transaction-update.ts +0 -1
  31. package/internal/src/selector/create-standalone-selector.ts +0 -2
  32. package/internal/src/set-state/copy-mutable-if-needed.ts +5 -0
  33. package/internal/src/set-state/emit-update.ts +25 -11
  34. package/internal/src/set-state/set-atom.ts +15 -18
  35. package/internal/src/store/store.ts +14 -2
  36. package/internal/src/store/withdraw.ts +72 -2
  37. package/internal/src/subscribe/subscribe-to-timeline.ts +2 -2
  38. package/internal/src/subscribe/subscribe-to-transaction.ts +2 -2
  39. package/internal/src/timeline/create-timeline.ts +12 -1
  40. package/internal/src/transaction/act-upon-store.ts +19 -0
  41. package/internal/src/transaction/apply-transaction.ts +6 -1
  42. package/internal/src/transaction/assign-transaction-to-continuity.ts +18 -0
  43. package/internal/src/transaction/build-transaction.ts +7 -6
  44. package/internal/src/transaction/create-transaction.ts +1 -1
  45. package/internal/src/transaction/get-epoch-number.ts +40 -0
  46. package/internal/src/transaction/index.ts +10 -1
  47. package/internal/src/transaction/set-epoch-number.ts +30 -0
  48. package/introspection/dist/index.cjs.map +1 -1
  49. package/introspection/dist/index.d.ts +3 -3
  50. package/introspection/dist/index.js.map +1 -1
  51. package/introspection/src/attach-introspection-states.ts +6 -2
  52. package/introspection/src/attach-timeline-family.ts +5 -2
  53. package/introspection/src/attach-transaction-logs.ts +2 -2
  54. package/json/dist/index.d.ts +3 -1
  55. package/json/src/index.ts +4 -0
  56. package/package.json +241 -230
  57. package/react/dist/index.cjs.map +1 -1
  58. package/react/dist/index.d.ts +1 -1
  59. package/react/dist/index.js.map +1 -1
  60. package/react/src/use-json.ts +1 -1
  61. package/react-devtools/dist/index.cjs +131 -134
  62. package/react-devtools/dist/index.cjs.map +1 -1
  63. package/react-devtools/dist/index.css +2 -2
  64. package/react-devtools/dist/index.css.map +1 -1
  65. package/react-devtools/dist/index.d.ts +3 -3
  66. package/react-devtools/dist/index.js +91 -108
  67. package/react-devtools/dist/index.js.map +1 -1
  68. package/react-devtools/src/StateEditor.tsx +4 -4
  69. package/react-devtools/src/StateIndex.tsx +1 -4
  70. package/react-devtools/src/TimelineIndex.tsx +3 -3
  71. package/react-devtools/src/TransactionIndex.tsx +9 -8
  72. package/react-devtools/src/index.ts +2 -2
  73. package/realtime/dist/index.cjs +120 -0
  74. package/realtime/dist/index.cjs.map +1 -0
  75. package/realtime/dist/index.d.ts +146 -0
  76. package/realtime/dist/index.js +111 -0
  77. package/realtime/dist/index.js.map +1 -0
  78. package/realtime/package.json +16 -0
  79. package/realtime/src/index.ts +2 -0
  80. package/realtime/src/realtime-continuity.ts +162 -0
  81. package/realtime/src/shared-room-store.ts +48 -0
  82. package/realtime-client/dist/index.cjs +424 -170
  83. package/realtime-client/dist/index.cjs.map +1 -1
  84. package/realtime-client/dist/index.d.ts +15 -11
  85. package/realtime-client/dist/index.js +96 -177
  86. package/realtime-client/dist/index.js.map +1 -1
  87. package/realtime-client/src/index.ts +8 -7
  88. package/realtime-client/src/{pull-family-member.ts → pull-atom-family-member.ts} +2 -2
  89. package/realtime-client/src/{pull-state.ts → pull-atom.ts} +2 -2
  90. package/realtime-client/src/{pull-mutable-family-member.ts → pull-mutable-atom-family-member.ts} +6 -6
  91. package/realtime-client/src/{pull-mutable.ts → pull-mutable-atom.ts} +1 -1
  92. package/realtime-client/src/pull-selector-family-member.ts +42 -0
  93. package/realtime-client/src/pull-selector.ts +38 -0
  94. package/realtime-client/src/realtime-client-stores/client-main-store.ts +12 -2
  95. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +7 -7
  96. package/realtime-client/src/sync-continuity.ts +368 -0
  97. package/realtime-react/dist/index.cjs +367 -27
  98. package/realtime-react/dist/index.cjs.map +1 -1
  99. package/realtime-react/dist/index.d.ts +24 -8
  100. package/realtime-react/dist/index.js +38 -22
  101. package/realtime-react/dist/index.js.map +1 -1
  102. package/realtime-react/src/index.ts +6 -5
  103. package/realtime-react/src/use-pull-atom-family-member.ts +21 -0
  104. package/realtime-react/src/{use-sync.ts → use-pull-atom.ts} +4 -4
  105. package/realtime-react/src/{use-pull-mutable.ts → use-pull-mutable-atom.ts} +4 -3
  106. package/realtime-react/src/use-pull-mutable-family-member.ts +9 -4
  107. package/realtime-react/src/use-pull-selector-family-member.ts +21 -0
  108. package/realtime-react/src/{use-pull.ts → use-pull-selector.ts} +7 -5
  109. package/realtime-react/src/use-push.ts +3 -2
  110. package/realtime-react/src/use-server-action.ts +3 -2
  111. package/realtime-react/src/use-sync-continuity.ts +12 -0
  112. package/realtime-server/dist/index.cjs +769 -371
  113. package/realtime-server/dist/index.cjs.map +1 -1
  114. package/realtime-server/dist/index.d.ts +130 -60
  115. package/realtime-server/dist/index.js +753 -361
  116. package/realtime-server/dist/index.js.map +1 -1
  117. package/realtime-server/src/index.ts +17 -3
  118. package/realtime-server/src/ipc-sockets/child-socket.ts +135 -0
  119. package/realtime-server/src/ipc-sockets/custom-socket.ts +90 -0
  120. package/realtime-server/src/ipc-sockets/index.ts +3 -0
  121. package/realtime-server/src/ipc-sockets/parent-socket.ts +185 -0
  122. package/realtime-server/src/realtime-action-receiver.ts +8 -5
  123. package/realtime-server/src/realtime-continuity-synchronizer.ts +376 -0
  124. package/realtime-server/src/realtime-family-provider.ts +30 -71
  125. package/realtime-server/src/realtime-mutable-family-provider.ts +24 -86
  126. package/realtime-server/src/realtime-server-stores/index.ts +4 -1
  127. package/realtime-server/src/realtime-server-stores/realtime-continuity-store.ts +109 -0
  128. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +64 -0
  129. package/realtime-server/src/realtime-server-stores/server-room-external-store.ts +42 -0
  130. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +51 -98
  131. package/realtime-server/src/realtime-server-stores/server-user-store.ts +14 -29
  132. package/realtime-server/src/realtime-state-receiver.ts +0 -1
  133. package/realtime-testing/dist/index.cjs +34 -32
  134. package/realtime-testing/dist/index.cjs.map +1 -1
  135. package/realtime-testing/dist/index.d.ts +1 -0
  136. package/realtime-testing/dist/index.js +33 -31
  137. package/realtime-testing/dist/index.js.map +1 -1
  138. package/realtime-testing/src/setup-realtime-test.tsx +44 -32
  139. package/src/atom.ts +49 -31
  140. package/src/logger.ts +14 -5
  141. package/src/selector.ts +44 -25
  142. package/src/subscribe.ts +2 -1
  143. package/src/timeline.ts +4 -4
  144. package/src/transaction.ts +13 -17
  145. package/src/validators.ts +15 -9
  146. package/dist/chunk-H4Q5FTPZ.js +0 -11
  147. package/dist/chunk-H4Q5FTPZ.js.map +0 -1
  148. package/internal/src/set-state/copy-mutable-in-transaction.ts +0 -19
  149. package/realtime-client/src/sync-server-action.ts +0 -170
  150. package/realtime-client/src/sync-state.ts +0 -19
  151. package/realtime-react/src/use-pull-family-member.ts +0 -16
  152. package/realtime-react/src/use-sync-server-action.ts +0 -16
  153. package/realtime-server/src/realtime-action-synchronizer.ts +0 -152
@@ -0,0 +1,3 @@
1
+ export function arbitrary(random: () => number = Math.random): string {
2
+ return random().toString(36).slice(2)
3
+ }
@@ -1,12 +1,9 @@
1
- import type { RegularAtomToken } from "atom.io"
1
+ import type { AtomToken } from "atom.io"
2
2
 
3
3
  import type { Store } from ".."
4
- import { deleteSelector, newest } from ".."
4
+ import { deleteSelector, getUpdateToken, newest } from ".."
5
5
 
6
- export function deleteAtom(
7
- atomToken: RegularAtomToken<unknown>,
8
- store: Store,
9
- ): void {
6
+ export function deleteAtom(atomToken: AtomToken<unknown>, store: Store): void {
10
7
  const target = newest(store)
11
8
  const { key } = atomToken
12
9
  const atom = target.atoms.get(key)
@@ -35,5 +32,9 @@ export function deleteAtom(
35
32
  target.selectorAtoms.delete(key)
36
33
  target.atomsThatAreDefault.delete(key)
37
34
  target.timelineAtoms.delete(key)
35
+ if (atomToken.type === `mutable_atom`) {
36
+ const updateToken = getUpdateToken(atomToken)
37
+ deleteAtom(updateToken, store)
38
+ }
38
39
  store.logger.info(`🔥`, `atom`, `${key}`, `deleted`)
39
40
  }
@@ -1,7 +1,7 @@
1
1
  import type { StateUpdate } from "atom.io"
2
- import type { ReadableState } from "."
2
+ import { type ReadableState, isChildStore } from "."
3
3
  import { Future } from "./future"
4
- import { copyMutableIfWithinTransaction } from "./set-state/copy-mutable-in-transaction"
4
+ import { copyMutableIfNeeded } from "./set-state/copy-mutable-if-needed"
5
5
  import type { Store } from "./store"
6
6
  import type { Subject } from "./subject"
7
7
 
@@ -54,8 +54,10 @@ export const readCachedValue = <T>(
54
54
  target: Store,
55
55
  ): T => {
56
56
  let value = target.valueMap.get(token.key) as T
57
- if (token.type === `atom`) {
58
- value = copyMutableIfWithinTransaction(value, token, target)
57
+ if (token.type === `mutable_atom` && isChildStore(target)) {
58
+ const { parent } = target
59
+ const copiedValue = copyMutableIfNeeded(token, parent, target)
60
+ value = copiedValue
59
61
  }
60
62
  return value
61
63
  }
@@ -1,6 +1,8 @@
1
1
  import type { Json } from "atom.io/json"
2
2
 
3
3
  import type {
4
+ AtomFamilyToken,
5
+ AtomToken,
4
6
  MutableAtomFamilyToken,
5
7
  MutableAtomToken,
6
8
  ReadableFamilyToken,
@@ -9,6 +11,8 @@ import type {
9
11
  ReadonlySelectorToken,
10
12
  RegularAtomFamilyToken,
11
13
  RegularAtomToken,
14
+ SelectorFamilyToken,
15
+ SelectorToken,
12
16
  WritableFamilyToken,
13
17
  WritableSelectorFamilyToken,
14
18
  WritableSelectorToken,
@@ -35,6 +39,12 @@ export function findInStore<T, K extends Json.Serializable, Key extends K>(
35
39
  store: Store,
36
40
  ): RegularAtomToken<T>
37
41
 
42
+ export function findInStore<T, K extends Json.Serializable, Key extends K>(
43
+ token: AtomFamilyToken<T, K>,
44
+ key: Key,
45
+ store: Store,
46
+ ): AtomToken<T>
47
+
38
48
  export function findInStore<T, K extends Json.Serializable, Key extends K>(
39
49
  token: WritableSelectorFamilyToken<T, K>,
40
50
  key: Key,
@@ -47,6 +57,12 @@ export function findInStore<T, K extends Json.Serializable, Key extends K>(
47
57
  store: Store,
48
58
  ): ReadonlySelectorToken<T>
49
59
 
60
+ export function findInStore<T, K extends Json.Serializable, Key extends K>(
61
+ token: SelectorFamilyToken<T, K>,
62
+ key: Key,
63
+ store: Store,
64
+ ): SelectorToken<T>
65
+
50
66
  export function findInStore<T, K extends Json.Serializable, Key extends K>(
51
67
  token: WritableFamilyToken<T, K>,
52
68
  key: Key,
@@ -1,18 +1,15 @@
1
1
  import type { Store } from "./store"
2
2
 
3
3
  export type EnvironmentData = {
4
- runtime: `browser` | `node` | `unknown`
4
+ window: typeof window | undefined
5
+ global: typeof global | undefined
5
6
  store: Store
6
7
  }
7
8
 
8
9
  export function getEnvironmentData(store: Store): EnvironmentData {
9
10
  return {
10
- runtime:
11
- typeof window === `undefined`
12
- ? typeof global === `object`
13
- ? `node`
14
- : `unknown`
15
- : `browser`,
11
+ window: typeof window === `undefined` ? undefined : window,
12
+ global: typeof global === `undefined` ? undefined : global,
16
13
  store,
17
14
  }
18
15
  }
@@ -6,6 +6,7 @@ import type { Store } from "./store"
6
6
  import type { Subject } from "./subject"
7
7
 
8
8
  export * from "./atom"
9
+ export * from "./arbitrary"
9
10
  export * from "./caching"
10
11
  export * from "./lineage"
11
12
  export * from "./families"
@@ -26,14 +27,14 @@ export * from "./subscribe"
26
27
  export * from "./timeline"
27
28
  export * from "./transaction"
28
29
 
29
- export type BaseStateData = {
30
+ export type AtomIOState = {
30
31
  key: string
31
32
  family?: FamilyMetadata
32
33
  install: (store: Store) => void
33
34
  subject: Subject<{ newValue: any; oldValue: any }>
34
35
  }
35
36
 
36
- export type RegularAtom<T> = BaseStateData & {
37
+ export type RegularAtom<T> = AtomIOState & {
37
38
  type: `atom`
38
39
  default: T | (() => T)
39
40
  cleanup?: () => void
@@ -41,7 +42,7 @@ export type RegularAtom<T> = BaseStateData & {
41
42
  export type MutableAtom<
42
43
  T extends Transceiver<any>,
43
44
  J extends Json.Serializable,
44
- > = BaseStateData &
45
+ > = AtomIOState &
45
46
  JsonInterface<T, J> & {
46
47
  type: `mutable_atom`
47
48
  default: T | (() => T)
@@ -51,12 +52,12 @@ export type Atom<T> =
51
52
  | RegularAtom<T>
52
53
  | (T extends Transceiver<any> ? MutableAtom<T, any> : never)
53
54
 
54
- export type WritableSelector<T> = BaseStateData & {
55
+ export type WritableSelector<T> = AtomIOState & {
55
56
  type: `selector`
56
57
  get: () => T
57
58
  set: (newValue: T | ((oldValue: T) => T)) => void
58
59
  }
59
- export type ReadonlySelector<T> = BaseStateData & {
60
+ export type ReadonlySelector<T> = AtomIOState & {
60
61
  type: `readonly_selector`
61
62
  get: () => T
62
63
  }
@@ -1,4 +1,4 @@
1
- import type { KeyedStateUpdate } from "atom.io"
1
+ import type { KeyedStateUpdate, RegularAtomToken } from "atom.io"
2
2
 
3
3
  import { setIntoStore } from "../set-state"
4
4
  import type { Store } from "../store"
@@ -10,5 +10,9 @@ export function ingestAtomUpdate(
10
10
  ): void {
11
11
  const { key, newValue, oldValue } = atomUpdate
12
12
  const value = applying === `newValue` ? newValue : oldValue
13
- setIntoStore({ key, type: `atom` }, value, store)
13
+ const token: RegularAtomToken<unknown> = { key, type: `atom` }
14
+ if (atomUpdate.family) {
15
+ Object.assign(token, { family: atomUpdate.family })
16
+ }
17
+ setIntoStore(token, value, store)
14
18
  }
@@ -1,7 +1,6 @@
1
1
  import type { TransactionUpdate } from "atom.io"
2
2
 
3
3
  import type { Store } from "../store"
4
- import { isRootStore } from "../transaction/is-root-store"
5
4
  import { ingestAtomUpdate } from "./ingest-atom-update"
6
5
 
7
6
  export function ingestTransactionUpdate(
@@ -1,5 +1,4 @@
1
1
  import type {
2
- FamilyMetadata,
3
2
  ReadonlySelectorOptions,
4
3
  ReadonlySelectorToken,
5
4
  WritableSelectorOptions,
@@ -7,7 +6,6 @@ import type {
7
6
  } from "atom.io"
8
7
 
9
8
  import type { Store } from "../store"
10
- import type { Subject } from "../subject"
11
9
  import { createReadonlySelector } from "./create-readonly-selector"
12
10
  import { createWritableSelector } from "./create-writable-selector"
13
11
 
@@ -9,7 +9,12 @@ export function copyMutableIfNeeded<T extends Transceiver<any>>(
9
9
  ): T {
10
10
  const originValue = origin.valueMap.get(atom.key)
11
11
  const targetValue = target.valueMap.get(atom.key)
12
+
12
13
  if (originValue === targetValue) {
14
+ if (originValue === undefined) {
15
+ return typeof atom.default === `function` ? atom.default() : atom.default
16
+ }
17
+
13
18
  origin.logger.info(`📃`, `atom`, `${atom.key}`, `copying`)
14
19
  const jsonValue = atom.toJson(originValue)
15
20
  const copiedValue = atom.fromJson(jsonValue)
@@ -8,16 +8,30 @@ export const emitUpdate = <T>(
8
8
  update: StateUpdate<T>,
9
9
  store: Store,
10
10
  ): void => {
11
- store.logger.info(
12
- `📢`,
13
- state.type,
14
- state.key,
15
- `went (`,
16
- update.oldValue,
17
- `->`,
18
- update.newValue,
19
- `) subscribers:`,
20
- state.subject.subscribers,
21
- )
11
+ switch (state.type) {
12
+ case `mutable_atom`:
13
+ store.logger.info(
14
+ `📢`,
15
+ state.type,
16
+ state.key,
17
+ `is now (`,
18
+ update.newValue,
19
+ `) subscribers:`,
20
+ state.subject.subscribers,
21
+ )
22
+ break
23
+ default:
24
+ store.logger.info(
25
+ `📢`,
26
+ state.type,
27
+ state.key,
28
+ `went (`,
29
+ update.oldValue,
30
+ `->`,
31
+ update.newValue,
32
+ `) subscribers:`,
33
+ state.subject.subscribers,
34
+ )
35
+ }
22
36
  state.subject.next(update)
23
37
  }
@@ -5,9 +5,9 @@ import { readOrComputeValue } from "../get-state/read-or-compute-value"
5
5
  import type { Transceiver } from "../mutable"
6
6
  import { markDone } from "../operation"
7
7
  import type { Store } from "../store"
8
- import { isRootStore } from "../transaction/is-root-store"
8
+ import { isChildStore, isRootStore } from "../transaction/is-root-store"
9
9
  import { become } from "./become"
10
- import { copyMutableIfWithinTransaction } from "./copy-mutable-in-transaction"
10
+ import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
11
11
  import { emitUpdate } from "./emit-update"
12
12
  import { evictDownStream } from "./evict-downstream"
13
13
  import { stowUpdate } from "./stow-update"
@@ -18,7 +18,12 @@ export const setAtom = <T>(
18
18
  target: Store,
19
19
  ): void => {
20
20
  const oldValue = readOrComputeValue(atom, target)
21
- let newValue = copyMutableIfWithinTransaction(oldValue, atom, target)
21
+ let newValue = oldValue
22
+ if (atom.type === `mutable_atom` && isChildStore(target)) {
23
+ const { parent } = target
24
+ const copiedValue = copyMutableIfNeeded(atom, parent, target)
25
+ newValue = copiedValue
26
+ }
22
27
  newValue = become(next)(newValue)
23
28
  target.logger.info(`📝`, `atom`, atom.key, `set to`, newValue)
24
29
  newValue = cacheValue(atom.key, newValue, atom.subject, target)
@@ -36,22 +41,14 @@ export const setAtom = <T>(
36
41
  } else if (atom.key.startsWith(`*`)) {
37
42
  const mutableKey = atom.key.slice(1)
38
43
  const mutableAtom = target.atoms.get(mutableKey) as Atom<any>
39
- let mutable: Transceiver<any> = target.valueMap.get(mutableKey)
40
- mutable = copyMutableIfWithinTransaction(mutable, mutableAtom, target)
41
- const output = mutable.do(update.newValue)
42
- if (output !== null) {
43
- target.logger.warn(
44
- `❌`,
45
- `mutable_atom`,
46
- mutableKey,
47
- `could not be updated.`,
48
- typeof output === `number`
49
- ? `Expected update number ${
50
- mutable.cacheUpdateNumber + 1
51
- }, but got ${output}`
52
- : output,
53
- )
44
+ let transceiver: Transceiver<any> = target.valueMap.get(mutableKey)
45
+ if (mutableAtom.type === `mutable_atom` && isChildStore(target)) {
46
+ const { parent } = target
47
+ const copiedValue = copyMutableIfNeeded(mutableAtom, parent, target)
48
+ transceiver = copiedValue
54
49
  }
50
+ const accepted = transceiver.do(update.newValue) === null
51
+ if (accepted) evictDownStream(mutableAtom, target)
55
52
  }
56
53
  }
57
54
  }
@@ -32,6 +32,7 @@ import type {
32
32
  TransactionEpoch,
33
33
  TransactionProgress,
34
34
  } from "../transaction"
35
+ import { isRootStore } from "../transaction/is-root-store"
35
36
 
36
37
  export class Store implements Lineage {
37
38
  public parent: Store | null = null
@@ -93,7 +94,11 @@ export class Store implements Lineage {
93
94
  }
94
95
  public operation: OperationProgress = { open: false }
95
96
  public transactionMeta: TransactionEpoch | TransactionProgress<ƒn> = {
96
- epoch: -1,
97
+ epoch: new Map<string, number>(),
98
+ actionContinuities: new Junction({
99
+ between: [`continuity`, `action`],
100
+ cardinality: `1:n`,
101
+ }),
97
102
  }
98
103
 
99
104
  public config: {
@@ -121,7 +126,14 @@ export class Store implements Lineage {
121
126
  if (store !== null) {
122
127
  this.valueMap = new Map(store?.valueMap)
123
128
  this.operation = { ...store?.operation }
124
- this.transactionMeta = { ...store?.transactionMeta }
129
+ if (isRootStore(store)) {
130
+ this.transactionMeta = {
131
+ epoch: new Map(store?.transactionMeta.epoch),
132
+ actionContinuities: new Junction(
133
+ store?.transactionMeta.actionContinuities.toJSON(),
134
+ ),
135
+ }
136
+ }
125
137
 
126
138
  this.config = {
127
139
  ...store?.config,
@@ -1,18 +1,31 @@
1
1
  import type {
2
+ AtomFamily,
3
+ AtomFamilyToken,
2
4
  AtomToken,
5
+ MutableAtomFamily,
6
+ MutableAtomFamilyToken,
3
7
  MutableAtomToken,
4
8
  ReadableToken,
9
+ ReadonlySelectorFamily,
10
+ ReadonlySelectorFamilyToken,
5
11
  ReadonlySelectorToken,
12
+ RegularAtomFamily,
13
+ RegularAtomFamilyToken,
6
14
  RegularAtomToken,
15
+ SelectorFamily,
16
+ SelectorFamilyToken,
7
17
  SelectorToken,
8
18
  TimelineManageable,
9
19
  TimelineToken,
10
20
  TransactionToken,
21
+ WritableSelectorFamily,
22
+ WritableSelectorFamilyToken,
11
23
  WritableSelectorToken,
12
24
  WritableToken,
13
25
  ƒn,
14
26
  } from "atom.io"
15
27
 
28
+ import type { Json } from "atom.io/json"
16
29
  import type {
17
30
  Atom,
18
31
  MutableAtom,
@@ -28,7 +41,24 @@ import type { Timeline } from "../timeline"
28
41
  import type { Transaction } from "../transaction"
29
42
  import type { Store } from "./store"
30
43
 
31
- export type Withdrawable = ReadableState<any> | Timeline<any> | Transaction<any>
44
+ export type Withdrawable =
45
+ | Atom<any>
46
+ | AtomFamily<any, any>
47
+ | MutableAtom<any, any>
48
+ | MutableAtomFamily<any, any, any>
49
+ | ReadableState<any>
50
+ | ReadableState<any>
51
+ | ReadonlySelector<any>
52
+ | ReadonlySelectorFamily<any, any>
53
+ | RegularAtom<any>
54
+ | RegularAtomFamily<any, any>
55
+ | Selector<any>
56
+ | SelectorFamily<any, any>
57
+ | Timeline<any>
58
+ | Transaction<any>
59
+ | WritableSelector<any>
60
+ | WritableSelectorFamily<any, any>
61
+ | WritableState<any>
32
62
 
33
63
  export function withdraw<T>(
34
64
  token: RegularAtomToken<T>,
@@ -62,6 +92,36 @@ export function withdraw<T>(
62
92
  token: ReadableToken<T>,
63
93
  store: Store,
64
94
  ): ReadableState<T> | undefined
95
+
96
+ export function withdraw<T, K extends Json.Serializable>(
97
+ token: RegularAtomFamilyToken<T, K>,
98
+ store: Store,
99
+ ): RegularAtomFamily<T, K> | undefined
100
+ export function withdraw<
101
+ T extends Transceiver<any>,
102
+ J extends Json.Serializable,
103
+ K extends Json.Serializable,
104
+ >(
105
+ token: MutableAtomFamilyToken<T, J, K>,
106
+ store: Store,
107
+ ): MutableAtomFamily<T, J, K> | undefined
108
+ export function withdraw<T, K extends Json.Serializable>(
109
+ token: AtomFamilyToken<T>,
110
+ store: Store,
111
+ ): AtomFamily<T, any> | undefined
112
+ export function withdraw<T, K extends Json.Serializable>(
113
+ token: ReadonlySelectorFamilyToken<T, K>,
114
+ store: Store,
115
+ ): ReadonlySelectorFamily<T, any> | undefined
116
+ export function withdraw<T, K extends Json.Serializable>(
117
+ token: WritableSelectorFamilyToken<T, K>,
118
+ store: Store,
119
+ ): WritableSelectorFamily<T, any> | undefined
120
+ export function withdraw<T, K extends Json.Serializable>(
121
+ token: SelectorFamilyToken<T, K>,
122
+ store: Store,
123
+ ): SelectorFamily<T, any> | undefined
124
+
65
125
  export function withdraw<T>(
66
126
  token: TransactionToken<T>,
67
127
  store: Store,
@@ -72,11 +132,15 @@ export function withdraw<T>(
72
132
  ): Timeline<T extends TimelineManageable ? T : never> | undefined
73
133
  export function withdraw<T>(
74
134
  token:
135
+ | RegularAtomFamilyToken<T, any>
75
136
  | RegularAtomToken<T>
137
+ | SelectorFamilyToken<T, any>
76
138
  | SelectorToken<T>
77
139
  | TimelineToken<T>
78
140
  | TransactionToken<T>
79
- | (T extends Transceiver<any> ? MutableAtomToken<T, any> : never),
141
+ | (T extends Transceiver<any>
142
+ ? MutableAtomFamilyToken<T, any, any> | MutableAtomToken<T, any>
143
+ : never),
80
144
  store: Store,
81
145
  ): Withdrawable | undefined {
82
146
  let withdrawn: Withdrawable | undefined
@@ -93,6 +157,12 @@ export function withdraw<T>(
93
157
  case `readonly_selector`:
94
158
  withdrawn = target.readonlySelectors.get(token.key)
95
159
  break
160
+ case `atom_family`:
161
+ case `mutable_atom_family`:
162
+ case `selector_family`:
163
+ case `readonly_selector_family`:
164
+ withdrawn = target.families.get(token.key)
165
+ break
96
166
  case `timeline`:
97
167
  withdrawn = target.timelines.get(token.key)
98
168
  break
@@ -1,6 +1,6 @@
1
1
  import type { TimelineManageable, TimelineToken, TimelineUpdate } from "atom.io"
2
- import type { Store } from "atom.io/internal"
3
- import { withdraw } from "atom.io/internal"
2
+ import type { Store } from ".."
3
+ import { withdraw } from ".."
4
4
 
5
5
  export const subscribeToTimeline = <ManagedAtom extends TimelineManageable>(
6
6
  token: TimelineToken<ManagedAtom>,
@@ -1,6 +1,6 @@
1
1
  import type { TransactionToken, TransactionUpdateHandler, ƒn } from "atom.io"
2
- import type { Store } from "atom.io/internal"
3
- import { withdraw } from "atom.io/internal"
2
+ import type { Store } from ".."
3
+ import { withdraw } from ".."
4
4
 
5
5
  export const subscribeToTransaction = <ƒ extends ƒn>(
6
6
  token: TransactionToken<ƒ>,
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  AtomFamily,
3
+ AtomFamilyToken,
3
4
  FamilyMetadata,
4
5
  StateUpdate,
5
6
  TimelineManageable,
@@ -86,7 +87,17 @@ export function createTimeline<ManagedAtom extends TimelineManageable>(
86
87
  tokenOrFamily.type === `atom_family` ||
87
88
  tokenOrFamily.type === `mutable_atom_family`
88
89
  ) {
89
- const family: AtomFamily<any> = tokenOrFamily
90
+ const familyToken: AtomFamilyToken<any> = tokenOrFamily
91
+ const family = withdraw(familyToken, store)
92
+ if (family === undefined) {
93
+ store.logger.error(
94
+ `❌`,
95
+ `timeline`,
96
+ options.key,
97
+ `Failed to add family "${familyToken.key}" because it does not exist in the store`,
98
+ )
99
+ continue
100
+ }
90
101
  const familyKey = family.key
91
102
  target.timelineAtoms.set({ atomKey: familyKey, timelineKey })
92
103
  family.subject.subscribe(`timeline:${options.key}`, (token) => {
@@ -0,0 +1,19 @@
1
+ import type { TransactionToken, ƒn } from "atom.io"
2
+
3
+ import { NotFoundError } from "../not-found-error"
4
+ import type { Store } from "../store"
5
+ import { withdraw } from "../store"
6
+
7
+ export function actUponStore<ƒ extends ƒn>(
8
+ token: TransactionToken<ƒ>,
9
+ id: string,
10
+ store: Store,
11
+ ): (...parameters: Parameters<ƒ>) => ReturnType<ƒ> {
12
+ return (...parameters: Parameters<ƒ>): ReturnType<ƒ> => {
13
+ const tx = withdraw(token, store)
14
+ if (tx) {
15
+ return tx.run(parameters, id)
16
+ }
17
+ throw new NotFoundError(token, store)
18
+ }
19
+ }
@@ -5,6 +5,7 @@ import { newest } from "../lineage"
5
5
  import { withdraw } from "../store"
6
6
  import type { Store } from "../store"
7
7
  import { isChildStore, isRootStore } from "./is-root-store"
8
+ import { setEpochNumberOfAction } from "./set-epoch-number"
8
9
 
9
10
  export const applyTransaction = <ƒ extends ƒn>(
10
11
  output: ReturnType<ƒ>,
@@ -59,7 +60,11 @@ export const applyTransaction = <ƒ extends ƒn>(
59
60
  }
60
61
  ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent)
61
62
  if (isRootStore(parent)) {
62
- parent.transactionMeta.epoch = child.transactionMeta.update.epoch
63
+ setEpochNumberOfAction(
64
+ child.transactionMeta.update.key,
65
+ child.transactionMeta.update.epoch,
66
+ parent,
67
+ )
63
68
  const myTransaction = withdraw<ƒ>(
64
69
  { key: child.transactionMeta.update.key, type: `transaction` },
65
70
  store,
@@ -0,0 +1,18 @@
1
+ import type { Store } from "../store"
2
+ import { isRootStore } from "./is-root-store"
3
+
4
+ export function assignTransactionToContinuity(
5
+ continuityKey: string,
6
+ transactionKey: string,
7
+ store: Store,
8
+ ): void {
9
+ const isRoot = isRootStore(store)
10
+ if (!isRoot) {
11
+ return
12
+ }
13
+ const { epoch, actionContinuities } = store.transactionMeta
14
+ actionContinuities.set(continuityKey, transactionKey)
15
+ if (!epoch.has(continuityKey)) {
16
+ epoch.set(continuityKey, -1)
17
+ }
18
+ }
@@ -1,9 +1,10 @@
1
- import { runTransaction } from "atom.io"
2
1
  import type { findState, ƒn } from "atom.io"
3
2
 
4
3
  import { Junction } from "~/packages/rel8/junction/src"
5
4
 
6
5
  import type { TransactionProgress } from "."
6
+ import { actUponStore, getEpochNumberOfAction } from "."
7
+ import { arbitrary } from "../arbitrary"
7
8
  import { findInStore } from "../families"
8
9
  import { getEnvironmentData } from "../get-environment-data"
9
10
  import { getFromStore } from "../get-state"
@@ -12,13 +13,12 @@ import { newest } from "../lineage"
12
13
  import { setIntoStore } from "../set-state"
13
14
  import type { Store } from "../store"
14
15
  import type { ChildStore, RootStore } from "./is-root-store"
15
- import { isRootStore } from "./is-root-store"
16
16
 
17
17
  export const buildTransaction = (
18
18
  key: string,
19
19
  params: any[],
20
20
  store: Store,
21
- id?: string,
21
+ id: string,
22
22
  ): ChildStore => {
23
23
  const parent = newest(store) as ChildStore | RootStore
24
24
  const childBase: Omit<ChildStore, `transactionMeta`> = {
@@ -44,12 +44,13 @@ export const buildTransaction = (
44
44
  selectors: new LazyMap(parent.selectors),
45
45
  valueMap: new LazyMap(parent.valueMap),
46
46
  }
47
+ const epoch = getEpochNumberOfAction(key, store)
47
48
  const transactionMeta: TransactionProgress<ƒn> = {
48
49
  phase: `building` as const,
49
50
  update: {
50
51
  key,
51
- id: id ?? Math.random().toString(36).slice(2),
52
- epoch: isRootStore(parent) ? parent.transactionMeta.epoch + 1 : NaN,
52
+ id,
53
+ epoch: epoch === undefined ? NaN : epoch + 1,
53
54
  updates: [],
54
55
  params,
55
56
  output: undefined,
@@ -57,7 +58,7 @@ export const buildTransaction = (
57
58
  transactors: {
58
59
  get: (token) => getFromStore(token, child),
59
60
  set: (token, value) => setIntoStore(token, value, child),
60
- run: (token, id) => runTransaction(token, id, child),
61
+ run: (token, id = arbitrary()) => actUponStore(token, id, child),
61
62
  find: ((token, key) => findInStore(token, key, child)) as typeof findState,
62
63
  env: () => getEnvironmentData(child),
63
64
  },
@@ -28,7 +28,7 @@ export function createTransaction<ƒ extends ƒn>(
28
28
  const newTransaction: Transaction<ƒ> = {
29
29
  key: options.key,
30
30
  type: `transaction`,
31
- run: (params: Parameters<ƒ>, id?: string) => {
31
+ run: (params: Parameters<ƒ>, id: string) => {
32
32
  const childStore = buildTransaction(options.key, params, store, id)
33
33
  try {
34
34
  const target = newest(store)