atom.io 0.38.2 → 0.39.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 (91) hide show
  1. package/dist/data/index.js.map +1 -1
  2. package/dist/eslint-plugin/index.js +2 -1
  3. package/dist/eslint-plugin/index.js.map +1 -1
  4. package/dist/internal/index.d.ts +128 -85
  5. package/dist/internal/index.d.ts.map +1 -1
  6. package/dist/internal/index.js +429 -286
  7. package/dist/internal/index.js.map +1 -1
  8. package/dist/introspection/index.d.ts.map +1 -1
  9. package/dist/introspection/index.js.map +1 -1
  10. package/dist/json/index.d.ts.map +1 -1
  11. package/dist/json/index.js.map +1 -1
  12. package/dist/main/index.d.ts +45 -35
  13. package/dist/main/index.d.ts.map +1 -1
  14. package/dist/main/index.js.map +1 -1
  15. package/dist/react/index.d.ts.map +1 -1
  16. package/dist/react/index.js +43 -2
  17. package/dist/react/index.js.map +1 -1
  18. package/dist/react-devtools/index.d.ts.map +1 -1
  19. package/dist/react-devtools/index.js +4 -5
  20. package/dist/react-devtools/index.js.map +1 -1
  21. package/dist/realtime/index.d.ts.map +1 -1
  22. package/dist/realtime/index.js.map +1 -1
  23. package/dist/realtime-client/index.js +5 -5
  24. package/dist/realtime-client/index.js.map +1 -1
  25. package/dist/realtime-react/index.js.map +1 -1
  26. package/dist/realtime-server/index.d.ts.map +1 -1
  27. package/dist/realtime-server/index.js +4 -4
  28. package/dist/realtime-server/index.js.map +1 -1
  29. package/dist/realtime-testing/index.d.ts.map +1 -1
  30. package/dist/realtime-testing/index.js.map +1 -1
  31. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  32. package/dist/transceivers/set-rtx/index.js.map +1 -1
  33. package/dist/web/index.js.map +1 -1
  34. package/package.json +10 -11
  35. package/src/internal/atom/create-regular-atom.ts +2 -6
  36. package/src/internal/caching.ts +2 -4
  37. package/src/internal/{ingest-updates → events}/ingest-atom-update.ts +4 -5
  38. package/src/internal/{ingest-updates → events}/ingest-creation-disposal.ts +37 -37
  39. package/src/internal/{ingest-updates → events}/ingest-selector-update.ts +5 -5
  40. package/src/internal/events/ingest-transaction-update.ts +45 -0
  41. package/src/internal/families/create-readonly-held-selector-family.ts +1 -1
  42. package/src/internal/families/create-readonly-pure-selector-family.ts +1 -1
  43. package/src/internal/families/create-regular-atom-family.ts +4 -3
  44. package/src/internal/families/create-writable-held-selector-family.ts +1 -1
  45. package/src/internal/families/create-writable-pure-selector-family.ts +1 -1
  46. package/src/internal/families/find-in-store.ts +2 -2
  47. package/src/internal/families/get-family-of-token.ts +1 -0
  48. package/src/internal/families/index.ts +0 -1
  49. package/src/internal/families/mint-in-store.ts +30 -64
  50. package/src/internal/get-state/get-from-store.ts +2 -3
  51. package/src/internal/get-state/read-or-compute-value.ts +6 -15
  52. package/src/internal/get-state/reduce-reference.ts +52 -11
  53. package/src/internal/index.ts +2 -2
  54. package/src/internal/is-fn.ts +9 -0
  55. package/src/internal/junction.ts +177 -133
  56. package/src/internal/mutable/create-mutable-atom-family.ts +1 -1
  57. package/src/internal/overlays/index.ts +3 -0
  58. package/src/internal/overlays/map-overlay.ts +86 -0
  59. package/src/internal/{lazy-map.ts → overlays/relations-overlay.ts} +6 -6
  60. package/src/internal/overlays/set-overlay.ts +55 -0
  61. package/src/internal/selector/create-readonly-held-selector.ts +8 -11
  62. package/src/internal/selector/create-readonly-pure-selector.ts +8 -10
  63. package/src/internal/selector/create-writable-held-selector.ts +6 -6
  64. package/src/internal/selector/create-writable-pure-selector.ts +2 -2
  65. package/src/internal/selector/register-selector.ts +3 -4
  66. package/src/internal/set-state/become.ts +11 -6
  67. package/src/internal/set-state/dispatch-state-update.ts +47 -12
  68. package/src/internal/set-state/operate-on-store.ts +10 -8
  69. package/src/internal/set-state/reset-atom-or-selector.ts +7 -7
  70. package/src/internal/set-state/set-atom-or-selector.ts +3 -2
  71. package/src/internal/set-state/set-atom.ts +5 -4
  72. package/src/internal/set-state/set-selector.ts +9 -8
  73. package/src/internal/store/withdraw.ts +4 -4
  74. package/src/internal/timeline/time-travel.ts +11 -11
  75. package/src/internal/transaction/apply-transaction.ts +5 -5
  76. package/src/internal/transaction/build-transaction.ts +17 -26
  77. package/src/internal/transaction/create-transaction.ts +1 -1
  78. package/src/internal/transaction/is-root-store.ts +2 -2
  79. package/src/main/events.ts +14 -3
  80. package/src/main/logger.ts +43 -32
  81. package/src/react-devtools/json-editor/editors-by-type/array-editor.tsx +1 -1
  82. package/src/react-devtools/json-editor/editors-by-type/object-editor.tsx +2 -3
  83. package/src/react-devtools/json-editor/editors-by-type/utilities/array-elements.ts +1 -1
  84. package/src/react-devtools/json-editor/editors-by-type/utilities/object-properties.ts +1 -1
  85. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +5 -5
  86. package/src/realtime-server/continuity/subscribe-to-continuity-perpectives.ts +4 -4
  87. package/dist/use-o-DXPncKmZ.js +0 -47
  88. package/dist/use-o-DXPncKmZ.js.map +0 -1
  89. package/src/internal/families/init-family-member.ts +0 -33
  90. package/src/internal/ingest-updates/ingest-transaction-update.ts +0 -47
  91. /package/src/internal/{ingest-updates → events}/index.ts +0 -0
@@ -0,0 +1,55 @@
1
+ export class SetOverlay<T> extends Set<T> {
2
+ public deleted: Set<T> = new Set()
3
+ public source: Set<T>
4
+
5
+ public constructor(source: Set<T>) {
6
+ super()
7
+ this.source = source
8
+ }
9
+
10
+ public add(value: T): this {
11
+ if (this.source.has(value)) {
12
+ this.deleted.delete(value)
13
+ return this
14
+ }
15
+ return super.add(value)
16
+ }
17
+
18
+ public hasOwn(member: T): boolean {
19
+ return super.has(member)
20
+ }
21
+
22
+ public has(key: T): boolean {
23
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key))
24
+ }
25
+
26
+ public delete(key: T): boolean {
27
+ if (this.source.has(key)) {
28
+ this.deleted.add(key)
29
+ return true
30
+ }
31
+ return super.delete(key)
32
+ }
33
+
34
+ public clear(): void {
35
+ this.deleted = new Set(this.source)
36
+ super.clear()
37
+ }
38
+
39
+ public *[Symbol.iterator](): SetIterator<T> {
40
+ yield* super[Symbol.iterator]()
41
+ for (const value of this.source) {
42
+ if (!this.deleted.has(value)) {
43
+ yield value
44
+ }
45
+ }
46
+ }
47
+
48
+ public *iterateOwn(): SetIterator<T> {
49
+ yield* super[Symbol.iterator]()
50
+ }
51
+
52
+ public get size(): number {
53
+ return super.size + this.source.size - this.deleted.size
54
+ }
55
+ }
@@ -21,6 +21,8 @@ export function createReadonlyHeldSelector<T extends object>(
21
21
  const covered = new Set<string>()
22
22
  const { key, const: constant } = options
23
23
  const type = `readonly_held_selector` as const
24
+ store.logger.info(`🔨`, type, key, `is being created`)
25
+
24
26
  const { get, find, json } = registerSelector(target, type, key, covered)
25
27
 
26
28
  const getFrom = (innerTarget: Store) => {
@@ -35,6 +37,7 @@ export function createReadonlyHeldSelector<T extends object>(
35
37
  innerTarget.selectorAtoms.delete(key)
36
38
  options.get({ get, find, json }, constant)
37
39
  writeToCache(innerTarget, readonlySelector, constant)
40
+ store.logger.info(`✨`, type, key, `=`, constant)
38
41
  covered.clear()
39
42
  return constant
40
43
  }
@@ -46,17 +49,11 @@ export function createReadonlyHeldSelector<T extends object>(
46
49
  getFrom,
47
50
  install: (s: Store) => createReadonlyHeldSelector(s, options, family),
48
51
  }
49
- if (family) {
50
- readonlySelector.family = family
51
- }
52
+ if (family) readonlySelector.family = family
53
+
52
54
  target.readonlySelectors.set(key, readonlySelector)
53
- store.logger.info(`✨`, type, key, `=`, constant)
54
- const token: ReadonlyHeldSelectorToken<T> = {
55
- key,
56
- type,
57
- }
58
- if (family) {
59
- token.family = family
60
- }
55
+ const token: ReadonlyHeldSelectorToken<T> = { key, type }
56
+ if (family) token.family = family
57
+
61
58
  return token
62
59
  }
@@ -21,6 +21,8 @@ export function createReadonlyPureSelector<T>(
21
21
  const covered = new Set<string>()
22
22
  const key = options.key
23
23
  const type = `readonly_pure_selector` as const
24
+ store.logger.info(`🔨`, type, key, `is being created`)
25
+
24
26
  const { get, find, json } = registerSelector(target, type, key, covered)
25
27
 
26
28
  const getFrom = () => {
@@ -48,16 +50,12 @@ export function createReadonlyPureSelector<T>(
48
50
  getFrom,
49
51
  install: (s: Store) => createReadonlyPureSelector(s, options, family),
50
52
  }
51
- if (family) {
52
- readonlySelector.family = family
53
- }
53
+ if (family) readonlySelector.family = family
54
+
54
55
  target.readonlySelectors.set(key, readonlySelector)
55
- const token: ReadonlyPureSelectorToken<T> = {
56
- key,
57
- type,
58
- }
59
- if (family) {
60
- token.family = family
61
- }
56
+
57
+ const token: ReadonlyPureSelectorToken<T> = { key, type }
58
+ if (family) token.family = family
59
+
62
60
  return token
63
61
  }
@@ -21,6 +21,8 @@ export function createWritableHeldSelector<T extends object>(
21
21
  const covered = new Set<string>()
22
22
  const { key, const: constant } = options
23
23
  const type = `writable_held_selector` as const
24
+ store.logger.info(`🔨`, type, key, `is being created`)
25
+
24
26
  const setterToolkit = registerSelector(target, type, key, covered)
25
27
  const { find, get, json } = setterToolkit
26
28
  const getterToolkit = { find, get, json }
@@ -54,14 +56,12 @@ export function createWritableHeldSelector<T extends object>(
54
56
  setSelf,
55
57
  install: (s: Store) => createWritableHeldSelector(s, options, family),
56
58
  }
57
- if (family) {
58
- mySelector.family = family
59
- }
59
+ if (family) mySelector.family = family
60
+
60
61
  target.writableSelectors.set(key, mySelector)
61
62
 
62
63
  const token: WritableHeldSelectorToken<T> = { key, type }
63
- if (family) {
64
- token.family = family
65
- }
64
+ if (family) token.family = family
65
+
66
66
  return token
67
67
  }
@@ -21,6 +21,8 @@ export function createWritablePureSelector<T>(
21
21
  const covered = new Set<string>()
22
22
  const key = options.key
23
23
  const type = `writable_pure_selector` as const
24
+ store.logger.info(`🔨`, type, key, `is being created`)
25
+
24
26
  const setterToolkit = registerSelector(target, type, key, covered)
25
27
  const { find, get, json } = setterToolkit
26
28
  const getterToolkit = { find, get, json }
@@ -57,8 +59,6 @@ export function createWritablePureSelector<T>(
57
59
  if (family) mySelector.family = family
58
60
 
59
61
  target.writableSelectors.set(key, mySelector)
60
- const initialValue = getFrom(target)
61
- store.logger.info(`✨`, mySelector.type, mySelector.key, `=`, initialValue)
62
62
 
63
63
  const token: WritablePureSelectorToken<T> = { key, type }
64
64
  if (family) token.family = family
@@ -37,11 +37,10 @@ export function registerSelector(
37
37
  | [ReadableToken<any>]
38
38
  ) => {
39
39
  const target = newest(store)
40
- const { token, familyToken, subKey } = reduceReference(store, ...params)
40
+ const { token, family, subKey } = reduceReference(store, ...params)
41
41
  let dependencyValue: unknown
42
- if (`counterfeit` in token && familyToken && subKey) {
43
- const dependencyFamily = withdraw(store, familyToken)
44
- dependencyValue = getFallback(store, token, dependencyFamily, subKey)
42
+ if (`counterfeit` in token && family && subKey) {
43
+ dependencyValue = getFallback(store, token, family, subKey)
45
44
  } else {
46
45
  const dependency = withdraw(store, token)
47
46
  dependencyValue = readOrComputeValue(store, dependency)
@@ -1,8 +1,13 @@
1
+ import { isFn } from "../is-fn"
2
+
1
3
  export type Modify<T> = (thing: T) => T
2
4
 
3
- export const become =
4
- <T>(nextVersionOfThing: Modify<T> | T) =>
5
- (originalThing: T): T =>
6
- nextVersionOfThing instanceof Function
7
- ? nextVersionOfThing(originalThing)
8
- : nextVersionOfThing
5
+ export function become<T>(
6
+ nextVersionOfThing: Modify<T> | T,
7
+ originalThing: T,
8
+ ): T {
9
+ if (isFn(nextVersionOfThing)) {
10
+ return nextVersionOfThing(originalThing)
11
+ }
12
+ return nextVersionOfThing
13
+ }
@@ -1,11 +1,12 @@
1
- import type {
2
- AtomToken,
3
- AtomUpdateEvent,
4
- StateUpdate,
5
- WritableToken,
6
- } from "atom.io"
1
+ import type { AtomUpdateEvent, StateCreationEvent, StateUpdate } from "atom.io"
7
2
 
8
- import type { MutableAtom, WritableState } from ".."
3
+ import {
4
+ type MutableAtom,
5
+ newest,
6
+ type Subject,
7
+ type WritableFamily,
8
+ type WritableState,
9
+ } from ".."
9
10
  import { hasRole } from "../atom"
10
11
  import { readOrComputeValue } from "../get-state"
11
12
  import type { Transceiver } from "../mutable"
@@ -14,13 +15,49 @@ import type { OpenOperation } from "../operation"
14
15
  import { deposit, type Store } from "../store"
15
16
  import { isChildStore, isRootStore } from "../transaction"
16
17
  import { evictDownstreamFromAtom } from "./evict-downstream"
18
+ import type { ProtoUpdate } from "./operate-on-store"
17
19
 
18
20
  export function dispatchOrDeferStateUpdate<T>(
19
21
  target: Store & { operation: OpenOperation<any> },
20
22
  state: WritableState<T>,
21
- [oldValue, newValue]: [T, T],
22
- _stateIsNewlyCreated: boolean,
23
+ { oldValue, newValue }: ProtoUpdate<T>,
24
+ stateIsNewlyCreated: boolean,
25
+ family?: WritableFamily<T, any>,
23
26
  ): void {
27
+ const token = deposit(state)
28
+ if (stateIsNewlyCreated && family) {
29
+ state.subject.next({ newValue })
30
+ const stateCreationEvent: StateCreationEvent<any> = {
31
+ type: `state_creation`,
32
+ subType: `writable`,
33
+ token,
34
+ timestamp: Date.now(),
35
+ value: newValue,
36
+ }
37
+ const familySubject = family.subject as Subject<StateCreationEvent<any>>
38
+ familySubject.next(stateCreationEvent)
39
+ const innerTarget = newest(target)
40
+ if (token.family) {
41
+ if (isRootStore(innerTarget)) {
42
+ switch (token.type) {
43
+ case `atom`:
44
+ case `mutable_atom`:
45
+ target.on.atomCreation.next(token)
46
+ break
47
+ case `writable_pure_selector`:
48
+ case `writable_held_selector`:
49
+ target.on.selectorCreation.next(token)
50
+ break
51
+ }
52
+ } else if (
53
+ isChildStore(innerTarget) &&
54
+ innerTarget.on.transactionApplying.state === null
55
+ ) {
56
+ innerTarget.transactionMeta.update.subEvents.push(stateCreationEvent)
57
+ }
58
+ }
59
+ return /* bailing early here to avoid redundant update */
60
+ }
24
61
  const { key, subject, type } = state
25
62
 
26
63
  const update: StateUpdate<T> = {
@@ -61,13 +98,11 @@ export function dispatchOrDeferStateUpdate<T>(
61
98
 
62
99
  if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
63
100
  if (target.on.transactionApplying.state === null) {
64
- const token: WritableToken<T> = deposit(state)
65
-
66
101
  if (isTransceiver(newValue)) {
67
102
  return
68
103
  }
69
104
  const { timestamp } = target.operation
70
- const atomUpdate: AtomUpdateEvent<AtomToken<T>> = {
105
+ const atomUpdate: AtomUpdateEvent<any> = {
71
106
  type: `atom_update`,
72
107
  token,
73
108
  timestamp,
@@ -1,6 +1,7 @@
1
1
  import type { WritableFamilyToken, WritableToken } from "atom.io"
2
2
  import { type Canonical, parseJson } from "atom.io/json"
3
3
 
4
+ import type { WritableFamily } from ".."
4
5
  import { seekInStore } from "../families"
5
6
  import { getFamilyOfToken } from "../families/get-family-of-token"
6
7
  import { mintInStore, MUST_CREATE } from "../families/mint-in-store"
@@ -12,6 +13,8 @@ import { resetAtomOrSelector } from "./reset-atom-or-selector"
12
13
  import { RESET_STATE } from "./reset-in-store"
13
14
  import { setAtomOrSelector } from "./set-atom-or-selector"
14
15
 
16
+ export type ProtoUpdate<T> = { oldValue: T; newValue: T }
17
+
15
18
  export const OWN_OP: unique symbol = Symbol(`OWN_OP`)
16
19
  export const JOIN_OP: unique symbol = Symbol(`JOIN_OP`)
17
20
 
@@ -32,7 +35,7 @@ export function operateOnStore<T, New extends T>(
32
35
  let existingToken: WritableToken<T> | undefined
33
36
  let brandNewToken: WritableToken<T> | undefined
34
37
  let token: WritableToken<T>
35
- let family: WritableFamilyToken<T, Canonical> | null
38
+ let family: WritableFamily<T, Canonical> | undefined
36
39
  let key: Canonical | null
37
40
  let value: New | typeof RESET_STATE | ((oldValue: T) => New)
38
41
  if (params.length === 2) {
@@ -43,20 +46,18 @@ export function operateOnStore<T, New extends T>(
43
46
  key = parseJson(token.family.subKey)
44
47
  existingToken = seekInStore(store, family, key)
45
48
  if (!existingToken) {
46
- brandNewToken = mintInStore(store, family, key, MUST_CREATE)
47
- token = brandNewToken
49
+ token = brandNewToken = mintInStore(store, family, key, MUST_CREATE)
48
50
  } else {
49
51
  token = existingToken
50
52
  }
51
53
  }
52
54
  } else {
53
- family = params[0]
55
+ family = withdraw(store, params[0])
54
56
  key = params[1]
55
57
  value = params[2]
56
58
  existingToken = seekInStore(store, family, key)
57
59
  if (!existingToken) {
58
- brandNewToken = mintInStore(store, family, key, MUST_CREATE)
59
- token = brandNewToken
60
+ token = brandNewToken = mintInStore(store, family, key, MUST_CREATE)
60
61
  } else {
61
62
  token = existingToken
62
63
  }
@@ -115,14 +116,15 @@ export function operateOnStore<T, New extends T>(
115
116
  }
116
117
 
117
118
  const state = withdraw(target, token)
118
- let protoUpdate: [T, T]
119
+ let protoUpdate: ProtoUpdate<T>
119
120
  if (value === RESET_STATE) {
120
121
  protoUpdate = resetAtomOrSelector(target, state)
121
122
  } else {
122
123
  protoUpdate = setAtomOrSelector(target, state, value)
123
124
  }
125
+
124
126
  const isNewlyCreated = Boolean(brandNewToken)
125
- dispatchOrDeferStateUpdate(target, state, protoUpdate, isNewlyCreated)
127
+ dispatchOrDeferStateUpdate(target, state, protoUpdate, isNewlyCreated, family)
126
128
 
127
129
  if (opMode === OWN_OP) {
128
130
  closeOperation(target)
@@ -1,20 +1,20 @@
1
1
  import type { Atom, OpenOperation, Store, WritableState } from ".."
2
2
  import { traceRootSelectorAtoms } from ".."
3
+ import { isFn } from "../is-fn"
3
4
  import { dispatchOrDeferStateUpdate } from "./dispatch-state-update"
5
+ import type { ProtoUpdate } from "./operate-on-store"
4
6
  import { setAtom } from "./set-atom"
5
7
 
6
8
  function resetAtom<T>(
7
9
  target: Store & { operation: OpenOperation },
8
10
  atom: Atom<T>,
9
- ): [oldValue: T, newValue: T] {
11
+ ): ProtoUpdate<T> {
10
12
  switch (atom.type) {
11
13
  case `mutable_atom`:
12
14
  return setAtom(target, atom, new atom.class())
13
15
  case `atom`: {
14
16
  let def = atom.default
15
- if (def instanceof Function) {
16
- def = def()
17
- }
17
+ if (isFn(def)) def = def()
18
18
  return setAtom(target, atom, def)
19
19
  }
20
20
  }
@@ -23,8 +23,8 @@ function resetAtom<T>(
23
23
  export function resetAtomOrSelector<T>(
24
24
  target: Store & { operation: OpenOperation },
25
25
  state: WritableState<T>,
26
- ): [oldValue: T, newValue: T] {
27
- let protoUpdate: [T, T]
26
+ ): ProtoUpdate<T> {
27
+ let protoUpdate: ProtoUpdate<T>
28
28
  switch (state.type) {
29
29
  case `atom`:
30
30
  case `mutable_atom`:
@@ -40,7 +40,7 @@ export function resetAtomOrSelector<T>(
40
40
  dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false)
41
41
  }
42
42
  const newValue = state.getFrom(target)
43
- protoUpdate = [oldValue, newValue]
43
+ protoUpdate = { oldValue, newValue }
44
44
  }
45
45
  break
46
46
  }
@@ -1,6 +1,7 @@
1
1
  import type { WritableState } from ".."
2
2
  import type { OpenOperation } from "../operation"
3
3
  import type { Store } from "../store"
4
+ import type { ProtoUpdate } from "./operate-on-store"
4
5
  import { setAtom } from "./set-atom"
5
6
  import { setSelector } from "./set-selector"
6
7
 
@@ -8,8 +9,8 @@ export const setAtomOrSelector = <T>(
8
9
  target: Store & { operation: OpenOperation },
9
10
  state: WritableState<T>,
10
11
  value: T | ((oldValue: T) => T),
11
- ): [oldValue: T, newValue: T] => {
12
- let protoUpdate: [T, T]
12
+ ): ProtoUpdate<T> => {
13
+ let protoUpdate: ProtoUpdate<T>
13
14
  switch (state.type) {
14
15
  case `atom`:
15
16
  case `mutable_atom`:
@@ -4,17 +4,18 @@ import { readOrComputeValue } from "../get-state/read-or-compute-value"
4
4
  import { markDone } from "../operation"
5
5
  import { become } from "./become"
6
6
  import { evictDownstreamFromAtom } from "./evict-downstream"
7
+ import type { ProtoUpdate } from "./operate-on-store"
7
8
 
8
9
  export const setAtom = <T>(
9
10
  target: Store & { operation: OpenOperation<any> },
10
11
  atom: Atom<T>,
11
12
  next: T | ((oldValue: T) => T),
12
- ): [oldValue: T, newValue: T] => {
13
+ ): ProtoUpdate<T> => {
13
14
  const oldValue = readOrComputeValue(target, atom, `mut`)
14
- let newValue = become(next)(oldValue)
15
- target.logger.info(`📝`, `atom`, atom.key, `set to`, newValue)
15
+ let newValue = become(next, oldValue)
16
+ target.logger.info(`⭐`, `atom`, atom.key, `setting value`, newValue)
16
17
  newValue = writeToCache(target, atom, newValue)
17
18
  markDone(target, atom.key)
18
19
  evictDownstreamFromAtom(target, atom)
19
- return [oldValue, newValue]
20
+ return { oldValue, newValue }
20
21
  }
@@ -1,14 +1,15 @@
1
- import type { WritableSelector } from ".."
1
+ import { readOrComputeValue, type WritableSelector } from ".."
2
2
  import { writeToCache } from "../caching"
3
3
  import { markDone, type OpenOperation } from "../operation"
4
4
  import type { Store } from "../store"
5
5
  import { become } from "./become"
6
+ import type { ProtoUpdate } from "./operate-on-store"
6
7
 
7
8
  export function setSelector<T>(
8
9
  target: Store & { operation: OpenOperation<any> },
9
10
  selector: WritableSelector<T>,
10
11
  next: T | ((oldValue: T) => T),
11
- ): [oldValue: T, newValue: T] {
12
+ ): ProtoUpdate<T> {
12
13
  let oldValue: T
13
14
  let newValue: T
14
15
  let constant: T
@@ -17,19 +18,19 @@ export function setSelector<T>(
17
18
 
18
19
  switch (selector.type) {
19
20
  case `writable_pure_selector`:
20
- oldValue = selector.getFrom(target)
21
- newValue = become(next)(oldValue)
22
- writeToCache(target, selector, newValue)
21
+ oldValue = readOrComputeValue(target, selector, `mut`)
22
+ newValue = become(next, oldValue)
23
+ newValue = writeToCache(target, selector, newValue)
23
24
  break
24
25
  case `writable_held_selector`:
25
26
  constant = selector.const
26
- become(next)(constant)
27
+ become(next, constant)
27
28
  oldValue = constant
28
29
  newValue = constant
29
30
  }
30
31
 
31
- target.logger.info(`📝`, type, key, `setting to`, newValue)
32
+ target.logger.info(`⭐`, type, key, `setting to`, newValue)
32
33
  markDone(target, key)
33
34
  selector.setSelf(newValue)
34
- return [oldValue, newValue]
35
+ return { oldValue, newValue }
35
36
  }
@@ -171,14 +171,14 @@ export function withdraw<T, K extends Canonical>(
171
171
  store: Store,
172
172
  token: SelectorFamilyToken<T, K>,
173
173
  ): SelectorFamily<T, K>
174
- export function withdraw<T, K extends Canonical>(
175
- store: Store,
176
- token: ReadableFamilyToken<T, K>,
177
- ): ReadableFamily<T, K>
178
174
  export function withdraw<T, K extends Canonical>(
179
175
  store: Store,
180
176
  token: WritableFamilyToken<T, K>,
181
177
  ): WritableFamily<T, K>
178
+ export function withdraw<T, K extends Canonical>(
179
+ store: Store,
180
+ token: ReadableFamilyToken<T, K>,
181
+ ): ReadableFamily<T, K>
182
182
 
183
183
  export function withdraw<T extends Fn>(
184
184
  store: Store,
@@ -1,12 +1,12 @@
1
1
  import type { TimelineToken } from "atom.io"
2
2
 
3
3
  import {
4
- ingestAtomUpdate,
4
+ ingestAtomUpdateEvent,
5
5
  ingestCreationEvent,
6
6
  ingestDisposalEvent,
7
- ingestSelectorUpdate,
8
- ingestTransactionUpdate,
9
- } from "../ingest-updates"
7
+ ingestSelectorUpdateEvent,
8
+ ingestTransactionOutcomeEvent,
9
+ } from "../events"
10
10
  import type { Store } from "../store"
11
11
 
12
12
  export const timeTravel = (
@@ -50,28 +50,28 @@ export const timeTravel = (
50
50
  --timelineData.at
51
51
  }
52
52
 
53
- const update = timelineData.history[timelineData.at]
53
+ const event = timelineData.history[timelineData.at]
54
54
  const applying = action === `redo` ? `newValue` : `oldValue`
55
55
 
56
- switch (update.type) {
56
+ switch (event.type) {
57
57
  case `atom_update`: {
58
- ingestAtomUpdate(applying, update, store)
58
+ ingestAtomUpdateEvent(store, event, applying)
59
59
  break
60
60
  }
61
61
  case `selector_update`: {
62
- ingestSelectorUpdate(applying, update, store)
62
+ ingestSelectorUpdateEvent(store, event, applying)
63
63
  break
64
64
  }
65
65
  case `transaction_outcome`: {
66
- ingestTransactionUpdate(applying, update, store)
66
+ ingestTransactionOutcomeEvent(store, event, applying)
67
67
  break
68
68
  }
69
69
  case `state_creation`: {
70
- ingestCreationEvent(update, applying, store)
70
+ ingestCreationEvent(store, event, applying)
71
71
  break
72
72
  }
73
73
  case `state_disposal`: {
74
- ingestDisposalEvent(update, applying, store)
74
+ ingestDisposalEvent(store, event, applying)
75
75
  break
76
76
  }
77
77
  case `molecule_creation`:
@@ -1,4 +1,4 @@
1
- import { ingestTransactionUpdate } from "../ingest-updates"
1
+ import { ingestTransactionOutcomeEvent } from "../events"
2
2
  import { newest } from "../lineage"
3
3
  import type { Store } from "../store"
4
4
  import { withdraw } from "../store"
@@ -6,10 +6,10 @@ import type { Fn } from "../utility-types"
6
6
  import { isChildStore, isRootStore } from "./is-root-store"
7
7
  import { setEpochNumberOfAction } from "./set-epoch-number"
8
8
 
9
- export const applyTransaction = <F extends Fn>(
10
- output: ReturnType<F>,
9
+ export function applyTransaction<F extends Fn>(
11
10
  store: Store,
12
- ): void => {
11
+ output: ReturnType<F>,
12
+ ): void {
13
13
  const child = newest(store)
14
14
  const { parent } = child
15
15
  if (
@@ -38,7 +38,7 @@ export const applyTransaction = <F extends Fn>(
38
38
  updates,
39
39
  )
40
40
 
41
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent)
41
+ ingestTransactionOutcomeEvent(parent, child.transactionMeta.update, `newValue`)
42
42
 
43
43
  if (isRootStore(parent)) {
44
44
  setEpochNumberOfAction(
@@ -11,10 +11,9 @@ import { arbitrary } from "../arbitrary"
11
11
  import { disposeFromStore, findInStore } from "../families"
12
12
  import { getEnvironmentData } from "../get-environment-data"
13
13
  import { getFromStore } from "../get-state"
14
- import { Junction } from "../junction"
15
- import { LazyMap } from "../lazy-map"
16
14
  import { newest } from "../lineage"
17
15
  import { getJsonToken } from "../mutable"
16
+ import { MapOverlay } from "../overlays/map-overlay"
18
17
  import { resetInStore, setIntoStore } from "../set-state"
19
18
  import type { Store } from "../store"
20
19
  import type { Fn } from "../utility-types"
@@ -36,35 +35,27 @@ export const buildTransaction = (
36
35
  loggers: parent.loggers,
37
36
  logger: parent.logger,
38
37
  config: parent.config,
39
- atoms: new LazyMap(parent.atoms),
38
+ atoms: new MapOverlay(parent.atoms),
40
39
  atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
41
- families: new LazyMap(parent.families),
42
- joins: new LazyMap(parent.joins),
40
+ families: new MapOverlay(parent.families),
41
+ joins: new MapOverlay(parent.joins),
43
42
  operation: { open: false },
44
- readonlySelectors: new LazyMap(parent.readonlySelectors),
45
- timelines: new LazyMap(parent.timelines),
46
- timelineTopics: new Junction(parent.timelineTopics.toJSON()),
43
+ readonlySelectors: new MapOverlay(parent.readonlySelectors),
44
+ timelines: new MapOverlay(parent.timelines),
45
+ timelineTopics: parent.timelineTopics.overlay(),
47
46
  trackers: new Map(),
48
- transactions: new LazyMap(parent.transactions),
49
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
50
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
51
- makeContentKey: (...keys) => keys.sort().join(`:`),
52
- }),
53
- writableSelectors: new LazyMap(parent.writableSelectors),
54
- valueMap: new LazyMap(parent.valueMap),
47
+ transactions: new MapOverlay(parent.transactions),
48
+ selectorAtoms: parent.selectorAtoms.overlay(),
49
+ selectorGraph: parent.selectorGraph.overlay(),
50
+ writableSelectors: new MapOverlay(parent.writableSelectors),
51
+ valueMap: new MapOverlay(parent.valueMap),
55
52
  defaults: parent.defaults,
56
53
  disposalTraces: store.disposalTraces.copy(),
57
- molecules: new LazyMap(parent.molecules),
58
- moleculeGraph: new Junction(parent.moleculeGraph.toJSON(), {
59
- makeContentKey: parent.moleculeGraph.makeContentKey,
60
- }),
61
- moleculeData: new Junction(parent.moleculeData.toJSON(), {
62
- makeContentKey: parent.moleculeData.makeContentKey,
63
- }),
64
- moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), {
65
- makeContentKey: parent.moleculeJoins.makeContentKey,
66
- }),
67
- miscResources: new LazyMap(parent.miscResources),
54
+ molecules: new MapOverlay(parent.molecules),
55
+ moleculeGraph: parent.moleculeGraph.overlay(),
56
+ moleculeData: parent.moleculeData.overlay(),
57
+ moleculeJoins: parent.moleculeJoins.overlay(),
58
+ miscResources: new MapOverlay(parent.miscResources),
68
59
  }
69
60
  const epoch = getEpochNumberOfAction(store, token.key)
70
61
  const transactionMeta: TransactionProgress<Fn> = {