atom.io 0.5.0 → 0.6.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 (87) hide show
  1. package/dist/index.d.mts +82 -66
  2. package/dist/index.d.ts +82 -66
  3. package/dist/index.js +482 -360
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +481 -360
  6. package/dist/index.mjs.map +1 -1
  7. package/json/dist/index.js.map +1 -1
  8. package/json/dist/index.mjs.map +1 -1
  9. package/package.json +12 -5
  10. package/react/dist/index.d.mts +18 -11
  11. package/react/dist/index.d.ts +18 -11
  12. package/react/dist/index.js +45 -21
  13. package/react/dist/index.js.map +1 -1
  14. package/react/dist/index.mjs +31 -21
  15. package/react/dist/index.mjs.map +1 -1
  16. package/react-devtools/dist/index.d.mts +4 -4
  17. package/react-devtools/dist/index.d.ts +4 -4
  18. package/react-devtools/dist/index.js.map +1 -1
  19. package/react-devtools/dist/index.mjs.map +1 -1
  20. package/realtime/dist/index.d.mts +3 -1
  21. package/realtime/dist/index.d.ts +3 -1
  22. package/realtime/dist/index.js +23 -0
  23. package/realtime/dist/index.js.map +1 -1
  24. package/realtime/dist/index.mjs +22 -0
  25. package/realtime/dist/index.mjs.map +1 -1
  26. package/realtime-react/dist/index.d.mts +45 -0
  27. package/realtime-react/dist/index.d.ts +45 -0
  28. package/realtime-react/dist/index.js +213 -0
  29. package/realtime-react/dist/index.js.map +1 -0
  30. package/realtime-react/dist/index.mjs +168 -0
  31. package/realtime-react/dist/index.mjs.map +1 -0
  32. package/realtime-react/package.json +15 -0
  33. package/src/index.ts +0 -6
  34. package/src/internal/get.ts +17 -3
  35. package/src/internal/index.ts +2 -0
  36. package/src/internal/meta/meta-state.ts +1 -1
  37. package/src/internal/operation.ts +3 -1
  38. package/src/internal/selector/create-read-write-selector.ts +62 -0
  39. package/src/internal/selector/create-readonly-selector.ts +52 -0
  40. package/src/internal/selector/index.ts +4 -0
  41. package/src/internal/selector/lookup-selector-sources.ts +16 -0
  42. package/src/internal/selector/register-selector.ts +57 -0
  43. package/src/internal/selector/trace-selector-atoms.ts +43 -0
  44. package/src/internal/selector/update-selector-atoms.ts +33 -0
  45. package/src/internal/selector-internal.ts +9 -207
  46. package/src/internal/store.ts +43 -16
  47. package/src/internal/subscribe-internal.ts +1 -1
  48. package/src/internal/time-travel-internal.ts +7 -7
  49. package/src/internal/timeline/add-atom-to-timeline.ts +164 -0
  50. package/src/internal/timeline/index.ts +1 -0
  51. package/src/internal/timeline-internal.ts +37 -156
  52. package/src/internal/transaction/abort-transaction.ts +12 -0
  53. package/src/internal/transaction/apply-transaction.ts +54 -0
  54. package/src/internal/transaction/build-transaction.ts +33 -0
  55. package/src/internal/transaction/index.ts +25 -0
  56. package/src/internal/transaction/redo-transaction.ts +23 -0
  57. package/src/internal/transaction/undo-transaction.ts +23 -0
  58. package/src/internal/transaction-internal.ts +14 -146
  59. package/src/react/index.ts +2 -46
  60. package/src/react/store-context.tsx +14 -0
  61. package/src/react/store-hooks.ts +48 -0
  62. package/src/react-devtools/AtomIODevtools.tsx +1 -1
  63. package/src/react-explorer/AtomIOExplorer.tsx +2 -2
  64. package/src/react-explorer/space-states.ts +2 -2
  65. package/src/realtime/README.md +33 -0
  66. package/src/realtime/hook-composition/index.ts +1 -0
  67. package/src/realtime/hook-composition/receive-state.ts +29 -0
  68. package/src/realtime/hook-composition/receive-transaction.ts +2 -3
  69. package/src/realtime-react/index.ts +3 -0
  70. package/src/realtime-react/realtime-context.tsx +31 -0
  71. package/src/realtime-react/realtime-hooks.ts +39 -0
  72. package/src/realtime-react/realtime-state.ts +10 -0
  73. package/src/realtime-react/use-pull-family-member.ts +27 -0
  74. package/src/realtime-react/use-pull-family.ts +25 -0
  75. package/src/realtime-react/use-pull.ts +23 -0
  76. package/src/realtime-react/use-push.ts +26 -0
  77. package/src/realtime-react/use-server-action.ts +34 -0
  78. package/src/silo.ts +12 -4
  79. package/src/subscribe.ts +30 -2
  80. package/src/timeline.ts +10 -0
  81. package/src/transaction.ts +15 -10
  82. package/src/realtime-client/hook-composition/compose-realtime-hooks.ts +0 -62
  83. package/src/realtime-client/hook-composition/realtime-client-family-member.ts +0 -28
  84. package/src/realtime-client/hook-composition/realtime-client-family.ts +0 -26
  85. package/src/realtime-client/hook-composition/realtime-client-single.ts +0 -24
  86. package/src/realtime-client/hook-composition/realtime-client-transaction.ts +0 -35
  87. package/src/realtime-client/index.ts +0 -1
@@ -0,0 +1,168 @@
1
+ // ../src/realtime-react/realtime-context.tsx
2
+ import * as React from "react";
3
+ import * as AR from "atom.io/react";
4
+ import { io } from "socket.io-client";
5
+
6
+ // ../src/realtime-react/realtime-state.ts
7
+ import * as AtomIO from "atom.io";
8
+ var myIdState__INTERNAL = AtomIO.atom({
9
+ key: `myId__INTERNAL`,
10
+ default: null
11
+ });
12
+ var myIdState = AtomIO.selector({
13
+ key: `myId`,
14
+ get: ({ get }) => get(myIdState__INTERNAL)
15
+ });
16
+
17
+ // ../src/realtime-react/realtime-context.tsx
18
+ import { jsx } from "@emotion/react/jsx-runtime";
19
+ var RealtimeContext = React.createContext({
20
+ socket: io()
21
+ });
22
+ var RealtimeProvider = ({ children, socket }) => {
23
+ const setMyId = AR.useI(myIdState__INTERNAL);
24
+ React.useEffect(() => {
25
+ socket.on(`connect`, () => {
26
+ setMyId(socket.id);
27
+ });
28
+ socket.on(`disconnect`, () => {
29
+ setMyId(null);
30
+ });
31
+ }, [socket, setMyId]);
32
+ return /* @__PURE__ */ jsx(RealtimeContext.Provider, { value: { socket }, children });
33
+ };
34
+
35
+ // ../src/realtime-react/use-pull.ts
36
+ import * as React3 from "react";
37
+ import * as AtomIO3 from "atom.io";
38
+
39
+ // ../src/react/store-context.tsx
40
+ import * as React2 from "react";
41
+ import * as AtomIO2 from "atom.io";
42
+ import { jsx as jsx2 } from "@emotion/react/jsx-runtime";
43
+ var StoreContext = React2.createContext(
44
+ AtomIO2.__INTERNAL__.IMPLICIT.STORE
45
+ );
46
+
47
+ // ../src/realtime-react/use-pull.ts
48
+ function usePull(token) {
49
+ const { socket } = React3.useContext(RealtimeContext);
50
+ const store = React3.useContext(StoreContext);
51
+ React3.useEffect(() => {
52
+ socket.on(`serve:${token.key}`, (data) => {
53
+ AtomIO3.setState(token, data, store);
54
+ });
55
+ socket.emit(`sub:${token.key}`);
56
+ return () => {
57
+ socket.off(`serve:${token.key}`);
58
+ socket.emit(`unsub:${token.key}`);
59
+ };
60
+ }, [token.key]);
61
+ }
62
+
63
+ // ../src/realtime-react/use-pull-family.ts
64
+ import * as React4 from "react";
65
+ import * as AtomIO4 from "atom.io";
66
+ function usePullFamily(family) {
67
+ const { socket } = React4.useContext(RealtimeContext);
68
+ const store = React4.useContext(StoreContext);
69
+ React4.useEffect(() => {
70
+ socket.on(`serve:${family.key}`, (key, data) => {
71
+ AtomIO4.setState(family(key), data, store);
72
+ });
73
+ socket == null ? void 0 : socket.emit(`sub:${family.key}`);
74
+ return () => {
75
+ socket == null ? void 0 : socket.off(`serve:${family.key}`);
76
+ socket == null ? void 0 : socket.emit(`unsub:${family.key}`);
77
+ };
78
+ }, [family.key]);
79
+ }
80
+
81
+ // ../src/realtime-react/use-pull-family-member.ts
82
+ import * as React5 from "react";
83
+ import * as AtomIO5 from "atom.io";
84
+ function usePullFamilyMember(family, subKey) {
85
+ const token = family(subKey);
86
+ const { socket } = React5.useContext(RealtimeContext);
87
+ const store = React5.useContext(StoreContext);
88
+ React5.useEffect(() => {
89
+ socket == null ? void 0 : socket.on(`serve:${token.key}`, (data) => {
90
+ AtomIO5.setState(family(subKey), data, store);
91
+ });
92
+ socket == null ? void 0 : socket.emit(`sub:${family.key}`, subKey);
93
+ return () => {
94
+ socket == null ? void 0 : socket.off(`serve:${token.key}`);
95
+ socket == null ? void 0 : socket.emit(`unsub:${token.key}`);
96
+ };
97
+ }, [family.key]);
98
+ }
99
+
100
+ // ../src/realtime-react/use-push.ts
101
+ import * as React6 from "react";
102
+ import * as AtomIO6 from "atom.io";
103
+ function usePush(token) {
104
+ const { socket } = React6.useContext(RealtimeContext);
105
+ const store = React6.useContext(StoreContext);
106
+ React6.useEffect(() => {
107
+ socket.emit(`claim:${token.key}`);
108
+ AtomIO6.subscribe(
109
+ token,
110
+ ({ newValue }) => {
111
+ socket.emit(`pub:${token.key}`, newValue);
112
+ },
113
+ store
114
+ );
115
+ return () => {
116
+ socket.emit(`unclaim:${token.key}`);
117
+ };
118
+ }, [token.key]);
119
+ }
120
+
121
+ // ../src/realtime-react/use-server-action.ts
122
+ import * as React7 from "react";
123
+ import * as AtomIO7 from "atom.io";
124
+ import { StoreContext as StoreContext2 } from "atom.io/react";
125
+ var TX_SUBS = /* @__PURE__ */ new Map();
126
+ function useServerAction(token) {
127
+ const store = React7.useContext(StoreContext2);
128
+ const { socket } = React7.useContext(RealtimeContext);
129
+ React7.useEffect(() => {
130
+ var _a;
131
+ const count = (_a = TX_SUBS.get(token.key)) != null ? _a : 0;
132
+ TX_SUBS.set(token.key, count + 1);
133
+ const unsubscribe = count === 0 ? AtomIO7.subscribeToTransaction(
134
+ token,
135
+ (update) => socket.emit(`tx:${token.key}`, update),
136
+ store
137
+ ) : () => null;
138
+ return () => {
139
+ var _a2;
140
+ const newCount = (_a2 = TX_SUBS.get(token.key)) != null ? _a2 : 0;
141
+ TX_SUBS.set(token.key, newCount - 1);
142
+ unsubscribe();
143
+ };
144
+ }, [token.key]);
145
+ return AtomIO7.runTransaction(token, store);
146
+ }
147
+
148
+ // ../src/realtime-react/realtime-hooks.ts
149
+ var realtimeHooks = {
150
+ usePull,
151
+ usePullFamily,
152
+ usePullFamilyMember,
153
+ usePush,
154
+ useServerAction
155
+ };
156
+ export {
157
+ RealtimeContext,
158
+ RealtimeProvider,
159
+ myIdState,
160
+ myIdState__INTERNAL,
161
+ realtimeHooks,
162
+ usePull,
163
+ usePullFamily,
164
+ usePullFamilyMember,
165
+ usePush,
166
+ useServerAction
167
+ };
168
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/realtime-react/realtime-context.tsx","../../src/realtime-react/realtime-state.ts","../../src/realtime-react/use-pull.ts","../../src/react/store-context.tsx","../../src/realtime-react/use-pull-family.ts","../../src/realtime-react/use-pull-family-member.ts","../../src/realtime-react/use-push.ts","../../src/realtime-react/use-server-action.ts","../../src/realtime-react/realtime-hooks.ts"],"sourcesContent":["import * as React from \"react\"\n\nimport * as AR from \"atom.io/react\"\nimport type { Socket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nimport { myIdState__INTERNAL } from \"./realtime-state\"\n\nexport const RealtimeContext = React.createContext<{ socket: Socket }>({\n socket: io(),\n})\n\nexport const RealtimeProvider: React.FC<{\n children: React.ReactNode\n socket: Socket\n}> = ({ children, socket }) => {\n const setMyId = AR.useI(myIdState__INTERNAL)\n React.useEffect(() => {\n socket.on(`connect`, () => {\n setMyId(socket.id)\n })\n socket.on(`disconnect`, () => {\n setMyId(null)\n })\n }, [socket, setMyId])\n return (\n <RealtimeContext.Provider value={{ socket }}>\n {children}\n </RealtimeContext.Provider>\n )\n}\n","import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | null>({\n key: `myId__INTERNAL`,\n default: null,\n})\nexport const myIdState = AtomIO.selector<string | null>({\n key: `myId`,\n get: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\n\nimport type { Json } from \"~/packages/anvl/src/json\"\n\nimport { RealtimeContext } from \"./realtime-context\"\nimport { StoreContext } from \"../react\"\n\nexport function usePull<J extends Json>(token: AtomIO.StateToken<J>): void {\n const { socket } = React.useContext(RealtimeContext)\n const store = React.useContext(StoreContext)\n React.useEffect(() => {\n socket.on(`serve:${token.key}`, (data: J) => {\n AtomIO.setState(token, data, store)\n })\n socket.emit(`sub:${token.key}`)\n return () => {\n socket.off(`serve:${token.key}`)\n socket.emit(`unsub:${token.key}`)\n }\n }, [token.key])\n}\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\n\nexport const StoreContext = React.createContext<AtomIO.Store>(\n AtomIO.__INTERNAL__.IMPLICIT.STORE\n)\n\nexport const StoreProvider: React.FC<{\n children: React.ReactNode\n store?: AtomIO.Store\n}> = ({ children, store = AtomIO.__INTERNAL__.IMPLICIT.STORE }) => (\n <StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n)\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\n\nimport type { Json } from \"~/packages/anvl/src/json\"\n\nimport { RealtimeContext } from \"./realtime-context\"\nimport { StoreContext } from \"../react\"\n\nexport function usePullFamily<J extends Json>(\n family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>\n): void {\n const { socket } = React.useContext(RealtimeContext)\n const store = React.useContext(StoreContext)\n React.useEffect(() => {\n socket.on(`serve:${family.key}`, (key: Json, data: J) => {\n AtomIO.setState(family(key), data, store)\n })\n socket?.emit(`sub:${family.key}`)\n return () => {\n socket?.off(`serve:${family.key}`)\n socket?.emit(`unsub:${family.key}`)\n }\n }, [family.key])\n}\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\n\nimport type { Json } from \"~/packages/anvl/src/json\"\n\nimport { RealtimeContext } from \"./realtime-context\"\nimport { StoreContext } from \"../react\"\n\nexport function usePullFamilyMember<J extends Json>(\n family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,\n subKey: AtomIO.Serializable\n): void {\n const token = family(subKey)\n const { socket } = React.useContext(RealtimeContext)\n const store = React.useContext(StoreContext)\n React.useEffect(() => {\n socket?.on(`serve:${token.key}`, (data: J) => {\n AtomIO.setState(family(subKey), data, store)\n })\n socket?.emit(`sub:${family.key}`, subKey)\n return () => {\n socket?.off(`serve:${token.key}`)\n socket?.emit(`unsub:${token.key}`)\n }\n }, [family.key])\n}\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\n\nimport type { Json } from \"~/packages/anvl/src/json\"\n\nimport { RealtimeContext } from \"./realtime-context\"\nimport { StoreContext } from \"../react\"\n\nexport function usePush<J extends Json>(token: AtomIO.StateToken<J>): void {\n const { socket } = React.useContext(RealtimeContext)\n const store = React.useContext(StoreContext)\n React.useEffect(() => {\n socket.emit(`claim:${token.key}`)\n AtomIO.subscribe(\n token,\n ({ newValue }) => {\n socket.emit(`pub:${token.key}`, newValue)\n },\n store\n )\n return () => {\n socket.emit(`unclaim:${token.key}`)\n }\n }, [token.key])\n}\n","import * as React from \"react\"\n\nimport * as AtomIO from \"atom.io\"\nimport { StoreContext } from \"atom.io/react\"\n\nimport type { ƒn } from \"~/packages/anvl/src/function\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nconst TX_SUBS = new Map<string, number>()\nexport function useServerAction<ƒ extends ƒn>(\n token: AtomIO.TransactionToken<ƒ>\n): (...parameters: Parameters<ƒ>) => ReturnType<ƒ> {\n const store = React.useContext(StoreContext)\n const { socket } = React.useContext(RealtimeContext)\n React.useEffect(() => {\n const count = TX_SUBS.get(token.key) ?? 0\n TX_SUBS.set(token.key, count + 1)\n const unsubscribe =\n count === 0\n ? AtomIO.subscribeToTransaction(\n token,\n (update) => socket.emit(`tx:${token.key}`, update),\n store\n )\n : () => null\n return () => {\n const newCount = TX_SUBS.get(token.key) ?? 0\n TX_SUBS.set(token.key, newCount - 1)\n unsubscribe()\n }\n }, [token.key])\n return AtomIO.runTransaction(token, store)\n}\n","import type * as AtomIO from \"atom.io\"\n\nimport type { ƒn } from \"~/packages/anvl/src/function\"\nimport type { Json } from \"~/packages/anvl/src/json\"\n\nimport { usePull } from \"./use-pull\"\nimport { usePullFamily } from \"./use-pull-family\"\nimport { usePullFamilyMember } from \"./use-pull-family-member\"\nimport { usePush } from \"./use-push\"\nimport { useServerAction } from \"./use-server-action\"\n\nexport type RealtimeHooks = {\n usePull: <J extends Json>(token: AtomIO.StateToken<J>) => void\n usePullFamily: <J extends Json>(\n family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>\n ) => void\n usePullFamilyMember: <J extends Json>(\n family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,\n subKey: string\n ) => void\n usePush: <J extends Json>(token: AtomIO.StateToken<J>) => void\n useServerAction: <ƒ extends ƒn>(\n token: AtomIO.TransactionToken<ƒ>\n ) => (...parameters: Parameters<ƒ>) => ReturnType<ƒ>\n}\n\nexport const realtimeHooks: RealtimeHooks = {\n usePull,\n usePullFamily,\n usePullFamilyMember,\n usePush,\n useServerAction,\n}\n\nexport * from \"./use-pull\"\nexport * from \"./use-pull-family\"\nexport * from \"./use-pull-family-member\"\nexport * from \"./use-push\"\nexport * from \"./use-server-action\"\n"],"mappings":"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","names":["React","AtomIO","React","AtomIO","jsx","React","AtomIO","React","AtomIO","React","AtomIO","React","AtomIO","StoreContext","StoreContext","_a"]}
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "atom.io-realtime-react",
3
+ "private": true,
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "browser": "./dist/index.mjs",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ }
15
+ }
package/src/index.ts CHANGED
@@ -50,12 +50,6 @@ export type FamilyMetadata = {
50
50
  subKey: string
51
51
  }
52
52
 
53
- export type TransactionToken<_> = {
54
- key: string
55
- type: `transaction`
56
- __brand?: _
57
- }
58
-
59
53
  export const getState = <T>(
60
54
  token: ReadonlySelectorToken<T> | StateToken<T>,
61
55
  store: Store = IMPLICIT.STORE
@@ -2,14 +2,21 @@ import HAMT from "hamt_plus"
2
2
 
3
3
  import type { ƒn } from "~/packages/anvl/src/function"
4
4
 
5
- import type { Atom, ReadonlySelector, Selector, Store } from "."
5
+ import type {
6
+ Atom,
7
+ ReadonlySelector,
8
+ Selector,
9
+ Store,
10
+ Timeline,
11
+ Transaction,
12
+ } from "."
6
13
  import { target, isValueCached, readCachedValue, IMPLICIT } from "."
7
14
  import type {
8
15
  AtomToken,
9
16
  ReadonlySelectorToken,
10
17
  SelectorToken,
11
18
  StateToken,
12
- Transaction,
19
+ TimelineToken,
13
20
  TransactionToken,
14
21
  } from ".."
15
22
 
@@ -51,13 +58,19 @@ export function withdraw<T>(
51
58
  token: ReadonlySelectorToken<T> | StateToken<T>,
52
59
  store: Store
53
60
  ): Atom<T> | ReadonlySelector<T> | Selector<T> | null
61
+ export function withdraw<T>(token: TimelineToken, store: Store): Timeline | null
54
62
  export function withdraw<T>(
55
- token: ReadonlySelectorToken<T> | StateToken<T> | TransactionToken<T>,
63
+ token:
64
+ | ReadonlySelectorToken<T>
65
+ | StateToken<T>
66
+ | TimelineToken
67
+ | TransactionToken<T>,
56
68
  store: Store
57
69
  ):
58
70
  | Atom<T>
59
71
  | ReadonlySelector<T>
60
72
  | Selector<T>
73
+ | Timeline
61
74
  | Transaction<T extends ƒn ? T : never>
62
75
  | null {
63
76
  const core = target(store)
@@ -66,6 +79,7 @@ export function withdraw<T>(
66
79
  HAMT.get(token.key, core.selectors) ??
67
80
  HAMT.get(token.key, core.readonlySelectors) ??
68
81
  HAMT.get(token.key, core.transactions) ??
82
+ HAMT.get(token.key, core.timelines) ??
69
83
  null
70
84
  )
71
85
  }
@@ -5,9 +5,11 @@ export * from "./is-default"
5
5
  export * as META from "./meta"
6
6
  export * from "./operation"
7
7
  export * from "./selector-internal"
8
+ export * from "./selector"
8
9
  export * from "./set"
9
10
  export * from "./store"
10
11
  export * from "./subscribe-internal"
11
12
  export * from "./time-travel-internal"
12
13
  export * from "./timeline-internal"
13
14
  export * from "./transaction-internal"
15
+ export * from "./transaction"
@@ -7,7 +7,7 @@ export type StateTokenIndex<
7
7
  Token extends
8
8
  | AtomToken<unknown>
9
9
  | ReadonlySelectorToken<unknown>
10
- | SelectorToken<unknown>
10
+ | SelectorToken<unknown>,
11
11
  > = Record<
12
12
  string,
13
13
  | Token
@@ -34,7 +34,9 @@ export const openOperation = (token: StateToken<any>, store: Store): void => {
34
34
  time: Date.now(),
35
35
  token,
36
36
  }
37
- store.config.logger?.info(`⭕ operation start from "${token.key}"`)
37
+ store.config.logger?.info(
38
+ `⭕ operation start from "${token.key}" in store "${store.config.name}"`
39
+ )
38
40
  }
39
41
  export const closeOperation = (store: Store): void => {
40
42
  const core = target(store)
@@ -0,0 +1,62 @@
1
+ import HAMT from "hamt_plus"
2
+ import * as Rx from "rxjs"
3
+
4
+ import { become } from "~/packages/anvl/src/function"
5
+
6
+ import {
7
+ type Store,
8
+ type Selector,
9
+ type StoreCore,
10
+ registerSelector,
11
+ selector__INTERNAL,
12
+ } from ".."
13
+ import type { FamilyMetadata, SelectorToken } from "../.."
14
+ import type { SelectorOptions } from "../../selector"
15
+ import { cacheValue, markDone } from "../operation"
16
+
17
+ export const createReadWriteSelector = <T>(
18
+ options: SelectorOptions<T>,
19
+ family: FamilyMetadata | undefined,
20
+ store: Store,
21
+ core: StoreCore
22
+ ): SelectorToken<T> => {
23
+ const subject = new Rx.Subject<{ newValue: T; oldValue: T }>()
24
+
25
+ const { get, set } = registerSelector(options.key, store)
26
+ const getSelf = () => {
27
+ const value = options.get({ get })
28
+ cacheValue(options.key, value, store)
29
+ return value
30
+ }
31
+
32
+ const setSelf = (next: T | ((oldValue: T) => T)): void => {
33
+ store.config.logger?.info(` <- "${options.key}" became`, next)
34
+ const oldValue = getSelf()
35
+ const newValue = become(next)(oldValue)
36
+ cacheValue(options.key, newValue, store)
37
+ markDone(options.key, store)
38
+ if (store.transactionStatus.phase === `idle`) {
39
+ subject.next({ newValue, oldValue })
40
+ }
41
+ options.set({ get, set }, newValue)
42
+ }
43
+ const mySelector: Selector<T> = {
44
+ ...options,
45
+ subject,
46
+ install: (s: Store) => selector__INTERNAL(options, family, s),
47
+ get: getSelf,
48
+ set: setSelf,
49
+ type: `selector`,
50
+ ...(family && { family }),
51
+ }
52
+ core.selectors = HAMT.set(options.key, mySelector, core.selectors)
53
+ const initialValue = getSelf()
54
+ store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
55
+ const token: SelectorToken<T> = {
56
+ key: options.key,
57
+ type: `selector`,
58
+ family,
59
+ }
60
+ store.subject.selectorCreation.next(token)
61
+ return token
62
+ }
@@ -0,0 +1,52 @@
1
+ import HAMT from "hamt_plus"
2
+ import * as Rx from "rxjs"
3
+
4
+ import { registerSelector } from "./register-selector"
5
+ import type {
6
+ FamilyMetadata,
7
+ ReadonlySelectorOptions,
8
+ ReadonlySelectorToken,
9
+ Store,
10
+ } from "../.."
11
+ import { cacheValue } from "../operation"
12
+ import { selector__INTERNAL, type ReadonlySelector } from "../selector-internal"
13
+ import type { StoreCore } from "../store"
14
+
15
+ export const createReadonlySelector = <T>(
16
+ options: ReadonlySelectorOptions<T>,
17
+ family: FamilyMetadata | undefined,
18
+ store: Store,
19
+ core: StoreCore
20
+ ): ReadonlySelectorToken<T> => {
21
+ const subject = new Rx.Subject<{ newValue: T; oldValue: T }>()
22
+
23
+ const { get } = registerSelector(options.key, store)
24
+ const getSelf = () => {
25
+ const value = options.get({ get })
26
+ cacheValue(options.key, value, store)
27
+ return value
28
+ }
29
+
30
+ const readonlySelector: ReadonlySelector<T> = {
31
+ ...options,
32
+ subject,
33
+ install: (s: Store) => selector__INTERNAL(options, family, s),
34
+ get: getSelf,
35
+ type: `readonly_selector`,
36
+ ...(family && { family }),
37
+ }
38
+ core.readonlySelectors = HAMT.set(
39
+ options.key,
40
+ readonlySelector,
41
+ core.readonlySelectors
42
+ )
43
+ const initialValue = getSelf()
44
+ store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
45
+ const token: ReadonlySelectorToken<T> = {
46
+ key: options.key,
47
+ type: `readonly_selector`,
48
+ family,
49
+ }
50
+ store.subject.selectorCreation.next(token)
51
+ return token
52
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./lookup-selector-sources"
2
+ export * from "./register-selector"
3
+ export * from "./trace-selector-atoms"
4
+ export * from "./update-selector-atoms"
@@ -0,0 +1,16 @@
1
+ import type { Store } from ".."
2
+ import { target, lookup } from ".."
3
+ import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "../.."
4
+
5
+ export const lookupSelectorSources = (
6
+ key: string,
7
+ store: Store
8
+ ): (
9
+ | AtomToken<unknown>
10
+ | ReadonlySelectorToken<unknown>
11
+ | SelectorToken<unknown>
12
+ )[] =>
13
+ target(store)
14
+ .selectorGraph.getRelations(key)
15
+ .filter(({ source }) => source !== key)
16
+ .map(({ source }) => lookup(source, store))
@@ -0,0 +1,57 @@
1
+ import { updateSelectorAtoms } from "./update-selector-atoms"
2
+ import type { Transactors } from "../../transaction"
3
+ import { getState__INTERNAL, withdraw } from "../get"
4
+ import { setState__INTERNAL } from "../set"
5
+ import type { Store } from "../store"
6
+ import { IMPLICIT } from "../store"
7
+ import { target } from "../transaction-internal"
8
+
9
+ export const registerSelector = (
10
+ selectorKey: string,
11
+ store: Store = IMPLICIT.STORE
12
+ ): Transactors => ({
13
+ get: (dependency) => {
14
+ const core = target(store)
15
+ const alreadyRegistered = core.selectorGraph
16
+ .getRelations(selectorKey)
17
+ .some(({ source }) => source === dependency.key)
18
+
19
+ const dependencyState = withdraw(dependency, store)
20
+ if (dependencyState === null) {
21
+ throw new Error(
22
+ `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
23
+ )
24
+ }
25
+ const dependencyValue = getState__INTERNAL(dependencyState, store)
26
+
27
+ if (alreadyRegistered) {
28
+ store.config.logger?.info(
29
+ ` || ${selectorKey} <- ${dependency.key} =`,
30
+ dependencyValue
31
+ )
32
+ } else {
33
+ store.config.logger?.info(
34
+ `🔌 registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
35
+ dependencyValue,
36
+ `)`
37
+ )
38
+ core.selectorGraph = core.selectorGraph.set(
39
+ { from: dependency.key, to: selectorKey },
40
+ {
41
+ source: dependency.key,
42
+ }
43
+ )
44
+ }
45
+ updateSelectorAtoms(selectorKey, dependency, store)
46
+ return dependencyValue
47
+ },
48
+ set: (stateToken, newValue) => {
49
+ const state = withdraw(stateToken, store)
50
+ if (state === null) {
51
+ throw new Error(
52
+ `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
53
+ )
54
+ }
55
+ setState__INTERNAL(state, newValue, store)
56
+ },
57
+ })
@@ -0,0 +1,43 @@
1
+ import { lookupSelectorSources } from "./lookup-selector-sources"
2
+ import type { Store, AtomToken, ReadonlySelectorToken, StateToken } from "../.."
3
+
4
+ export const traceSelectorAtoms = (
5
+ selectorKey: string,
6
+ dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
7
+ store: Store
8
+ ): AtomToken<unknown>[] => {
9
+ const roots: AtomToken<unknown>[] = []
10
+
11
+ const sources = lookupSelectorSources(dependency.key, store)
12
+ let depth = 0
13
+ while (sources.length > 0) {
14
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
15
+ const source = sources.shift()!
16
+ ++depth
17
+ if (depth > 999) {
18
+ throw new Error(
19
+ `Maximum selector dependency depth exceeded in selector "${selectorKey}".`
20
+ )
21
+ }
22
+
23
+ if (source.type !== `atom`) {
24
+ sources.push(...lookupSelectorSources(source.key, store))
25
+ } else {
26
+ roots.push(source)
27
+ }
28
+ }
29
+
30
+ return roots
31
+ }
32
+
33
+ export const traceAllSelectorAtoms = (
34
+ selectorKey: string,
35
+ store: Store
36
+ ): AtomToken<unknown>[] => {
37
+ const sources = lookupSelectorSources(selectorKey, store)
38
+ return sources.flatMap((source) =>
39
+ source.type === `atom`
40
+ ? source
41
+ : traceSelectorAtoms(selectorKey, source, store)
42
+ )
43
+ }
@@ -0,0 +1,33 @@
1
+ import { traceSelectorAtoms } from "./trace-selector-atoms"
2
+ import type { Store } from ".."
3
+ import { target } from ".."
4
+ import type { ReadonlySelectorToken, StateToken } from "../.."
5
+
6
+ export const updateSelectorAtoms = (
7
+ selectorKey: string,
8
+ dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
9
+ store: Store
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
+ }
33
+ }