atom.io 0.6.2 → 0.6.4

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 (117) hide show
  1. package/dist/index.d.mts +27 -15
  2. package/dist/index.d.ts +27 -15
  3. package/dist/index.js +44 -24
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +44 -24
  6. package/dist/index.mjs.map +1 -1
  7. package/json/dist/index.d.mts +18 -0
  8. package/json/dist/index.d.ts +18 -0
  9. package/json/dist/index.js +51 -0
  10. package/json/dist/index.js.map +1 -0
  11. package/json/dist/index.mjs +15 -0
  12. package/json/dist/index.mjs.map +1 -0
  13. package/json/package.json +13 -13
  14. package/package.json +31 -12
  15. package/react/dist/index.d.mts +24 -0
  16. package/react/dist/index.d.ts +24 -0
  17. package/react/dist/index.js +87 -0
  18. package/react/dist/index.js.map +1 -0
  19. package/react/dist/index.mjs +45 -0
  20. package/react/dist/index.mjs.map +1 -0
  21. package/react/package.json +13 -13
  22. package/react-devtools/dist/index.css +26 -0
  23. package/react-devtools/dist/index.css.map +1 -0
  24. package/react-devtools/dist/index.d.mts +15 -0
  25. package/react-devtools/dist/index.d.ts +15 -0
  26. package/react-devtools/dist/index.js +2108 -0
  27. package/react-devtools/dist/index.js.map +1 -0
  28. package/react-devtools/dist/index.mjs +2080 -0
  29. package/react-devtools/dist/index.mjs.map +1 -0
  30. package/react-devtools/package.json +13 -13
  31. package/realtime/dist/index.d.mts +27 -0
  32. package/realtime/dist/index.d.ts +27 -0
  33. package/realtime/dist/index.js +191 -0
  34. package/realtime/dist/index.js.map +1 -0
  35. package/realtime/dist/index.mjs +152 -0
  36. package/realtime/dist/index.mjs.map +1 -0
  37. package/realtime/package.json +13 -13
  38. package/realtime-react/dist/index.d.mts +45 -0
  39. package/realtime-react/dist/index.d.ts +45 -0
  40. package/realtime-react/dist/index.js +217 -0
  41. package/realtime-react/dist/index.js.map +1 -0
  42. package/realtime-react/dist/index.mjs +172 -0
  43. package/realtime-react/dist/index.mjs.map +1 -0
  44. package/realtime-react/package.json +13 -13
  45. package/realtime-testing/dist/index.d.mts +49 -0
  46. package/realtime-testing/dist/index.d.ts +49 -0
  47. package/realtime-testing/dist/index.js +165 -0
  48. package/realtime-testing/dist/index.js.map +1 -0
  49. package/realtime-testing/dist/index.mjs +129 -0
  50. package/realtime-testing/dist/index.mjs.map +1 -0
  51. package/realtime-testing/package.json +15 -0
  52. package/src/atom.ts +16 -17
  53. package/src/index.ts +59 -59
  54. package/src/internal/atom-internal.ts +37 -37
  55. package/src/internal/families-internal.ts +115 -116
  56. package/src/internal/get.ts +83 -83
  57. package/src/internal/index.ts +1 -0
  58. package/src/internal/is-default.ts +17 -17
  59. package/src/internal/meta/attach-meta.ts +7 -7
  60. package/src/internal/meta/meta-state.ts +115 -115
  61. package/src/internal/operation.ts +93 -93
  62. package/src/internal/selector/create-read-write-selector.ts +47 -47
  63. package/src/internal/selector/create-readonly-selector.ts +38 -38
  64. package/src/internal/selector/lookup-selector-sources.ts +9 -9
  65. package/src/internal/selector/register-selector.ts +44 -44
  66. package/src/internal/selector/trace-selector-atoms.ts +30 -30
  67. package/src/internal/selector/update-selector-atoms.ts +25 -25
  68. package/src/internal/selector-internal.ts +38 -39
  69. package/src/internal/set.ts +78 -78
  70. package/src/internal/store.ts +119 -119
  71. package/src/internal/subject.ts +24 -0
  72. package/src/internal/subscribe-internal.ts +62 -62
  73. package/src/internal/time-travel-internal.ts +76 -76
  74. package/src/internal/timeline/add-atom-to-timeline.ts +158 -153
  75. package/src/internal/timeline-internal.ts +81 -82
  76. package/src/internal/transaction/abort-transaction.ts +8 -8
  77. package/src/internal/transaction/apply-transaction.ts +41 -41
  78. package/src/internal/transaction/build-transaction.ts +28 -28
  79. package/src/internal/transaction/index.ts +7 -7
  80. package/src/internal/transaction/redo-transaction.ts +13 -13
  81. package/src/internal/transaction/undo-transaction.ts +13 -13
  82. package/src/internal/transaction-internal.ts +49 -49
  83. package/src/json/select-json.ts +12 -12
  84. package/src/logger.ts +30 -30
  85. package/src/react/store-context.tsx +5 -6
  86. package/src/react/store-hooks.ts +19 -20
  87. package/src/react-devtools/AtomIODevtools.tsx +85 -85
  88. package/src/react-devtools/StateEditor.tsx +54 -55
  89. package/src/react-devtools/TokenList.tsx +49 -45
  90. package/src/react-explorer/AtomIOExplorer.tsx +198 -187
  91. package/src/react-explorer/explorer-effects.ts +11 -11
  92. package/src/react-explorer/explorer-states.ts +186 -193
  93. package/src/react-explorer/index.ts +11 -11
  94. package/src/react-explorer/space-states.ts +48 -50
  95. package/src/react-explorer/view-states.ts +25 -25
  96. package/src/realtime/hook-composition/expose-family.ts +81 -81
  97. package/src/realtime/hook-composition/expose-single.ts +26 -26
  98. package/src/realtime/hook-composition/expose-timeline.ts +60 -0
  99. package/src/realtime/hook-composition/index.ts +2 -2
  100. package/src/realtime/hook-composition/receive-state.ts +18 -18
  101. package/src/realtime/hook-composition/receive-transaction.ts +8 -8
  102. package/src/realtime-react/realtime-context.tsx +18 -19
  103. package/src/realtime-react/realtime-hooks.ts +17 -17
  104. package/src/realtime-react/realtime-state.ts +4 -4
  105. package/src/realtime-react/use-pull-family-member.ts +16 -17
  106. package/src/realtime-react/use-pull-family.ts +14 -15
  107. package/src/realtime-react/use-pull.ts +13 -14
  108. package/src/realtime-react/use-push.ts +16 -17
  109. package/src/realtime-react/use-server-action.ts +22 -23
  110. package/src/realtime-testing/index.ts +1 -0
  111. package/src/realtime-testing/setup-realtime-test.tsx +159 -0
  112. package/src/selector.ts +26 -27
  113. package/src/silo.ts +38 -38
  114. package/src/subscribe.ts +68 -68
  115. package/src/timeline.ts +13 -13
  116. package/src/transaction.ts +28 -28
  117. package/src/web-effects/storage.ts +17 -17
@@ -4,30 +4,30 @@ import { target } from ".."
4
4
  import type { ReadonlySelectorToken, StateToken } from "../.."
5
5
 
6
6
  export const updateSelectorAtoms = (
7
- selectorKey: string,
8
- dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
9
- store: Store
7
+ selectorKey: string,
8
+ dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
9
+ store: Store,
10
10
  ): void => {
11
- const core = target(store)
12
- if (dependency.type === `atom`) {
13
- core.selectorAtoms = core.selectorAtoms.set({
14
- selectorKey,
15
- atomKey: dependency.key,
16
- })
17
- store.config.logger?.info(
18
- ` || adding root for "${selectorKey}": ${dependency.key}`
19
- )
20
- return
21
- }
22
- const roots = traceSelectorAtoms(selectorKey, dependency, store)
23
- store.config.logger?.info(
24
- ` || adding roots for "${selectorKey}":`,
25
- roots.map((r) => r.key)
26
- )
27
- for (const root of roots) {
28
- core.selectorAtoms = core.selectorAtoms.set({
29
- selectorKey,
30
- atomKey: root.key,
31
- })
32
- }
11
+ const core = target(store)
12
+ if (dependency.type === `atom`) {
13
+ core.selectorAtoms = core.selectorAtoms.set({
14
+ selectorKey,
15
+ atomKey: dependency.key,
16
+ })
17
+ store.config.logger?.info(
18
+ ` || adding root for "${selectorKey}": ${dependency.key}`,
19
+ )
20
+ return
21
+ }
22
+ const roots = traceSelectorAtoms(selectorKey, dependency, store)
23
+ store.config.logger?.info(
24
+ ` || adding roots for "${selectorKey}":`,
25
+ roots.map((r) => r.key),
26
+ )
27
+ for (const root of roots) {
28
+ core.selectorAtoms = core.selectorAtoms.set({
29
+ selectorKey,
30
+ atomKey: root.key,
31
+ })
32
+ }
33
33
  }
@@ -1,61 +1,60 @@
1
1
  import HAMT from "hamt_plus"
2
- import type * as Rx from "rxjs"
3
2
 
4
- import type { Store } from "."
5
3
  import { target, IMPLICIT } from "."
4
+ import type { Store, Subject } from "."
6
5
  import { createReadWriteSelector } from "./selector/create-read-write-selector"
7
6
  import { createReadonlySelector } from "./selector/create-readonly-selector"
8
7
  import type {
9
- FamilyMetadata,
10
- ReadonlySelectorOptions,
11
- ReadonlySelectorToken,
12
- SelectorOptions,
13
- SelectorToken,
8
+ FamilyMetadata,
9
+ ReadonlySelectorOptions,
10
+ ReadonlySelectorToken,
11
+ SelectorOptions,
12
+ SelectorToken,
14
13
  } from ".."
15
14
 
16
15
  export type Selector<T> = {
17
- key: string
18
- type: `selector`
19
- family?: FamilyMetadata
20
- install: (store: Store) => void
21
- subject: Rx.Subject<{ newValue: T; oldValue: T }>
22
- get: () => T
23
- set: (newValue: T | ((oldValue: T) => T)) => void
16
+ key: string
17
+ type: `selector`
18
+ family?: FamilyMetadata
19
+ install: (store: Store) => void
20
+ subject: Subject<{ newValue: T; oldValue: T }>
21
+ get: () => T
22
+ set: (newValue: T | ((oldValue: T) => T)) => void
24
23
  }
25
24
  export type ReadonlySelector<T> = {
26
- key: string
27
- type: `readonly_selector`
28
- family?: FamilyMetadata
29
- install: (store: Store) => void
30
- subject: Rx.Subject<{ newValue: T; oldValue: T }>
31
- get: () => T
25
+ key: string
26
+ type: `readonly_selector`
27
+ family?: FamilyMetadata
28
+ install: (store: Store) => void
29
+ subject: Subject<{ newValue: T; oldValue: T }>
30
+ get: () => T
32
31
  }
33
32
 
34
33
  export function selector__INTERNAL<T>(
35
- options: SelectorOptions<T>,
36
- family?: FamilyMetadata,
37
- store?: Store
34
+ options: SelectorOptions<T>,
35
+ family?: FamilyMetadata,
36
+ store?: Store,
38
37
  ): SelectorToken<T>
39
38
  export function selector__INTERNAL<T>(
40
- options: ReadonlySelectorOptions<T>,
41
- family?: FamilyMetadata,
42
- store?: Store
39
+ options: ReadonlySelectorOptions<T>,
40
+ family?: FamilyMetadata,
41
+ store?: Store,
43
42
  ): ReadonlySelectorToken<T>
44
43
  export function selector__INTERNAL<T>(
45
- options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
46
- family?: FamilyMetadata,
47
- store: Store = IMPLICIT.STORE
44
+ options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
45
+ family?: FamilyMetadata,
46
+ store: Store = IMPLICIT.STORE,
48
47
  ): ReadonlySelectorToken<T> | SelectorToken<T> {
49
- const core = target(store)
48
+ const core = target(store)
50
49
 
51
- if (HAMT.has(options.key, core.selectors)) {
52
- store.config.logger?.error(
53
- `Key "${options.key}" already exists in the store.`
54
- )
55
- }
50
+ if (HAMT.has(options.key, core.selectors)) {
51
+ store.config.logger?.error(
52
+ `Key "${options.key}" already exists in the store.`,
53
+ )
54
+ }
56
55
 
57
- if (!(`set` in options)) {
58
- return createReadonlySelector(options, family, store, core)
59
- }
60
- return createReadWriteSelector(options, family, store, core)
56
+ if (!(`set` in options)) {
57
+ return createReadonlySelector(options, family, store, core)
58
+ }
59
+ return createReadWriteSelector(options, family, store, core)
61
60
  }
@@ -4,99 +4,99 @@ import { become } from "~/packages/anvl/src/function"
4
4
 
5
5
  import type { Atom, Selector, Store } from "."
6
6
  import {
7
- IMPLICIT,
8
- cacheValue,
9
- emitUpdate,
10
- evictCachedValue,
11
- getState__INTERNAL,
12
- isAtomDefault,
13
- isDone,
14
- markAtomAsNotDefault,
15
- markDone,
16
- stowUpdate,
17
- target,
7
+ IMPLICIT,
8
+ cacheValue,
9
+ emitUpdate,
10
+ evictCachedValue,
11
+ getState__INTERNAL,
12
+ isAtomDefault,
13
+ isDone,
14
+ markAtomAsNotDefault,
15
+ markDone,
16
+ stowUpdate,
17
+ target,
18
18
  } from "."
19
19
 
20
20
  export const evictDownStream = <T>(
21
- state: Atom<T>,
22
- store: Store = IMPLICIT.STORE
21
+ state: Atom<T>,
22
+ store: Store = IMPLICIT.STORE,
23
23
  ): void => {
24
- const core = target(store)
25
- const downstream = core.selectorAtoms.getRelations(state.key)
26
- const downstreamKeys = downstream.map(({ id }) => id)
27
- store.config.logger?.info(
28
- ` || ${downstreamKeys.length} downstream:`,
29
- downstreamKeys
30
- )
31
- if (core.operation.open) {
32
- store.config.logger?.info(` ||`, [...core.operation.done], `already done`)
33
- }
34
- downstream.forEach(({ id: stateKey }) => {
35
- if (isDone(stateKey, store)) {
36
- store.config.logger?.info(` || ${stateKey} already done`)
37
- return
38
- }
39
- const state =
40
- HAMT.get(stateKey, core.selectors) ??
41
- HAMT.get(stateKey, core.readonlySelectors)
42
- if (!state) {
43
- store.config.logger?.info(
44
- ` || ${stateKey} is an atom, and can't be downstream`
45
- )
46
- return
47
- }
48
- evictCachedValue(stateKey, store)
49
- store.config.logger?.info(` xx evicted "${stateKey}"`)
24
+ const core = target(store)
25
+ const downstream = core.selectorAtoms.getRelations(state.key)
26
+ const downstreamKeys = downstream.map(({ id }) => id)
27
+ store.config.logger?.info(
28
+ ` || ${downstreamKeys.length} downstream:`,
29
+ downstreamKeys,
30
+ )
31
+ if (core.operation.open) {
32
+ store.config.logger?.info(` ||`, [...core.operation.done], `already done`)
33
+ }
34
+ downstream.forEach(({ id: stateKey }) => {
35
+ if (isDone(stateKey, store)) {
36
+ store.config.logger?.info(` || ${stateKey} already done`)
37
+ return
38
+ }
39
+ const state =
40
+ HAMT.get(stateKey, core.selectors) ??
41
+ HAMT.get(stateKey, core.readonlySelectors)
42
+ if (!state) {
43
+ store.config.logger?.info(
44
+ ` || ${stateKey} is an atom, and can't be downstream`,
45
+ )
46
+ return
47
+ }
48
+ evictCachedValue(stateKey, store)
49
+ store.config.logger?.info(` xx evicted "${stateKey}"`)
50
50
 
51
- markDone(stateKey, store)
52
- })
51
+ markDone(stateKey, store)
52
+ })
53
53
  }
54
54
 
55
55
  export const setAtomState = <T>(
56
- atom: Atom<T>,
57
- next: T | ((oldValue: T) => T),
58
- store: Store = IMPLICIT.STORE
56
+ atom: Atom<T>,
57
+ next: T | ((oldValue: T) => T),
58
+ store: Store = IMPLICIT.STORE,
59
59
  ): void => {
60
- const oldValue = getState__INTERNAL(atom, store)
61
- const newValue = become(next)(oldValue)
62
- store.config.logger?.info(`<< setting atom "${atom.key}" to`, newValue)
63
- cacheValue(atom.key, newValue, store)
64
- if (isAtomDefault(atom.key, store)) {
65
- markAtomAsNotDefault(atom.key, store)
66
- }
67
- markDone(atom.key, store)
68
- store.config.logger?.info(
69
- ` || evicting caches downstream from "${atom.key}"`
70
- )
71
- evictDownStream(atom, store)
72
- const update = { oldValue, newValue }
73
- if (store.transactionStatus.phase !== `building`) {
74
- emitUpdate(atom, update, store)
75
- } else {
76
- stowUpdate(atom, update, store)
77
- }
60
+ const oldValue = getState__INTERNAL(atom, store)
61
+ const newValue = become(next)(oldValue)
62
+ store.config.logger?.info(`<< setting atom "${atom.key}" to`, newValue)
63
+ cacheValue(atom.key, newValue, store)
64
+ if (isAtomDefault(atom.key, store)) {
65
+ markAtomAsNotDefault(atom.key, store)
66
+ }
67
+ markDone(atom.key, store)
68
+ store.config.logger?.info(
69
+ ` || evicting caches downstream from "${atom.key}"`,
70
+ )
71
+ evictDownStream(atom, store)
72
+ const update = { oldValue, newValue }
73
+ if (store.transactionStatus.phase !== `building`) {
74
+ emitUpdate(atom, update, store)
75
+ } else {
76
+ stowUpdate(atom, update, store)
77
+ }
78
78
  }
79
79
  export const setSelectorState = <T>(
80
- selector: Selector<T>,
81
- next: T | ((oldValue: T) => T),
82
- store: Store = IMPLICIT.STORE
80
+ selector: Selector<T>,
81
+ next: T | ((oldValue: T) => T),
82
+ store: Store = IMPLICIT.STORE,
83
83
  ): void => {
84
- const oldValue = getState__INTERNAL(selector, store)
85
- const newValue = become(next)(oldValue)
84
+ const oldValue = getState__INTERNAL(selector, store)
85
+ const newValue = become(next)(oldValue)
86
86
 
87
- store.config.logger?.info(`<< setting selector "${selector.key}" to`, newValue)
88
- store.config.logger?.info(` || propagating change made to "${selector.key}"`)
87
+ store.config.logger?.info(`<< setting selector "${selector.key}" to`, newValue)
88
+ store.config.logger?.info(` || propagating change made to "${selector.key}"`)
89
89
 
90
- selector.set(newValue)
90
+ selector.set(newValue)
91
91
  }
92
92
  export const setState__INTERNAL = <T>(
93
- state: Atom<T> | Selector<T>,
94
- value: T | ((oldValue: T) => T),
95
- store: Store = IMPLICIT.STORE
93
+ state: Atom<T> | Selector<T>,
94
+ value: T | ((oldValue: T) => T),
95
+ store: Store = IMPLICIT.STORE,
96
96
  ): void => {
97
- if (`set` in state) {
98
- setSelectorState(state, value, store)
99
- } else {
100
- setAtomState(state, value, store)
101
- }
97
+ if (`set` in state) {
98
+ setSelectorState(state, value, store)
99
+ } else {
100
+ setAtomState(state, value, store)
101
+ }
102
102
  }
@@ -1,153 +1,153 @@
1
1
  import type { Hamt } from "hamt_plus"
2
2
  import HAMT from "hamt_plus"
3
- import * as Rx from "rxjs"
4
3
 
5
4
  import type { ƒn } from "~/packages/anvl/src/function"
6
5
  import { doNothing } from "~/packages/anvl/src/function"
7
6
  import { Join } from "~/packages/anvl/src/join"
8
7
 
8
+ import { Subject } from "."
9
9
  import type {
10
- Atom,
11
- OperationProgress,
12
- ReadonlySelector,
13
- Selector,
14
- TransactionStatus,
15
- Timeline,
16
- Transaction,
10
+ Atom,
11
+ OperationProgress,
12
+ ReadonlySelector,
13
+ Selector,
14
+ TransactionStatus,
15
+ Timeline,
16
+ Transaction,
17
17
  } from "."
18
18
  import type {
19
- AtomToken,
20
- Logger,
21
- ReadonlySelectorToken,
22
- SelectorToken,
23
- TimelineToken,
24
- TransactionToken,
19
+ AtomToken,
20
+ Logger,
21
+ ReadonlySelectorToken,
22
+ SelectorToken,
23
+ TimelineToken,
24
+ TransactionToken,
25
25
  } from ".."
26
26
 
27
27
  export type StoreCore = Pick<
28
- Store,
29
- | `atoms`
30
- | `atomsThatAreDefault`
31
- | `operation`
32
- | `readonlySelectors`
33
- | `selectorAtoms`
34
- | `selectorGraph`
35
- | `selectors`
36
- | `timelineAtoms`
37
- | `timelines`
38
- | `transactions`
39
- | `valueMap`
28
+ Store,
29
+ | `atoms`
30
+ | `atomsThatAreDefault`
31
+ | `operation`
32
+ | `readonlySelectors`
33
+ | `selectorAtoms`
34
+ | `selectorGraph`
35
+ | `selectors`
36
+ | `timelineAtoms`
37
+ | `timelines`
38
+ | `transactions`
39
+ | `valueMap`
40
40
  >
41
41
 
42
42
  export interface Store {
43
- atoms: Hamt<Atom<any>, string>
44
- atomsThatAreDefault: Set<string>
45
- readonlySelectors: Hamt<ReadonlySelector<any>, string>
46
- selectorAtoms: Join<null, `selectorKey`, `atomKey`>
47
- selectorGraph: Join<{ source: string }>
48
- selectors: Hamt<Selector<any>, string>
49
- timelineAtoms: Join<null, `timelineKey`, `atomKey`>
50
- timelines: Hamt<Timeline, string>
51
- transactions: Hamt<Transaction<any>, string>
52
- valueMap: Hamt<any, string>
43
+ atoms: Hamt<Atom<any>, string>
44
+ atomsThatAreDefault: Set<string>
45
+ readonlySelectors: Hamt<ReadonlySelector<any>, string>
46
+ selectorAtoms: Join<null, `selectorKey`, `atomKey`>
47
+ selectorGraph: Join<{ source: string }>
48
+ selectors: Hamt<Selector<any>, string>
49
+ timelineAtoms: Join<null, `timelineKey`, `atomKey`>
50
+ timelines: Hamt<Timeline, string>
51
+ transactions: Hamt<Transaction<any>, string>
52
+ valueMap: Hamt<any, string>
53
53
 
54
- subject: {
55
- atomCreation: Rx.Subject<AtomToken<unknown>>
56
- selectorCreation: Rx.Subject<
57
- ReadonlySelectorToken<unknown> | SelectorToken<unknown>
58
- >
59
- transactionCreation: Rx.Subject<TransactionToken<unknown>>
60
- timelineCreation: Rx.Subject<TimelineToken>
61
- }
54
+ subject: {
55
+ atomCreation: Subject<AtomToken<unknown>>
56
+ selectorCreation: Subject<
57
+ ReadonlySelectorToken<unknown> | SelectorToken<unknown>
58
+ >
59
+ transactionCreation: Subject<TransactionToken<unknown>>
60
+ timelineCreation: Subject<TimelineToken>
61
+ }
62
62
 
63
- operation: OperationProgress
64
- transactionStatus: TransactionStatus<ƒn>
65
- config: {
66
- name: string
67
- logger: Logger | null
68
- logger__INTERNAL: Logger
69
- }
63
+ operation: OperationProgress
64
+ transactionStatus: TransactionStatus<ƒn>
65
+ config: {
66
+ name: string
67
+ logger: Logger | null
68
+ logger__INTERNAL: Logger
69
+ }
70
70
  }
71
71
 
72
72
  export const createStore = (name: string, store: Store | null = null): Store => {
73
- const copiedStore = {
74
- ...(store ??
75
- (() => ({
76
- atomsThatAreDefault: new Set(),
77
- selectorAtoms: new Join({ relationType: `n:n` })
78
- .from(`selectorKey`)
79
- .to(`atomKey`),
80
- selectorGraph: new Join({ relationType: `n:n` }),
81
- valueMap: HAMT.make<any, string>(),
82
- }))()),
73
+ const copiedStore = {
74
+ ...(store ??
75
+ (() => ({
76
+ atomsThatAreDefault: new Set(),
77
+ selectorAtoms: new Join({ relationType: `n:n` })
78
+ .from(`selectorKey`)
79
+ .to(`atomKey`),
80
+ selectorGraph: new Join({ relationType: `n:n` }),
81
+ valueMap: HAMT.make<any, string>(),
82
+ }))()),
83
83
 
84
- atoms: HAMT.make<Atom<any>, string>(),
85
- readonlySelectors: HAMT.make<ReadonlySelector<any>, string>(),
86
- selectors: HAMT.make<Selector<any>, string>(),
87
- transactions: HAMT.make<Transaction<any>, string>(),
88
- timelines: HAMT.make<Timeline, string>(),
84
+ atoms: HAMT.make<Atom<any>, string>(),
85
+ readonlySelectors: HAMT.make<ReadonlySelector<any>, string>(),
86
+ selectors: HAMT.make<Selector<any>, string>(),
87
+ transactions: HAMT.make<Transaction<any>, string>(),
88
+ timelines: HAMT.make<Timeline, string>(),
89
89
 
90
- timelineAtoms: new Join({ relationType: `1:n` })
91
- .from(`timelineKey`)
92
- .to(`atomKey`),
90
+ timelineAtoms: new Join({ relationType: `1:n` })
91
+ .from(`timelineKey`)
92
+ .to(`atomKey`),
93
93
 
94
- subject: {
95
- atomCreation: new Rx.Subject(),
96
- selectorCreation: new Rx.Subject(),
97
- transactionCreation: new Rx.Subject(),
98
- timelineCreation: new Rx.Subject(),
99
- ...store?.subject,
100
- },
94
+ subject: {
95
+ atomCreation: new Subject(),
96
+ selectorCreation: new Subject(),
97
+ transactionCreation: new Subject(),
98
+ timelineCreation: new Subject(),
99
+ ...store?.subject,
100
+ },
101
101
 
102
- operation: {
103
- open: false,
104
- ...store?.operation,
105
- },
106
- transactionStatus: {
107
- phase: `idle`,
108
- ...store?.transactionStatus,
109
- },
110
- config: {
111
- logger: {
112
- ...console,
113
- info: doNothing,
114
- ...store?.config?.logger,
115
- },
116
- logger__INTERNAL: console,
117
- ...store?.config,
118
- name,
119
- },
120
- } satisfies Store
102
+ operation: {
103
+ open: false,
104
+ ...store?.operation,
105
+ },
106
+ transactionStatus: {
107
+ phase: `idle`,
108
+ ...store?.transactionStatus,
109
+ },
110
+ config: {
111
+ logger: {
112
+ ...console,
113
+ info: doNothing,
114
+ ...store?.config?.logger,
115
+ },
116
+ logger__INTERNAL: console,
117
+ ...store?.config,
118
+ name,
119
+ },
120
+ } satisfies Store
121
121
 
122
- store?.atoms.forEach((atom) => {
123
- const copiedAtom = { ...atom, subject: new Rx.Subject() } satisfies Atom<any>
124
- copiedStore.atoms = HAMT.set(atom.key, copiedAtom, copiedStore.atoms)
125
- })
126
- store?.readonlySelectors.forEach((selector) => {
127
- selector.install(copiedStore)
128
- })
129
- store?.selectors.forEach((selector) => {
130
- selector.install(copiedStore)
131
- })
132
- store?.transactions.forEach((tx) => {
133
- tx.install(copiedStore)
134
- })
135
- store?.timelines.forEach((timeline) => {
136
- timeline.install(copiedStore)
137
- })
122
+ store?.atoms.forEach((atom) => {
123
+ const copiedAtom = { ...atom, subject: new Subject() } satisfies Atom<any>
124
+ copiedStore.atoms = HAMT.set(atom.key, copiedAtom, copiedStore.atoms)
125
+ })
126
+ store?.readonlySelectors.forEach((selector) => {
127
+ selector.install(copiedStore)
128
+ })
129
+ store?.selectors.forEach((selector) => {
130
+ selector.install(copiedStore)
131
+ })
132
+ store?.transactions.forEach((tx) => {
133
+ tx.install(copiedStore)
134
+ })
135
+ store?.timelines.forEach((timeline) => {
136
+ timeline.install(copiedStore)
137
+ })
138
138
 
139
- return copiedStore
139
+ return copiedStore
140
140
  }
141
141
 
142
142
  export const IMPLICIT = {
143
- STORE_INTERNAL: undefined as Store | undefined,
144
- get STORE(): Store {
145
- return this.STORE_INTERNAL ?? (this.STORE_INTERNAL = createStore(`DEFAULT`))
146
- },
143
+ STORE_INTERNAL: undefined as Store | undefined,
144
+ get STORE(): Store {
145
+ return this.STORE_INTERNAL ?? (this.STORE_INTERNAL = createStore(`DEFAULT`))
146
+ },
147
147
  }
148
148
 
149
149
  export const clearStore = (store: Store = IMPLICIT.STORE): void => {
150
- const { config } = store
151
- Object.assign(store, createStore(config.name))
152
- store.config = config
150
+ const { config } = store
151
+ Object.assign(store, createStore(config.name))
152
+ store.config = config
153
153
  }
@@ -0,0 +1,24 @@
1
+ type Subscriber<T> = (value: T) => void
2
+
3
+ export class Subject<T> {
4
+ public subscribers: Subscriber<T>[] = []
5
+
6
+ public subscribe(subscriber: Subscriber<T>): { unsubscribe: () => void } {
7
+ this.subscribers.push(subscriber)
8
+ const unsubscribe = () => this.unsubscribe(subscriber)
9
+ return { unsubscribe }
10
+ }
11
+
12
+ private unsubscribe(subscriber: Subscriber<T>) {
13
+ const subscriberIndex = this.subscribers.indexOf(subscriber)
14
+ if (subscriberIndex !== -1) {
15
+ this.subscribers.splice(subscriberIndex, 1)
16
+ }
17
+ }
18
+
19
+ public next(value: T): void {
20
+ for (const subscriber of this.subscribers) {
21
+ subscriber(value)
22
+ }
23
+ }
24
+ }