atom.io 0.15.1 → 0.15.3
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.
- package/data/dist/index.cjs +28 -29
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +9 -9
- package/data/dist/index.js +28 -29
- package/data/dist/index.js.map +1 -1
- package/data/src/join.ts +41 -46
- package/dist/{chunk-S7R5MU6A.js → chunk-K22LR3V6.js} +3 -2
- package/dist/chunk-K22LR3V6.js.map +1 -0
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +1 -1
- package/internal/dist/index.cjs +110 -92
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +9 -6
- package/internal/dist/index.js +110 -92
- package/internal/dist/index.js.map +1 -1
- package/internal/src/caching.ts +9 -7
- package/internal/src/index.ts +5 -0
- package/internal/src/mutable/get-json-token.ts +1 -1
- package/internal/src/mutable/get-update-token.ts +1 -1
- package/internal/src/mutable/tracker.ts +35 -17
- package/internal/src/read-or-compute-value.ts +8 -12
- package/internal/src/set-state/copy-mutable-in-transaction.ts +4 -4
- package/internal/src/set-state/set-atom-or-selector.ts +7 -4
- package/internal/src/set-state/stow-update.ts +1 -1
- package/internal/src/transaction/apply-transaction.ts +1 -0
- package/package.json +6 -6
- package/react-devtools/dist/index.d.ts +2 -0
- package/realtime-react/dist/index.cjs +5 -2
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +2 -2
- package/realtime-react/dist/index.js +5 -2
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/realtime-context.tsx +6 -3
- package/realtime-react/src/use-pull-mutable-family-member.ts +1 -1
- package/src/index.ts +5 -0
- package/src/set-state.ts +3 -1
- package/transceivers/set-rtx/dist/index.cjs +8 -5
- package/transceivers/set-rtx/dist/index.cjs.map +1 -1
- package/transceivers/set-rtx/dist/index.js +8 -5
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/src/set-rtx.ts +8 -5
- package/dist/chunk-S7R5MU6A.js.map +0 -1
package/internal/src/caching.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { StateUpdate } from "atom.io"
|
|
1
|
+
import type { ReadableToken, StateUpdate } from "atom.io"
|
|
2
|
+
import type { StateNode } from "."
|
|
2
3
|
import { Future } from "./future"
|
|
3
|
-
import {
|
|
4
|
+
import { copyMutableIfWithinTransaction } from "./set-state/copy-mutable-in-transaction"
|
|
4
5
|
import type { Store } from "./store"
|
|
5
6
|
import type { Subject } from "./subject"
|
|
6
7
|
|
|
@@ -48,11 +49,12 @@ export function cacheValue<T>(
|
|
|
48
49
|
return value
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
export const readCachedValue = <T>(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
export const readCachedValue = <T>(token: StateNode<any>, target: Store): T => {
|
|
53
|
+
let value = target.valueMap.get(token.key) as T
|
|
54
|
+
if (token.type === `atom`) {
|
|
55
|
+
value = copyMutableIfWithinTransaction(value, token, target)
|
|
56
|
+
}
|
|
57
|
+
return value
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
export const evictCachedValue = (key: string, target: Store): void => {
|
package/internal/src/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { Atom } from "./atom"
|
|
2
|
+
import type { ReadonlySelector, Selector } from "./selector"
|
|
3
|
+
|
|
1
4
|
export * from "./atom"
|
|
2
5
|
export * from "./caching"
|
|
3
6
|
export * from "./lineage"
|
|
@@ -16,3 +19,5 @@ export * from "./subject"
|
|
|
16
19
|
export * from "./subscribe"
|
|
17
20
|
export * from "./timeline"
|
|
18
21
|
export * from "./transaction"
|
|
22
|
+
|
|
23
|
+
export type StateNode<T> = Atom<T> | ReadonlySelector<T> | Selector<T>
|
|
@@ -4,7 +4,7 @@ import type { Json } from "atom.io/json"
|
|
|
4
4
|
import type { Transceiver } from "./transceiver"
|
|
5
5
|
|
|
6
6
|
export const getJsonToken = <
|
|
7
|
-
Core extends Transceiver<
|
|
7
|
+
Core extends Transceiver<any>,
|
|
8
8
|
SerializableCore extends Json.Serializable,
|
|
9
9
|
>(
|
|
10
10
|
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
@@ -3,7 +3,7 @@ import type { Json } from "atom.io/json"
|
|
|
3
3
|
import type { Signal, Transceiver } from "./transceiver"
|
|
4
4
|
|
|
5
5
|
export const getUpdateToken = <
|
|
6
|
-
Core extends Transceiver<
|
|
6
|
+
Core extends Transceiver<any>,
|
|
7
7
|
SerializableCore extends Json.Serializable,
|
|
8
8
|
>(
|
|
9
9
|
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
@@ -46,7 +46,8 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
46
46
|
return latestUpdateState
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
private unsubscribeFromInnerValue: (
|
|
49
|
+
private unsubscribeFromInnerValue: () => void
|
|
50
|
+
private unsubscribeFromState: () => void
|
|
50
51
|
private observeCore(
|
|
51
52
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
52
53
|
latestUpdateState: AtomToken<typeof this.Update | null>,
|
|
@@ -61,20 +62,25 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
61
62
|
: target.transactionMeta.update.key
|
|
62
63
|
}`,
|
|
63
64
|
(update) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
if (target.operation.open) {
|
|
66
|
+
const unsubscribe = target.subject.operationStatus.subscribe(
|
|
67
|
+
mutableState.key,
|
|
68
|
+
() => {
|
|
69
|
+
unsubscribe()
|
|
70
|
+
setState(latestUpdateState, update, target)
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
} else {
|
|
74
|
+
setState(mutableState, (current) => current, target)
|
|
75
|
+
setState(latestUpdateState, update, target)
|
|
76
|
+
}
|
|
71
77
|
},
|
|
72
78
|
)
|
|
73
|
-
subscribeToState(
|
|
79
|
+
this.unsubscribeFromState = subscribeToState(
|
|
74
80
|
mutableState,
|
|
75
81
|
(update) => {
|
|
76
82
|
if (update.newValue !== update.oldValue) {
|
|
77
|
-
this.unsubscribeFromInnerValue
|
|
83
|
+
this.unsubscribeFromInnerValue()
|
|
78
84
|
const target = newest(store)
|
|
79
85
|
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
80
86
|
`tracker:${store.config.name}:${
|
|
@@ -83,13 +89,18 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
83
89
|
: target.transactionMeta.update.key
|
|
84
90
|
}`,
|
|
85
91
|
(update) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
if (target.operation.open) {
|
|
93
|
+
const unsubscribe = target.subject.operationStatus.subscribe(
|
|
94
|
+
mutableState.key,
|
|
95
|
+
() => {
|
|
96
|
+
unsubscribe()
|
|
97
|
+
setState(latestUpdateState, update, target)
|
|
98
|
+
},
|
|
99
|
+
)
|
|
100
|
+
} else {
|
|
101
|
+
setState(mutableState, (current) => current, target)
|
|
102
|
+
setState(latestUpdateState, update, target)
|
|
103
|
+
}
|
|
93
104
|
},
|
|
94
105
|
)
|
|
95
106
|
}
|
|
@@ -165,6 +176,8 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
165
176
|
public mutableState: MutableAtomToken<Mutable, Json.Serializable>
|
|
166
177
|
public latestUpdateState: AtomToken<typeof this.Update | null>
|
|
167
178
|
|
|
179
|
+
public dispose: () => void
|
|
180
|
+
|
|
168
181
|
public constructor(
|
|
169
182
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
170
183
|
store: Store,
|
|
@@ -175,5 +188,10 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
175
188
|
this.observeCore(mutableState, this.latestUpdateState, target)
|
|
176
189
|
this.updateCore(mutableState, this.latestUpdateState, target)
|
|
177
190
|
target.trackers.set(mutableState.key, this)
|
|
191
|
+
this.dispose = () => {
|
|
192
|
+
this.unsubscribeFromInnerValue()
|
|
193
|
+
this.unsubscribeFromState()
|
|
194
|
+
target.trackers.delete(mutableState.key)
|
|
195
|
+
}
|
|
178
196
|
}
|
|
179
197
|
}
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import type { ReadonlySelector, Selector } from "./selector"
|
|
1
|
+
import type { StateNode } from "."
|
|
2
|
+
import { readCachedValue } from "./caching"
|
|
4
3
|
import type { Store } from "./store"
|
|
5
4
|
|
|
6
|
-
export const readOrComputeValue = <T>(
|
|
7
|
-
state
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (isValueCached(state.key, store)) {
|
|
11
|
-
store.logger.info(`📖`, state.type, state.key, `reading cached value`)
|
|
12
|
-
return readCachedValue(state.key, store)
|
|
5
|
+
export const readOrComputeValue = <T>(state: StateNode<T>, target: Store): T => {
|
|
6
|
+
if (target.valueMap.has(state.key)) {
|
|
7
|
+
target.logger.info(`📖`, state.type, state.key, `reading cached value`)
|
|
8
|
+
return readCachedValue(state, target)
|
|
13
9
|
}
|
|
14
10
|
if (state.type !== `atom`) {
|
|
15
|
-
|
|
11
|
+
target.logger.info(`🧮`, state.type, state.key, `computing value`)
|
|
16
12
|
return state.get()
|
|
17
13
|
}
|
|
18
14
|
const fallback =
|
|
19
15
|
state.default instanceof Function ? state.default() : state.default
|
|
20
|
-
|
|
16
|
+
target.logger.info(
|
|
21
17
|
`💁`,
|
|
22
18
|
`atom`,
|
|
23
19
|
state.key,
|
|
@@ -13,10 +13,6 @@ export function copyMutableIfWithinTransaction<T>(
|
|
|
13
13
|
const target = newest(store)
|
|
14
14
|
const parent = target.parent
|
|
15
15
|
if (parent !== null) {
|
|
16
|
-
if (`toJson` in atom && `fromJson` in atom) {
|
|
17
|
-
const copiedValue = copyMutableIfNeeded(atom, atom, parent, target)
|
|
18
|
-
return copiedValue
|
|
19
|
-
}
|
|
20
16
|
if (`family` in atom) {
|
|
21
17
|
const family = parent.families.get(atom.family.key)
|
|
22
18
|
if (family && family.type === `atom_family`) {
|
|
@@ -31,6 +27,10 @@ export function copyMutableIfWithinTransaction<T>(
|
|
|
31
27
|
}
|
|
32
28
|
}
|
|
33
29
|
}
|
|
30
|
+
if (`toJson` in atom && `fromJson` in atom) {
|
|
31
|
+
const copiedValue = copyMutableIfNeeded(atom, atom, parent, target)
|
|
32
|
+
return copiedValue
|
|
33
|
+
}
|
|
34
34
|
}
|
|
35
35
|
return oldValue
|
|
36
36
|
}
|
|
@@ -8,9 +8,12 @@ export const setAtomOrSelector = <T>(
|
|
|
8
8
|
value: T | ((oldValue: T) => T),
|
|
9
9
|
store: Store,
|
|
10
10
|
): void => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
switch (state.type) {
|
|
12
|
+
case `atom`:
|
|
13
|
+
setAtom(state, value, store)
|
|
14
|
+
break
|
|
15
|
+
case `selector`:
|
|
16
|
+
state.set(value)
|
|
17
|
+
break
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -6,7 +6,7 @@ import { isTransceiver } from "../mutable"
|
|
|
6
6
|
import type { Store } from "../store"
|
|
7
7
|
|
|
8
8
|
function shouldUpdateBeStowed(key: string, update: StateUpdate<any>): boolean {
|
|
9
|
-
// do not stow updates that aren't json
|
|
9
|
+
// do not stow updates that aren't json
|
|
10
10
|
if (isTransceiver(update.newValue)) {
|
|
11
11
|
return false
|
|
12
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atom.io",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.3",
|
|
4
4
|
"description": "Composable and testable reactive data library.",
|
|
5
5
|
"homepage": "https://atom.io.fyi",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@emotion/react": "11.11.
|
|
51
|
+
"@emotion/react": "11.11.3",
|
|
52
52
|
"@testing-library/react": "14.1.2",
|
|
53
53
|
"@types/http-proxy": "1.17.14",
|
|
54
54
|
"@types/npmlog": "7.0.0",
|
|
55
|
-
"@types/react": "18.2.
|
|
55
|
+
"@types/react": "18.2.46",
|
|
56
56
|
"@types/tmp": "0.2.6",
|
|
57
57
|
"@vitest/coverage-v8": "1.1.0",
|
|
58
58
|
"@vitest/ui": "1.1.0",
|
|
59
59
|
"concurrently": "8.2.2",
|
|
60
|
-
"drizzle-kit": "0.20.
|
|
61
|
-
"drizzle-orm": "0.29.
|
|
60
|
+
"drizzle-kit": "0.20.9",
|
|
61
|
+
"drizzle-orm": "0.29.2",
|
|
62
62
|
"eslint": "8.56.0",
|
|
63
63
|
"framer-motion": "10.16.16",
|
|
64
64
|
"happy-dom": "12.10.3",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"tsup": "8.0.1",
|
|
76
76
|
"typescript": "5.3.3",
|
|
77
77
|
"vite": "5.0.10",
|
|
78
|
-
"vite-tsconfig-paths": "4.2.
|
|
78
|
+
"vite-tsconfig-paths": "4.2.3",
|
|
79
79
|
"vitest": "1.1.0"
|
|
80
80
|
},
|
|
81
81
|
"main": "dist/index.js",
|
|
@@ -177,10 +177,12 @@ declare class Tracker<Mutable extends Transceiver<any>> {
|
|
|
177
177
|
private Update;
|
|
178
178
|
private initializeState;
|
|
179
179
|
private unsubscribeFromInnerValue;
|
|
180
|
+
private unsubscribeFromState;
|
|
180
181
|
private observeCore;
|
|
181
182
|
private updateCore;
|
|
182
183
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>;
|
|
183
184
|
latestUpdateState: AtomToken<typeof this.Update | null>;
|
|
185
|
+
dispose: () => void;
|
|
184
186
|
constructor(mutableState: MutableAtomToken<Mutable, Json.Serializable>, store: Store);
|
|
185
187
|
}
|
|
186
188
|
|
|
@@ -35,10 +35,13 @@ var RealtimeContext = React6__namespace.createContext({
|
|
|
35
35
|
var RealtimeProvider = ({ children, socket }) => {
|
|
36
36
|
const setMyId = react.useI(RTC__namespace.myIdState__INTERNAL);
|
|
37
37
|
React6__namespace.useEffect(() => {
|
|
38
|
-
|
|
38
|
+
if (socket) {
|
|
39
|
+
setMyId(socket.id);
|
|
40
|
+
}
|
|
41
|
+
socket == null ? void 0 : socket.on(`connect`, () => {
|
|
39
42
|
setMyId(socket.id);
|
|
40
43
|
});
|
|
41
|
-
socket.on(`disconnect`, () => {
|
|
44
|
+
socket == null ? void 0 : socket.on(`disconnect`, () => {
|
|
42
45
|
setMyId(null);
|
|
43
46
|
});
|
|
44
47
|
}, [socket, setMyId]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-context.tsx","../src/use-pull.ts","../src/use-pull-family-member.ts","../src/use-pull-mutable.ts","../src/use-pull-mutable-family-member.ts","../src/use-push.ts","../src/use-server-action.ts"],"names":["RTC","React","StoreContext"],"mappings":";AAAA,SAAS,YAAY;AACrB,YAAY,SAAS;AACrB,YAAY,WAAW;
|
|
1
|
+
{"version":3,"sources":["../src/realtime-context.tsx","../src/use-pull.ts","../src/use-pull-family-member.ts","../src/use-pull-mutable.ts","../src/use-pull-mutable-family-member.ts","../src/use-push.ts","../src/use-server-action.ts"],"names":["RTC","React","StoreContext"],"mappings":"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","sourcesContent":["import { useI } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\nimport type { Socket } from \"socket.io-client\"\n\nexport const RealtimeContext = React.createContext<{ socket: Socket | null }>({\n\tsocket: null,\n})\n\nexport const RealtimeProvider: React.FC<{\n\tchildren: React.ReactNode\n\tsocket: Socket | null\n}> = ({ children, socket }) => {\n\tconst setMyId = useI(RTC.myIdState__INTERNAL)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\tsetMyId(socket.id)\n\t\t}\n\t\tsocket?.on(`connect`, () => {\n\t\t\tsetMyId(socket.id)\n\t\t})\n\t\tsocket?.on(`disconnect`, () => {\n\t\t\tsetMyId(null)\n\t\t})\n\t}, [socket, setMyId])\n\treturn (\n\t\t<RealtimeContext.Provider value={{ socket }}>\n\t\t\t{children}\n\t\t</RealtimeContext.Provider>\n\t)\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePull<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullState(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullFamilyMember(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullMutable<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(token: AtomIO.MutableAtomToken<T, J>): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullMutableState(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(token: AtomIO.MutableAtomToken<T, J>): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullMutableFamilyMember(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePush<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pushState(token, socket, `use-push:${id}`, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import * as AtomIO from \"atom.io\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function useServerAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n): (...parameters: Parameters<ƒ>) => ReturnType<ƒ> {\n\tconst store = React.useContext(StoreContext)\n\tconst { socket } = React.useContext(RealtimeContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.synchronizeTransactionResults(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n\treturn AtomIO.runTransaction(token, store)\n}\n"]}
|
|
@@ -9,7 +9,7 @@ declare const RealtimeContext: React.Context<{
|
|
|
9
9
|
}>;
|
|
10
10
|
declare const RealtimeProvider: React.FC<{
|
|
11
11
|
children: React.ReactNode;
|
|
12
|
-
socket: Socket;
|
|
12
|
+
socket: Socket | null;
|
|
13
13
|
}>;
|
|
14
14
|
|
|
15
15
|
declare function usePull<J extends Json.Serializable>(token: AtomIO.StateToken<J>): void;
|
|
@@ -18,7 +18,7 @@ declare function usePullFamilyMember<J extends Json.Serializable>(token: AtomIO.
|
|
|
18
18
|
|
|
19
19
|
declare function usePullMutable<T extends Transceiver<any>, J extends Json.Serializable>(token: AtomIO.MutableAtomToken<T, J>): void;
|
|
20
20
|
|
|
21
|
-
declare function usePullMutableFamilyMember<T extends Transceiver<
|
|
21
|
+
declare function usePullMutableFamilyMember<T extends Transceiver<any>, J extends Json.Serializable>(token: AtomIO.MutableAtomToken<T, J>): void;
|
|
22
22
|
|
|
23
23
|
declare function usePush<J extends Json.Serializable>(token: AtomIO.StateToken<J>): void;
|
|
24
24
|
|
|
@@ -11,10 +11,13 @@ var RealtimeContext = React6.createContext({
|
|
|
11
11
|
var RealtimeProvider = ({ children, socket }) => {
|
|
12
12
|
const setMyId = useI(RTC.myIdState__INTERNAL);
|
|
13
13
|
React6.useEffect(() => {
|
|
14
|
-
|
|
14
|
+
if (socket) {
|
|
15
|
+
setMyId(socket.id);
|
|
16
|
+
}
|
|
17
|
+
socket == null ? void 0 : socket.on(`connect`, () => {
|
|
15
18
|
setMyId(socket.id);
|
|
16
19
|
});
|
|
17
|
-
socket.on(`disconnect`, () => {
|
|
20
|
+
socket == null ? void 0 : socket.on(`disconnect`, () => {
|
|
18
21
|
setMyId(null);
|
|
19
22
|
});
|
|
20
23
|
}, [socket, setMyId]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-context.tsx","../src/use-pull.ts","../src/use-pull-family-member.ts","../src/use-pull-mutable.ts","../src/use-pull-mutable-family-member.ts","../src/use-push.ts","../src/use-server-action.ts"],"names":["RTC","React","StoreContext"],"mappings":";;;AAAA,SAAS,YAAY;AACrB,YAAY,SAAS;AACrB,YAAY,WAAW;
|
|
1
|
+
{"version":3,"sources":["../src/realtime-context.tsx","../src/use-pull.ts","../src/use-pull-family-member.ts","../src/use-pull-mutable.ts","../src/use-pull-mutable-family-member.ts","../src/use-push.ts","../src/use-server-action.ts"],"names":["RTC","React","StoreContext"],"mappings":"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","sourcesContent":["import { useI } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\nimport type { Socket } from \"socket.io-client\"\n\nexport const RealtimeContext = React.createContext<{ socket: Socket | null }>({\n\tsocket: null,\n})\n\nexport const RealtimeProvider: React.FC<{\n\tchildren: React.ReactNode\n\tsocket: Socket | null\n}> = ({ children, socket }) => {\n\tconst setMyId = useI(RTC.myIdState__INTERNAL)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\tsetMyId(socket.id)\n\t\t}\n\t\tsocket?.on(`connect`, () => {\n\t\t\tsetMyId(socket.id)\n\t\t})\n\t\tsocket?.on(`disconnect`, () => {\n\t\t\tsetMyId(null)\n\t\t})\n\t}, [socket, setMyId])\n\treturn (\n\t\t<RealtimeContext.Provider value={{ socket }}>\n\t\t\t{children}\n\t\t</RealtimeContext.Provider>\n\t)\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePull<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullState(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullFamilyMember(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullMutable<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(token: AtomIO.MutableAtomToken<T, J>): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullMutableState(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(token: AtomIO.MutableAtomToken<T, J>): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pullMutableFamilyMember(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function usePush<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n): void {\n\tconst { socket } = React.useContext(RealtimeContext)\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.pushState(token, socket, `use-push:${id}`, store)\n\t\t}\n\t}, [token.key, socket])\n}\n","import * as AtomIO from \"atom.io\"\nimport { StoreContext } from \"atom.io/react\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as React from \"react\"\n\nimport { RealtimeContext } from \"./realtime-context\"\n\nexport function useServerAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n): (...parameters: Parameters<ƒ>) => ReturnType<ƒ> {\n\tconst store = React.useContext(StoreContext)\n\tconst { socket } = React.useContext(RealtimeContext)\n\tReact.useEffect(() => {\n\t\tif (socket) {\n\t\t\treturn RTC.synchronizeTransactionResults(token, socket, store)\n\t\t}\n\t}, [token.key, socket])\n\treturn AtomIO.runTransaction(token, store)\n}\n"]}
|
|
@@ -9,14 +9,17 @@ export const RealtimeContext = React.createContext<{ socket: Socket | null }>({
|
|
|
9
9
|
|
|
10
10
|
export const RealtimeProvider: React.FC<{
|
|
11
11
|
children: React.ReactNode
|
|
12
|
-
socket: Socket
|
|
12
|
+
socket: Socket | null
|
|
13
13
|
}> = ({ children, socket }) => {
|
|
14
14
|
const setMyId = useI(RTC.myIdState__INTERNAL)
|
|
15
15
|
React.useEffect(() => {
|
|
16
|
-
|
|
16
|
+
if (socket) {
|
|
17
|
+
setMyId(socket.id)
|
|
18
|
+
}
|
|
19
|
+
socket?.on(`connect`, () => {
|
|
17
20
|
setMyId(socket.id)
|
|
18
21
|
})
|
|
19
|
-
socket
|
|
22
|
+
socket?.on(`disconnect`, () => {
|
|
20
23
|
setMyId(null)
|
|
21
24
|
})
|
|
22
25
|
}, [socket, setMyId])
|
|
@@ -8,7 +8,7 @@ import * as React from "react"
|
|
|
8
8
|
import { RealtimeContext } from "./realtime-context"
|
|
9
9
|
|
|
10
10
|
export function usePullMutableFamilyMember<
|
|
11
|
-
T extends Transceiver<
|
|
11
|
+
T extends Transceiver<any>,
|
|
12
12
|
J extends Json.Serializable,
|
|
13
13
|
>(token: AtomIO.MutableAtomToken<T, J>): void {
|
|
14
14
|
const { socket } = React.useContext(RealtimeContext)
|
package/src/index.ts
CHANGED
|
@@ -33,7 +33,12 @@ export type SelectorToken<_> = {
|
|
|
33
33
|
family?: FamilyMetadata
|
|
34
34
|
__brand?: _
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Prefer `WritableToken`.
|
|
38
|
+
*/
|
|
36
39
|
export type StateToken<T> = AtomToken<T> | SelectorToken<T>
|
|
40
|
+
export type WritableToken<T> = AtomToken<T> | SelectorToken<T>
|
|
41
|
+
export type ReadableToken<T> = ReadonlySelectorToken<T> | WritableToken<T>
|
|
37
42
|
|
|
38
43
|
export type ReadonlySelectorToken<_> = {
|
|
39
44
|
key: string
|
package/src/set-state.ts
CHANGED
|
@@ -11,7 +11,9 @@ export function setState<T, New extends T>(
|
|
|
11
11
|
if (rejection) {
|
|
12
12
|
return
|
|
13
13
|
}
|
|
14
|
-
const state =
|
|
14
|
+
const state =
|
|
15
|
+
Internal.withdraw(token, store) ??
|
|
16
|
+
Internal.withdrawNewFamilyMember(token, store)
|
|
15
17
|
if (state === undefined) {
|
|
16
18
|
throw new Internal.NotFoundError(token, store)
|
|
17
19
|
}
|
|
@@ -46,25 +46,28 @@ var SetRTX = class _SetRTX extends Set {
|
|
|
46
46
|
return set;
|
|
47
47
|
}
|
|
48
48
|
add(value) {
|
|
49
|
+
const result = super.add(value);
|
|
49
50
|
if (this.mode === `record`) {
|
|
50
51
|
this.cacheUpdateNumber++;
|
|
51
52
|
this.emit(`add:${json.stringifyJson(value)}`);
|
|
52
53
|
}
|
|
53
|
-
return
|
|
54
|
+
return result;
|
|
54
55
|
}
|
|
55
56
|
clear() {
|
|
56
|
-
|
|
57
|
+
const capturedContents = this.mode === `record` ? [...this] : null;
|
|
58
|
+
super.clear();
|
|
59
|
+
if (capturedContents) {
|
|
57
60
|
this.cacheUpdateNumber++;
|
|
58
|
-
this.emit(`clear:${JSON.stringify(
|
|
61
|
+
this.emit(`clear:${JSON.stringify(capturedContents)}`);
|
|
59
62
|
}
|
|
60
|
-
super.clear();
|
|
61
63
|
}
|
|
62
64
|
delete(value) {
|
|
65
|
+
const result = super.delete(value);
|
|
63
66
|
if (this.mode === `record`) {
|
|
64
67
|
this.cacheUpdateNumber++;
|
|
65
68
|
this.emit(`del:${json.stringifyJson(value)}`);
|
|
66
69
|
}
|
|
67
|
-
return
|
|
70
|
+
return result;
|
|
68
71
|
}
|
|
69
72
|
transaction(run) {
|
|
70
73
|
this.mode = `transaction`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/set-rtx.ts"],"names":["update","value"],"mappings":"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","sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, Stringified, primitive } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdate =\n\t| `add:${string}`\n\t| `clear:${string}`\n\t| `del:${string}`\n\t| `tx:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<NumberedSetUpdate>, Lineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.add(value)\n\t}\n\n\tpublic clear(): void {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify([...this])}`)\n\t\t}\n\t\tsuper.clear()\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.delete(value)\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\tconsole.error(`Failed to apply transaction to SetRTX: ${thrown}`)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) =>\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`),\n\t\t)\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak)\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const update of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(update as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdate): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst update = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!update) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(update)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint)\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const value of values) this.add(value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/set-rtx.ts"],"names":["update","value"],"mappings":"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","sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, Stringified, primitive } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdate =\n\t| `add:${string}`\n\t| `clear:${string}`\n\t| `del:${string}`\n\t| `tx:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<NumberedSetUpdate>, Lineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\tconsole.error(`Failed to apply transaction to SetRTX: ${thrown}`)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) =>\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`),\n\t\t)\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak)\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const update of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(update as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdate): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst update = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!update) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(update)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint)\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const value of values) this.add(value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"]}
|
|
@@ -44,25 +44,28 @@ var SetRTX = class _SetRTX extends Set {
|
|
|
44
44
|
return set;
|
|
45
45
|
}
|
|
46
46
|
add(value) {
|
|
47
|
+
const result = super.add(value);
|
|
47
48
|
if (this.mode === `record`) {
|
|
48
49
|
this.cacheUpdateNumber++;
|
|
49
50
|
this.emit(`add:${stringifyJson(value)}`);
|
|
50
51
|
}
|
|
51
|
-
return
|
|
52
|
+
return result;
|
|
52
53
|
}
|
|
53
54
|
clear() {
|
|
54
|
-
|
|
55
|
+
const capturedContents = this.mode === `record` ? [...this] : null;
|
|
56
|
+
super.clear();
|
|
57
|
+
if (capturedContents) {
|
|
55
58
|
this.cacheUpdateNumber++;
|
|
56
|
-
this.emit(`clear:${JSON.stringify(
|
|
59
|
+
this.emit(`clear:${JSON.stringify(capturedContents)}`);
|
|
57
60
|
}
|
|
58
|
-
super.clear();
|
|
59
61
|
}
|
|
60
62
|
delete(value) {
|
|
63
|
+
const result = super.delete(value);
|
|
61
64
|
if (this.mode === `record`) {
|
|
62
65
|
this.cacheUpdateNumber++;
|
|
63
66
|
this.emit(`del:${stringifyJson(value)}`);
|
|
64
67
|
}
|
|
65
|
-
return
|
|
68
|
+
return result;
|
|
66
69
|
}
|
|
67
70
|
transaction(run) {
|
|
68
71
|
this.mode = `transaction`;
|