atom.io 0.37.0 → 0.38.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 (42) hide show
  1. package/dist/internal/index.d.ts +32 -33
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +200 -133
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/json/index.d.ts +1 -1
  6. package/dist/json/index.d.ts.map +1 -1
  7. package/dist/json/index.js.map +1 -1
  8. package/dist/main/index.d.ts +6 -3
  9. package/dist/main/index.d.ts.map +1 -1
  10. package/dist/main/index.js +22 -2
  11. package/dist/main/index.js.map +1 -1
  12. package/package.json +2 -2
  13. package/src/internal/atom/dispose-atom.ts +11 -6
  14. package/src/internal/families/create-readonly-held-selector-family.ts +2 -4
  15. package/src/internal/families/create-readonly-pure-selector-family.ts +2 -4
  16. package/src/internal/families/create-regular-atom-family.ts +7 -5
  17. package/src/internal/families/create-writable-held-selector-family.ts +3 -4
  18. package/src/internal/families/create-writable-pure-selector-family.ts +2 -4
  19. package/src/internal/families/find-in-store.ts +7 -1
  20. package/src/internal/families/get-family-of-token.ts +21 -24
  21. package/src/internal/families/mint-in-store.ts +59 -35
  22. package/src/internal/get-state/get-fallback.ts +57 -0
  23. package/src/internal/get-state/get-from-store.ts +10 -47
  24. package/src/internal/get-state/reduce-reference.ts +66 -0
  25. package/src/internal/index.ts +17 -30
  26. package/src/internal/ingest-updates/ingest-creation-disposal.ts +4 -3
  27. package/src/internal/molecule.ts +5 -5
  28. package/src/internal/mutable/create-mutable-atom-family.ts +4 -8
  29. package/src/internal/mutable/get-json-token.ts +2 -1
  30. package/src/internal/not-found-error.ts +2 -3
  31. package/src/internal/operation.ts +1 -1
  32. package/src/internal/selector/register-selector.ts +17 -24
  33. package/src/internal/selector/update-selector-atoms.ts +2 -2
  34. package/src/internal/set-state/operate-on-store.ts +17 -13
  35. package/src/internal/set-state/set-into-store.ts +2 -2
  36. package/src/internal/store/index.ts +1 -1
  37. package/src/internal/store/{counterfeit.ts → mint-or-counterfeit.ts} +27 -15
  38. package/src/internal/subscribe/subscribe-to-state.ts +2 -0
  39. package/src/internal/timeline/create-timeline.ts +2 -0
  40. package/src/json/index.ts +3 -3
  41. package/src/main/logger.ts +26 -4
  42. package/src/internal/pretty-print.ts +0 -7
@@ -7,13 +7,15 @@ import type {
7
7
  WritableToken,
8
8
  WriterToolkit,
9
9
  } from "atom.io"
10
- import type { Canonical, Json } from "atom.io/json"
10
+ import type { Canonical } from "atom.io/json"
11
11
 
12
12
  import { findInStore } from "../families"
13
+ import { getFallback } from "../get-state/get-fallback"
13
14
  import { readOrComputeValue } from "../get-state/read-or-compute-value"
15
+ import { reduceReference } from "../get-state/reduce-reference"
14
16
  import { newest } from "../lineage"
15
17
  import { getJsonToken } from "../mutable"
16
- import { operateOnStore } from "../set-state/operate-on-store"
18
+ import { JOIN_OP, operateOnStore } from "../set-state/operate-on-store"
17
19
  import type { Store } from "../store"
18
20
  import { withdraw } from "../store"
19
21
  import { updateSelectorAtoms } from "./update-selector-atoms"
@@ -31,48 +33,39 @@ export function registerSelector(
31
33
  return {
32
34
  get: (
33
35
  ...params:
34
- | [ReadableFamilyToken<any, any>, Json.Serializable]
36
+ | [ReadableFamilyToken<any, any>, Canonical]
35
37
  | [ReadableToken<any>]
36
38
  ) => {
37
39
  const target = newest(store)
38
- let dependency: ReadableToken<any>
39
-
40
- if (params.length === 2) {
41
- const [family, key] = params
42
- dependency = findInStore(store, family, key)
40
+ const { token, familyToken, subKey } = reduceReference(store, ...params)
41
+ let dependencyValue: unknown
42
+ if (`counterfeit` in token && familyToken && subKey) {
43
+ const dependencyFamily = withdraw(store, familyToken)
44
+ dependencyValue = getFallback(store, token, dependencyFamily, subKey)
43
45
  } else {
44
- ;[dependency] = params
46
+ const dependency = withdraw(store, token)
47
+ dependencyValue = readOrComputeValue(store, dependency)
45
48
  }
46
49
 
47
- const dependencyState = withdraw(store, dependency)
48
- const dependencyValue = readOrComputeValue(store, dependencyState)
49
- const dependencyKey = dependency.key
50
-
51
50
  store.logger.info(
52
51
  `🔌`,
53
52
  selectorType,
54
53
  selectorKey,
55
- `registers dependency ( "${dependencyKey}" =`,
54
+ `registers dependency ( "${token.key}" =`,
56
55
  dependencyValue,
57
56
  `)`,
58
57
  )
59
58
 
60
59
  target.selectorGraph.set(
61
60
  {
62
- upstreamSelectorKey: dependencyKey,
61
+ upstreamSelectorKey: token.key,
63
62
  downstreamSelectorKey: selectorKey,
64
63
  },
65
64
  {
66
- source: dependency.key,
65
+ source: token.key,
67
66
  },
68
67
  )
69
- updateSelectorAtoms(
70
- store,
71
- selectorType,
72
- selectorKey,
73
- dependency as any,
74
- covered,
75
- )
68
+ updateSelectorAtoms(store, selectorType, selectorKey, token, covered)
76
69
  return dependencyValue
77
70
  },
78
71
  set: (<T, K extends Canonical, New extends T, Key extends K>(
@@ -85,7 +78,7 @@ export function registerSelector(
85
78
  | [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
86
79
  ) => {
87
80
  const target = newest(store)
88
- operateOnStore(target, false, ...params)
81
+ operateOnStore(target, JOIN_OP, ...params)
89
82
  }) as typeof setState,
90
83
  find: ((...args: Parameters<typeof findState>) =>
91
84
  findInStore(store, ...args)) as typeof findState,
@@ -1,4 +1,4 @@
1
- import type { ReadonlyPureSelectorToken, WritableToken } from "atom.io"
1
+ import type { ReadableToken } from "atom.io"
2
2
 
3
3
  import { newest } from "../lineage"
4
4
  import type { Store } from "../store"
@@ -12,7 +12,7 @@ export function updateSelectorAtoms(
12
12
  | `writable_held_selector`
13
13
  | `writable_pure_selector`,
14
14
  selectorKey: string,
15
- dependency: ReadonlyPureSelectorToken<unknown> | WritableToken<unknown>,
15
+ dependency: ReadableToken<unknown>,
16
16
  covered: Set<string>,
17
17
  ): void {
18
18
  const target = newest(store)
@@ -3,7 +3,7 @@ import { type Canonical, parseJson } from "atom.io/json"
3
3
 
4
4
  import { seekInStore } from "../families"
5
5
  import { getFamilyOfToken } from "../families/get-family-of-token"
6
- import { mintInStore } from "../families/mint-in-store"
6
+ import { mintInStore, MUST_CREATE } from "../families/mint-in-store"
7
7
  import type { OpenOperation } from "../operation"
8
8
  import { closeOperation, openOperation } from "../operation"
9
9
  import { type Store, withdraw } from "../store"
@@ -12,9 +12,12 @@ import { resetAtomOrSelector } from "./reset-atom-or-selector"
12
12
  import { RESET_STATE } from "./reset-in-store"
13
13
  import { setAtomOrSelector } from "./set-atom-or-selector"
14
14
 
15
+ export const OWN_OP: unique symbol = Symbol(`OWN_OP`)
16
+ export const JOIN_OP: unique symbol = Symbol(`JOIN_OP`)
17
+
15
18
  export function operateOnStore<T, New extends T>(
16
19
  store: Store,
17
- ownOp: boolean,
20
+ opMode: typeof JOIN_OP | typeof OWN_OP,
18
21
  ...params:
19
22
  | [
20
23
  token: WritableFamilyToken<T, Canonical>,
@@ -35,13 +38,12 @@ export function operateOnStore<T, New extends T>(
35
38
  if (params.length === 2) {
36
39
  token = params[0]
37
40
  value = params[1]
38
- if (token.family) {
39
- // biome-ignore lint/style/noNonNullAssertion: this token belongs to a family
40
- family = getFamilyOfToken(store, token)!
41
+ if (`family` in token) {
42
+ family = getFamilyOfToken(store, token)
41
43
  key = parseJson(token.family.subKey)
42
44
  existingToken = seekInStore(store, family, key)
43
45
  if (!existingToken) {
44
- brandNewToken = mintInStore(store, family, key)
46
+ brandNewToken = mintInStore(store, family, key, MUST_CREATE)
45
47
  token = brandNewToken
46
48
  } else {
47
49
  token = existingToken
@@ -53,7 +55,7 @@ export function operateOnStore<T, New extends T>(
53
55
  value = params[2]
54
56
  existingToken = seekInStore(store, family, key)
55
57
  if (!existingToken) {
56
- brandNewToken = mintInStore(store, family, key)
58
+ brandNewToken = mintInStore(store, family, key, MUST_CREATE)
57
59
  token = brandNewToken
58
60
  } else {
59
61
  token = existingToken
@@ -64,7 +66,7 @@ export function operateOnStore<T, New extends T>(
64
66
 
65
67
  let target: Store & { operation: OpenOperation }
66
68
 
67
- if (ownOp) {
69
+ if (opMode === OWN_OP) {
68
70
  const result = openOperation(store, token)
69
71
  const rejected = typeof result === `number`
70
72
  if (rejected) {
@@ -81,7 +83,7 @@ export function operateOnStore<T, New extends T>(
81
83
  action,
82
84
  `from T-${rejectionTime}`,
83
85
  )
84
- operateOnStore(store, ownOp, token, value)
86
+ operateOnStore(store, opMode, token, value)
85
87
  },
86
88
  )
87
89
  return
@@ -102,10 +104,12 @@ export function operateOnStore<T, New extends T>(
102
104
  token.key,
103
105
  `could not be`,
104
106
  action,
105
- `because it was not found in the store "${store.config.name}".`,
107
+ `because key`,
108
+ subKey,
109
+ `is not allocated.`,
106
110
  disposal
107
- ? `This state was previously disposed:\n${disposal.trace}`
108
- : `No previous disposal trace was found.`,
111
+ ? `this key was previously disposed:${disposal.trace}`
112
+ : `(no previous disposal trace found)`,
109
113
  )
110
114
  return
111
115
  }
@@ -120,7 +124,7 @@ export function operateOnStore<T, New extends T>(
120
124
  const isNewlyCreated = Boolean(brandNewToken)
121
125
  dispatchOrDeferStateUpdate(target, state, protoUpdate, isNewlyCreated)
122
126
 
123
- if (ownOp) {
127
+ if (opMode === OWN_OP) {
124
128
  closeOperation(target)
125
129
  }
126
130
  }
@@ -2,7 +2,7 @@ import type { WritableFamilyToken, WritableToken } from "atom.io"
2
2
  import type { Canonical } from "atom.io/json"
3
3
 
4
4
  import type { Store } from "../store"
5
- import { operateOnStore } from "./operate-on-store"
5
+ import { operateOnStore, OWN_OP } from "./operate-on-store"
6
6
  import type { RESET_STATE } from "./reset-in-store"
7
7
 
8
8
  export function setIntoStore<T, New extends T>(
@@ -36,5 +36,5 @@ export function setIntoStore<T, New extends T>(
36
36
  value: New | typeof RESET_STATE | ((oldValue: T) => New),
37
37
  ]
38
38
  ): void {
39
- operateOnStore(store, true, ...params)
39
+ operateOnStore(store, OWN_OP, ...params)
40
40
  }
@@ -1,5 +1,5 @@
1
1
  export * from "./circular-buffer"
2
- export * from "./counterfeit"
3
2
  export * from "./deposit"
3
+ export * from "./mint-or-counterfeit"
4
4
  export * from "./store"
5
5
  export * from "./withdraw"
@@ -21,6 +21,8 @@ import { stringifyJson } from "atom.io/json"
21
21
 
22
22
  import type { Transceiver } from "../mutable"
23
23
 
24
+ export const COUNTERFEIT: unique symbol = Symbol(`counterfeit`)
25
+
24
26
  export const FAMILY_MEMBER_TOKEN_TYPES = {
25
27
  atom_family: `atom`,
26
28
  molecule_family: `molecule`,
@@ -31,66 +33,76 @@ export const FAMILY_MEMBER_TOKEN_TYPES = {
31
33
  writable_pure_selector_family: `writable_pure_selector`,
32
34
  } as const
33
35
 
34
- export function counterfeit<
36
+ export function mint<
35
37
  T extends Transceiver<any, any, any>,
36
38
  K extends Canonical,
37
39
  Key extends K,
38
40
  >(token: MutableAtomFamilyToken<T, K>, key: Key): MutableAtomToken<T>
39
41
 
40
- export function counterfeit<T, K extends Canonical, Key extends K>(
42
+ export function mint<T, K extends Canonical, Key extends K>(
41
43
  token: RegularAtomFamilyToken<T, K>,
42
44
  key: Key,
45
+ counterfeit?: typeof COUNTERFEIT,
43
46
  ): RegularAtomToken<T>
44
47
 
45
- export function counterfeit<T, K extends Canonical, Key extends K>(
48
+ export function mint<T, K extends Canonical, Key extends K>(
46
49
  token: AtomFamilyToken<T, K>,
47
50
  key: Key,
51
+ counterfeit?: typeof COUNTERFEIT,
48
52
  ): AtomToken<T>
49
53
 
50
- export function counterfeit<T, K extends Canonical, Key extends K>(
54
+ export function mint<T, K extends Canonical, Key extends K>(
51
55
  token: WritablePureSelectorFamilyToken<T, K>,
52
56
  key: Key,
57
+ counterfeit?: typeof COUNTERFEIT,
53
58
  ): WritablePureSelectorToken<T>
54
59
 
55
- export function counterfeit<T, K extends Canonical, Key extends K>(
60
+ export function mint<T, K extends Canonical, Key extends K>(
56
61
  token: ReadonlyPureSelectorFamilyToken<T, K>,
57
62
  key: Key,
63
+ counterfeit?: typeof COUNTERFEIT,
58
64
  ): ReadonlyPureSelectorToken<T>
59
65
 
60
- export function counterfeit<T, K extends Canonical, Key extends K>(
66
+ export function mint<T, K extends Canonical, Key extends K>(
61
67
  token: SelectorFamilyToken<T, K>,
62
68
  key: Key,
69
+ counterfeit?: typeof COUNTERFEIT,
63
70
  ): SelectorToken<T>
64
71
 
65
- export function counterfeit<T, K extends Canonical, Key extends K>(
72
+ export function mint<T, K extends Canonical, Key extends K>(
66
73
  token: WritableFamilyToken<T, K>,
67
74
  key: Key,
75
+ counterfeit?: typeof COUNTERFEIT,
68
76
  ): WritableToken<T>
69
77
 
70
- export function counterfeit<T, K extends Canonical, Key extends K>(
78
+ export function mint<T, K extends Canonical, Key extends K>(
71
79
  token: ReadableFamilyToken<T, K>,
72
80
  key: Key,
81
+ counterfeit?: typeof COUNTERFEIT,
73
82
  ): ReadableToken<T>
74
83
 
75
- export function counterfeit(
84
+ export function mint(
76
85
  token: ReadableFamilyToken<any, any>,
77
86
  key: Canonical,
87
+ counterfeit?: typeof COUNTERFEIT,
78
88
  ): ReadableToken<any> {
79
89
  const subKey = stringifyJson(key)
80
90
  const fullKey = `${token.key}(${subKey})`
81
91
  const type = FAMILY_MEMBER_TOKEN_TYPES[token.type]
82
- const stateToken = {
92
+ const stateToken: ReadableToken<any> & {
93
+ counterfeit?: boolean
94
+ } = {
83
95
  key: fullKey,
84
96
  type,
85
- } satisfies ReadableToken<any>
86
-
87
- Object.assign(stateToken, {
88
97
  family: {
89
98
  key: token.key,
90
99
  subKey,
91
100
  },
92
- })
101
+ }
102
+
103
+ if (counterfeit) {
104
+ stateToken.counterfeit = true
105
+ }
93
106
 
94
- Object.assign(stateToken, { counterfeit: true })
95
107
  return stateToken
96
108
  }
@@ -1,6 +1,7 @@
1
1
  import type { ReadableToken, StateUpdate, UpdateHandler } from "atom.io"
2
2
 
3
3
  import { readOrComputeValue } from "../get-state"
4
+ import { reduceReference } from "../get-state/reduce-reference"
4
5
  import { traceRootSelectorAtoms } from "../selector"
5
6
  import type { Store } from "../store"
6
7
  import { withdraw } from "../store"
@@ -25,6 +26,7 @@ export function subscribeToState<T>(
25
26
  handleUpdate(update)
26
27
  }
27
28
  }
29
+ reduceReference(store, token)
28
30
  const state = withdraw(store, token)
29
31
  store.logger.info(`👀`, state.type, state.key, `Adding subscription "${key}"`)
30
32
  const isSelector =
@@ -13,6 +13,7 @@ import type {
13
13
  TransactionToken,
14
14
  } from "atom.io"
15
15
 
16
+ import { reduceReference } from "../get-state/reduce-reference"
16
17
  import { newest } from "../lineage"
17
18
  import { getUpdateToken } from "../mutable"
18
19
  import { deposit, type Store, withdraw } from "../store"
@@ -130,6 +131,7 @@ function addAtomToTimeline(
130
131
  atomToken: AtomToken<any>,
131
132
  tl: Timeline<any>,
132
133
  ): void {
134
+ reduceReference(store, atomToken)
133
135
  let maybeAtom = withdraw(store, atomToken)
134
136
  if (maybeAtom.type === `mutable_atom`) {
135
137
  const updateToken = getUpdateToken(maybeAtom)
package/src/json/index.ts CHANGED
@@ -66,9 +66,9 @@ export type stringified<J extends Json.Serializable> = (
66
66
  )
67
67
 
68
68
  /** Type-safe wrapper for {@link JSON.parse} */
69
- export const parseJson = <S extends stringified<Json.Serializable>>(
70
- str: S | string,
71
- ): S extends stringified<infer J> ? J : Json.Serializable => JSON.parse(str)
69
+ export const parseJson = <J extends Json.Serializable>(
70
+ str: stringified<J> | string,
71
+ ): J => JSON.parse(str)
72
72
 
73
73
  /** Type-safe wrapper for {@link JSON.stringify} */
74
74
  export const stringifyJson = <J extends Json.Serializable>(
@@ -8,10 +8,12 @@ const LOGGER_ICON_DICTIONARY = {
8
8
  "âšī¸": `Time-travel complete`,
9
9
  "✅": `Realtime transaction success`,
10
10
  "✨": `Computation complete`,
11
+ "đŸ’Ŗ": `Dangerous action likely to cause bad errors`,
12
+ "❗": `Dangerous action unless in development mode`,
11
13
  "❌": `Conflict prevents attempted action`,
12
14
  "⭕": `Operation start`,
13
15
  "🔴": `Operation complete`,
14
- "❗": `Operation blocked`,
16
+ "đŸšĢ": `Operation blocked`,
15
17
  "đŸŸĸ": `Operation unblocked`,
16
18
  "🐞": `Possible bug in AtomIO`,
17
19
  "👀": `Subscription added`,
@@ -55,8 +57,7 @@ export type TokenDenomination =
55
57
  | `atom_family`
56
58
  | `atom`
57
59
  | `continuity`
58
- | `molecule_family`
59
- | `molecule`
60
+ | `key`
60
61
  | `mutable_atom_family`
61
62
  | `mutable_atom`
62
63
  | `readonly_held_selector_family`
@@ -72,6 +73,27 @@ export type TokenDenomination =
72
73
  | `writable_pure_selector_family`
73
74
  | `writable_pure_selector`
74
75
 
76
+ export const PRETTY_TOKEN_TYPES: Record<TokenDenomination, string> = {
77
+ atom_family: `atom family`,
78
+ atom: `atom`,
79
+ continuity: `continuity`,
80
+ key: `key`,
81
+ mutable_atom_family: `atom family [m]`,
82
+ mutable_atom: `atom [m]`,
83
+ readonly_held_selector_family: `selector family [h]`,
84
+ readonly_held_selector: `selector [h]`,
85
+ readonly_pure_selector_family: `selector family`,
86
+ readonly_pure_selector: `selector`,
87
+ state: `state`,
88
+ timeline: `timeline`,
89
+ transaction: `transaction`,
90
+ unknown: `unknown`,
91
+ writable_held_selector_family: `selector family [wh]`,
92
+ writable_held_selector: `selector [wh]`,
93
+ writable_pure_selector_family: `selector family [w]`,
94
+ writable_pure_selector: `selector [w]`,
95
+ }
96
+
75
97
  export const LOG_LEVELS = [`info`, `warn`, `error`] as const
76
98
  export type LogLevel = (typeof LOG_LEVELS)[number]
77
99
 
@@ -93,7 +115,7 @@ export const simpleLog =
93
115
  (icon, denomination, tokenKey, message, ...rest) => {
94
116
  /* eslint-disable-next-line no-console */
95
117
  console[logLevel](
96
- `${icon} ${denomination} "${tokenKey}" ${message}`,
118
+ `${icon} ${PRETTY_TOKEN_TYPES[denomination]} \`${tokenKey}\` ${message}`,
97
119
  ...rest,
98
120
  )
99
121
  }
@@ -1,7 +0,0 @@
1
- import type { AtomIOToken } from "atom.io"
2
-
3
- import { capitalize } from "./capitalize"
4
-
5
- export function prettyPrintTokenType(token: AtomIOToken): string {
6
- return token.type.split(`_`).map(capitalize).join(` `)
7
- }