atom.io 0.10.1 → 0.10.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/dist/index.d.mts +53 -8
- package/dist/index.d.ts +53 -8
- package/dist/index.js +64 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -33
- package/dist/index.mjs.map +1 -1
- package/internal/dist/index.js +251 -110
- package/internal/dist/index.js.map +1 -1
- package/internal/dist/index.mjs +251 -110
- package/internal/dist/index.mjs.map +1 -1
- package/internal/src/atom/create-atom.ts +15 -4
- package/internal/src/atom/delete-atom.ts +1 -1
- package/internal/src/caching.ts +4 -4
- package/internal/src/get-state-internal.ts +3 -5
- package/internal/src/mutable/create-mutable-atom.ts +4 -10
- package/internal/src/operation.ts +23 -4
- package/internal/src/selector/create-read-write-selector.ts +12 -2
- package/internal/src/selector/create-readonly-selector.ts +7 -1
- package/internal/src/selector/create-selector.ts +4 -5
- package/internal/src/selector/register-selector.ts +7 -1
- package/internal/src/selector/update-selector-atoms.ts +10 -3
- package/internal/src/set-state/copy-mutable-if-needed.ts +1 -1
- package/internal/src/set-state/copy-mutable-in-transaction.ts +0 -3
- package/internal/src/set-state/emit-update.ts +6 -3
- package/internal/src/set-state/evict-downstream.ts +15 -14
- package/internal/src/set-state/set-atom.ts +1 -1
- package/internal/src/set-state/stow-update.ts +9 -4
- package/internal/src/store/store.ts +8 -19
- package/internal/src/store/withdraw-new-family-member.ts +4 -1
- package/internal/src/store/withdraw.ts +6 -1
- package/internal/src/subscribe/recall-state.ts +4 -1
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +11 -5
- package/internal/src/timeline/add-atom-to-timeline.ts +40 -9
- package/internal/src/timeline/time-travel-internal.ts +26 -8
- package/internal/src/timeline/timeline-internal.ts +8 -2
- package/internal/src/transaction/abort-transaction.ts +10 -2
- package/internal/src/transaction/apply-transaction.ts +22 -5
- package/internal/src/transaction/build-transaction.ts +5 -1
- package/internal/src/transaction/redo-transaction.ts +1 -1
- package/internal/src/transaction/transaction-internal.ts +1 -4
- package/internal/src/transaction/undo-transaction.ts +7 -1
- package/package.json +3 -3
- package/realtime-client/dist/index.js +30 -5
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/dist/index.mjs +30 -5
- package/realtime-client/dist/index.mjs.map +1 -1
- package/realtime-client/src/use-server-action.ts +30 -5
- package/src/logger.ts +82 -14
- package/src/subscribe.ts +30 -7
|
@@ -8,17 +8,23 @@ export const redo__INTERNAL = (
|
|
|
8
8
|
token: TimelineToken,
|
|
9
9
|
store: Store = IMPLICIT.STORE,
|
|
10
10
|
): void => {
|
|
11
|
-
store.logger.info(
|
|
11
|
+
store.logger.info(`⏩`, `timeline`, token.key, `redo`)
|
|
12
12
|
const timelineData = store.timelines.get(token.key)
|
|
13
13
|
if (!timelineData) {
|
|
14
14
|
store.logger.error(
|
|
15
|
-
|
|
15
|
+
`🐞`,
|
|
16
|
+
`timeline`,
|
|
17
|
+
token.key,
|
|
18
|
+
`Failed to redo. This timeline has not been initialized.`,
|
|
16
19
|
)
|
|
17
20
|
return
|
|
18
21
|
}
|
|
19
22
|
if (timelineData.at === timelineData.history.length) {
|
|
20
23
|
store.logger.warn(
|
|
21
|
-
|
|
24
|
+
`💁`,
|
|
25
|
+
`timeline`,
|
|
26
|
+
token.key,
|
|
27
|
+
`Failed to redo at the end of timeline "${token.key}". There is nothing to redo.`,
|
|
22
28
|
)
|
|
23
29
|
return
|
|
24
30
|
}
|
|
@@ -43,7 +49,10 @@ export const redo__INTERNAL = (
|
|
|
43
49
|
timelineData.subject.next(`redo`)
|
|
44
50
|
timelineData.timeTraveling = null
|
|
45
51
|
store.logger.info(
|
|
46
|
-
|
|
52
|
+
`⏹️`,
|
|
53
|
+
`timeline`,
|
|
54
|
+
token.key,
|
|
55
|
+
`"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
|
|
47
56
|
)
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -51,17 +60,23 @@ export const undo__INTERNAL = (
|
|
|
51
60
|
token: TimelineToken,
|
|
52
61
|
store: Store = IMPLICIT.STORE,
|
|
53
62
|
): void => {
|
|
54
|
-
store.logger.info(
|
|
63
|
+
store.logger.info(`⏪`, `timeline`, token.key, `undo`)
|
|
55
64
|
const timelineData = store.timelines.get(token.key)
|
|
56
65
|
if (!timelineData) {
|
|
57
66
|
store.logger.error(
|
|
58
|
-
|
|
67
|
+
`🐞`,
|
|
68
|
+
`timeline`,
|
|
69
|
+
token.key,
|
|
70
|
+
`Failed to undo. This timeline has not been initialized.`,
|
|
59
71
|
)
|
|
60
72
|
return
|
|
61
73
|
}
|
|
62
74
|
if (timelineData.at === 0) {
|
|
63
75
|
store.logger.warn(
|
|
64
|
-
|
|
76
|
+
`💁`,
|
|
77
|
+
`timeline`,
|
|
78
|
+
token.key,
|
|
79
|
+
`Failed to undo at the beginning of timeline "${token.key}". There is nothing to undo.`,
|
|
65
80
|
)
|
|
66
81
|
return
|
|
67
82
|
}
|
|
@@ -86,6 +101,9 @@ export const undo__INTERNAL = (
|
|
|
86
101
|
timelineData.subject.next(`undo`)
|
|
87
102
|
timelineData.timeTraveling = null
|
|
88
103
|
store.logger.info(
|
|
89
|
-
|
|
104
|
+
`⏹️`,
|
|
105
|
+
`timeline`,
|
|
106
|
+
token.key,
|
|
107
|
+
`"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
|
|
90
108
|
)
|
|
91
109
|
}
|
|
@@ -77,7 +77,10 @@ export function timeline__INTERNAL(
|
|
|
77
77
|
const timelineKey = core.timelineAtoms.getRelatedKey(tokenOrFamily.key)
|
|
78
78
|
if (timelineKey) {
|
|
79
79
|
store.logger.error(
|
|
80
|
-
|
|
80
|
+
`❌`,
|
|
81
|
+
`timeline`,
|
|
82
|
+
options.key,
|
|
83
|
+
`Failed to add atom "${tokenOrFamily.key}" because it already belongs to timeline "${timelineKey}"`,
|
|
81
84
|
)
|
|
82
85
|
continue
|
|
83
86
|
}
|
|
@@ -101,7 +104,10 @@ export function timeline__INTERNAL(
|
|
|
101
104
|
)
|
|
102
105
|
if (familyTimelineKey) {
|
|
103
106
|
store.logger.error(
|
|
104
|
-
|
|
107
|
+
`❌`,
|
|
108
|
+
`timeline`,
|
|
109
|
+
options.key,
|
|
110
|
+
`Failed to add atom "${token.key}" because its family "${token.family.key}" already belongs to timeline "${familyTimelineKey}"`,
|
|
105
111
|
)
|
|
106
112
|
continue
|
|
107
113
|
}
|
|
@@ -3,10 +3,18 @@ import type { Store } from "../store"
|
|
|
3
3
|
export const abortTransaction = (store: Store): void => {
|
|
4
4
|
if (store.transactionStatus.phase === `idle`) {
|
|
5
5
|
store.logger.warn(
|
|
6
|
-
|
|
6
|
+
`🐞`,
|
|
7
|
+
`transaction`,
|
|
8
|
+
`???`,
|
|
9
|
+
`abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`,
|
|
7
10
|
)
|
|
8
11
|
return
|
|
9
12
|
}
|
|
13
|
+
store.logger.info(
|
|
14
|
+
`🪂`,
|
|
15
|
+
`transaction`,
|
|
16
|
+
store.transactionStatus.key,
|
|
17
|
+
`Aborting transaction`,
|
|
18
|
+
)
|
|
10
19
|
store.transactionStatus = { phase: `idle` }
|
|
11
|
-
store.logger.info(`🪂`, `transaction fail`)
|
|
12
20
|
}
|
|
@@ -10,7 +10,10 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
10
10
|
): void => {
|
|
11
11
|
if (store.transactionStatus.phase !== `building`) {
|
|
12
12
|
store.logger.warn(
|
|
13
|
-
|
|
13
|
+
`🐞`,
|
|
14
|
+
`transaction`,
|
|
15
|
+
`???`,
|
|
16
|
+
`applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`,
|
|
14
17
|
)
|
|
15
18
|
return
|
|
16
19
|
}
|
|
@@ -18,9 +21,13 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
18
21
|
store.transactionStatus.output = output
|
|
19
22
|
const { atomUpdates } = store.transactionStatus
|
|
20
23
|
store.logger.info(
|
|
21
|
-
|
|
24
|
+
`🛄`,
|
|
25
|
+
`transaction`,
|
|
26
|
+
store.transactionStatus.key,
|
|
27
|
+
`Applying transaction with ${atomUpdates.length} updates:`,
|
|
28
|
+
atomUpdates,
|
|
22
29
|
)
|
|
23
|
-
|
|
30
|
+
|
|
24
31
|
for (const { key, newValue } of atomUpdates) {
|
|
25
32
|
const token: AtomToken<unknown> = { key, type: `atom` }
|
|
26
33
|
if (!store.valueMap.has(token.key)) {
|
|
@@ -38,7 +45,12 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
38
45
|
}
|
|
39
46
|
store.atoms.set(newAtom.key, newAtom)
|
|
40
47
|
store.valueMap.set(newAtom.key, newAtom.default)
|
|
41
|
-
store.logger.info(
|
|
48
|
+
store.logger.info(
|
|
49
|
+
`🔨`,
|
|
50
|
+
`transaction`,
|
|
51
|
+
store.transactionStatus.key,
|
|
52
|
+
`Adding atom "${newAtom.key}"`,
|
|
53
|
+
)
|
|
42
54
|
}
|
|
43
55
|
}
|
|
44
56
|
// if (store.transactionStatus.key === `dealCards`) debugger
|
|
@@ -59,6 +71,11 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
59
71
|
output,
|
|
60
72
|
params: store.transactionStatus.params as Parameters<ƒ>,
|
|
61
73
|
})
|
|
74
|
+
store.logger.info(
|
|
75
|
+
`🛬`,
|
|
76
|
+
`transaction`,
|
|
77
|
+
store.transactionStatus.key,
|
|
78
|
+
`Finished applying transaction.`,
|
|
79
|
+
)
|
|
62
80
|
store.transactionStatus = { phase: `idle` }
|
|
63
|
-
store.logger.info(`🛬 transaction "${myTransaction.key}" applied`)
|
|
64
81
|
}
|
|
@@ -8,7 +8,7 @@ export const redoTransactionUpdate = <ƒ extends ƒn>(
|
|
|
8
8
|
update: TransactionUpdate<ƒ>,
|
|
9
9
|
store: Store,
|
|
10
10
|
): void => {
|
|
11
|
-
store.logger.info(`
|
|
11
|
+
store.logger.info(`⏭️`, `transaction`, update.key, `Redo`)
|
|
12
12
|
for (const { key, newValue } of update.atomUpdates) {
|
|
13
13
|
const token: AtomToken<unknown> = { key, type: `atom` }
|
|
14
14
|
const state = withdraw(token, store)
|
|
@@ -41,10 +41,7 @@ export function transaction__INTERNAL<ƒ extends ƒn>(
|
|
|
41
41
|
return output
|
|
42
42
|
} catch (thrown) {
|
|
43
43
|
abortTransaction(store)
|
|
44
|
-
store.logger.
|
|
45
|
-
`❗ Transaction "${options.key}" failed in store "${store.config.name}":`,
|
|
46
|
-
thrown,
|
|
47
|
-
)
|
|
44
|
+
store.logger.warn(`💥`, `transaction`, options.key, `caught:`, thrown)
|
|
48
45
|
throw thrown
|
|
49
46
|
}
|
|
50
47
|
},
|
|
@@ -8,7 +8,13 @@ export const undoTransactionUpdate = <ƒ extends ƒn>(
|
|
|
8
8
|
update: TransactionUpdate<ƒ>,
|
|
9
9
|
store: Store,
|
|
10
10
|
): void => {
|
|
11
|
-
store.logger.info(
|
|
11
|
+
store.logger.info(
|
|
12
|
+
`⏮️`,
|
|
13
|
+
`transaction`,
|
|
14
|
+
update.key,
|
|
15
|
+
`Undoing transaction update`,
|
|
16
|
+
update,
|
|
17
|
+
)
|
|
12
18
|
for (const { key, oldValue } of update.atomUpdates) {
|
|
13
19
|
const token: AtomToken<unknown> = { key, type: `atom` }
|
|
14
20
|
const state = withdraw(token, store)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atom.io",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Composable and testable reactive data library.",
|
|
5
5
|
"homepage": "https://atom.io.fyi",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@testing-library/react": "14.1.2",
|
|
52
52
|
"@types/http-proxy": "1.17.14",
|
|
53
53
|
"@types/npmlog": "4.1.6",
|
|
54
|
-
"@types/react": "18.2.
|
|
54
|
+
"@types/react": "18.2.38",
|
|
55
55
|
"@types/tmp": "0.2.6",
|
|
56
56
|
"@vitest/coverage-v8": "0.34.6",
|
|
57
57
|
"concurrently": "8.2.2",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"socket.io-client": "4.7.2",
|
|
72
72
|
"tmp": "0.2.1",
|
|
73
73
|
"tsup": "8.0.0",
|
|
74
|
-
"typescript": "5.
|
|
74
|
+
"typescript": "5.3.2",
|
|
75
75
|
"vite": "4.5.0",
|
|
76
76
|
"vite-tsconfig-paths": "4.2.1",
|
|
77
77
|
"vitest": "0.34.6"
|
|
@@ -131,17 +131,42 @@ function synchronizeTransactionResults(token, socket, store) {
|
|
|
131
131
|
const clientResult = JSON.stringify(clientUpdate);
|
|
132
132
|
const topic = `tx:sync:${transactionId}`;
|
|
133
133
|
const sync = (serverUpdate) => {
|
|
134
|
-
store.logger.info(
|
|
134
|
+
store.logger.info(
|
|
135
|
+
`\u{1F504}`,
|
|
136
|
+
`transaction`,
|
|
137
|
+
token.key,
|
|
138
|
+
`syncing client and server`
|
|
139
|
+
);
|
|
135
140
|
socket.off(topic, sync);
|
|
136
141
|
const serverResult = JSON.stringify(serverUpdate);
|
|
137
142
|
if (clientResult !== serverResult) {
|
|
138
143
|
store.logger.error(
|
|
139
|
-
`\
|
|
144
|
+
`\u274C`,
|
|
145
|
+
`transaction`,
|
|
146
|
+
token.key,
|
|
147
|
+
`results do not match between client and server`
|
|
148
|
+
);
|
|
149
|
+
store.logger.error(
|
|
150
|
+
`\u274C`,
|
|
151
|
+
`transaction`,
|
|
152
|
+
token.key,
|
|
153
|
+
`client:`,
|
|
154
|
+
clientResult
|
|
155
|
+
);
|
|
156
|
+
store.logger.error(
|
|
157
|
+
`\u274C`,
|
|
158
|
+
`transaction`,
|
|
159
|
+
token.key,
|
|
160
|
+
`server:`,
|
|
161
|
+
serverResult
|
|
140
162
|
);
|
|
141
|
-
store.logger.error(`\u2757 Client:`, clientResult);
|
|
142
|
-
store.logger.error(`\u2757 Server:`, serverResult);
|
|
143
163
|
} else {
|
|
144
|
-
store.logger.info(
|
|
164
|
+
store.logger.info(
|
|
165
|
+
`\u2705`,
|
|
166
|
+
`transaction`,
|
|
167
|
+
token.key,
|
|
168
|
+
`results match between client and server`
|
|
169
|
+
);
|
|
145
170
|
}
|
|
146
171
|
};
|
|
147
172
|
socket.on(topic, sync);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-state.ts","../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":["AtomIO","getJsonToken","getUpdateToken","parseJson","_a"],"mappings":"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","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | null>({\n\tkey: `myId__INTERNAL`,\n\tdefault: null,\n})\nexport const myIdState = AtomIO.selector<string | null>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.AtomToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tAtomIO.setState(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tAtomIO.setState(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tsubscriptionKey: string,\n\tstore: Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tAtomIO.subscribe(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\tsubscriptionKey,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nconst TX_SUBS = new Map<string, number>()\nexport function synchronizeTransactionResults(\n\ttoken: AtomIO.TransactionToken<any>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst count = TX_SUBS.get(token.key) ?? 0\n\tTX_SUBS.set(token.key, count + 1)\n\tconst unsubscribe =\n\t\tcount === 0\n\t\t\t? AtomIO.subscribeToTransaction(\n\t\t\t\t\ttoken,\n\t\t\t\t\t(clientUpdate) => {\n\t\t\t\t\t\tconst transactionId = Math.random().toString(36).slice(2)\n\t\t\t\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\t\t\t\tconst topic = `tx:sync:${transactionId}`\n\t\t\t\t\t\tconst sync = (serverUpdate: typeof clientUpdate) => {\n\t\t\t\t\t\t\tstore.logger.info(`♻️ Transaction \"${token.key}\" synced`)\n\t\t\t\t\t\t\tsocket.off(topic, sync)\n\t\t\t\t\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\t\t\t\t\tif (clientResult !== serverResult) {\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❗ Transaction \"${token.key}\" produced different results on client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(`❗ Client:`, clientResult)\n\t\t\t\t\t\t\t\tstore.logger.error(`❗ Server:`, serverResult)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstore.logger.info(`✅ Transaction ${token.key} results match`)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsocket.on(topic, sync)\n\t\t\t\t\t\tsocket.emit(`tx:${token.key}`, clientUpdate, transactionId)\n\t\t\t\t\t},\n\t\t\t\t\t`use-server-action`,\n\t\t\t\t\tstore,\n\t\t\t )\n\t\t\t: () => null\n\treturn () => {\n\t\tconst newCount = TX_SUBS.get(token.key) ?? 0\n\t\tTX_SUBS.set(token.key, newCount - 1)\n\t\tunsubscribe()\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/realtime-state.ts","../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":["AtomIO","getJsonToken","getUpdateToken","parseJson","_a"],"mappings":";AAAA,YAAY,YAAY;AAEjB,IAAM,sBAA6B,YAAoB;AAAA,EAC7D,KAAK;AAAA,EACL,SAAS;AACV,CAAC;AACM,IAAM,YAAmB,gBAAwB;AAAA,EACvD,KAAK;AAAA,EACL,KAAK,CAAC,EAAE,IAAI,MAAM,IAAI,mBAAmB;AAC1C,CAAC;;;ACTD,YAAYA,aAAY;AAKjB,SAAS,UACf,OACA,QACA,OACa;AACb,SAAO,GAAG,SAAS,MAAM,GAAG,IAAI,CAAC,SAAS;AACzC,IAAO,iBAAS,OAAO,MAAM,KAAK;AAAA,EACnC,CAAC;AACD,SAAO,KAAK,OAAO,MAAM,GAAG,EAAE;AAC9B,SAAO,MAAM;AACZ,WAAO,IAAI,SAAS,MAAM,GAAG,EAAE;AAC/B,WAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAAA,EACjC;AACD;;;AClBA,YAAYA,aAAY;AAGxB,SAAS,iBAAiB;AAGnB,SAAS,iBACf,OACA,QACA,OACa;AACb,MAAI,EAAE,YAAY,QAAQ;AACzB,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,MAAM;AAAA,IAAC;AAAA,EACf;AACA,QAAM,EAAE,KAAK,WAAW,QAAQ,iBAAiB,IAAI,MAAM;AAC3D,QAAM,SAAS,UAAU,gBAAgB;AACzC,mCAAQ,GAAG,SAAS,MAAM,GAAG,IAAI,CAAC,SAAY;AAC7C,IAAO,iBAAS,OAAO,MAAM,KAAK;AAAA,EACnC;AACA,mCAAQ,KAAK,OAAO,SAAS,IAAI;AACjC,SAAO,MAAM;AACZ,qCAAQ,IAAI,SAAS,MAAM,GAAG;AAC9B,qCAAQ,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AACD;;;ACzBA,YAAYA,aAAY;AAExB,SAAS,cAAc,sBAAsB;AAItC,SAAS,iBAIf,OACA,QACA,OACa;AACb,QAAM,YAAY,aAAa,KAAK;AACpC,QAAM,cAAc,eAAe,KAAK;AACxC,SAAO,GAAG,QAAQ,MAAM,GAAG,IAAI,CAAC,SAAY;AAC3C,IAAO,iBAAS,WAAW,MAAM,KAAK;AAAA,EACvC,CAAC;AACD,SAAO;AAAA,IACN,QAAQ,MAAM,GAAG;AAAA,IACjB,CAAC,SAA+D;AAC/D,MAAO,iBAAS,aAAa,MAAM,KAAK;AAAA,IACzC;AAAA,EACD;AACA,SAAO,KAAK,OAAO,MAAM,GAAG,EAAE;AAC9B,SAAO,MAAM;AACZ,WAAO,IAAI,QAAQ,MAAM,GAAG,EAAE;AAC9B,WAAO,IAAI,QAAQ,MAAM,GAAG,EAAE;AAC9B,WAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAAA,EACjC;AACD;;;AC/BA,YAAYA,aAAY;AACxB,SAAS,gBAAAC,eAAc,kBAAAC,uBAAsB;AAE7C,SAAS,aAAAC,kBAAiB;AAInB,SAAS,wBAIf,OACA,QACA,OACa;AACb,MAAI,EAAE,YAAY,QAAQ;AACzB,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,MAAM;AAAA,IAAC;AAAA,EACf;AACA,QAAM,EAAE,KAAK,WAAW,QAAQ,iBAAiB,IAAI,MAAM;AAC3D,QAAM,SAASA,WAAU,gBAAgB;AACzC,mCAAQ,GAAG,QAAQ,MAAM,GAAG,IAAI,CAAC,SAAY;AAC5C,UAAM,YAAYF,cAAa,KAAK;AACpC,IAAO,iBAAS,WAAW,MAAM,KAAK;AAAA,EACvC;AACA,mCAAQ;AAAA,IACP,QAAQ,MAAM,GAAG;AAAA,IACjB,CAAC,SAA+D;AAC/D,YAAM,eAAeC,gBAAe,KAAK;AACzC,MAAO,iBAAS,cAAc,MAAM,KAAK;AAAA,IAC1C;AAAA;AAED,mCAAQ,KAAK,OAAO,SAAS,IAAI;AACjC,SAAO,MAAM;AACZ,qCAAQ,IAAI,SAAS,MAAM,GAAG;AAC9B,qCAAQ,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AACD;;;ACrCA,YAAYF,aAAY;AAKjB,SAAS,UACf,OACA,QACA,iBACA,OACa;AACb,SAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAChC,EAAO;AAAA,IACN;AAAA,IACA,CAAC,EAAE,SAAS,MAAM;AACjB,aAAO,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,SAAO,MAAM;AACZ,WAAO,IAAI,OAAO,MAAM,GAAG,EAAE;AAC7B,WAAO,KAAK,WAAW,MAAM,GAAG,EAAE;AAAA,EACnC;AACD;;;ACxBA,YAAYA,aAAY;AAIxB,IAAM,UAAU,oBAAI,IAAoB;AACjC,SAAS,8BACf,OACA,QACA,OACa;AATd;AAUC,QAAM,SAAQ,aAAQ,IAAI,MAAM,GAAG,MAArB,YAA0B;AACxC,UAAQ,IAAI,MAAM,KAAK,QAAQ,CAAC;AAChC,QAAM,cACL,UAAU,IACA;AAAA,IACP;AAAA,IACA,CAAC,iBAAiB;AACjB,YAAM,gBAAgB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AACxD,YAAM,eAAe,KAAK,UAAU,YAAY;AAChD,YAAM,QAAQ,WAAW,aAAa;AACtC,YAAM,OAAO,CAAC,iBAAsC;AACnD,cAAM,OAAO;AAAA,UACZ;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACD;AACA,eAAO,IAAI,OAAO,IAAI;AACtB,cAAM,eAAe,KAAK,UAAU,YAAY;AAChD,YAAI,iBAAiB,cAAc;AAClC,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACD;AACA,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACD;AACA,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACD;AAAA,QACD,OAAO;AACN,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACD;AAAA,QACD;AAAA,MACD;AACA,aAAO,GAAG,OAAO,IAAI;AACrB,aAAO,KAAK,MAAM,MAAM,GAAG,IAAI,cAAc,aAAa;AAAA,IAC3D;AAAA,IACA;AAAA,IACA;AAAA,EACA,IACA,MAAM;AACV,SAAO,MAAM;AAlEd,QAAAI;AAmEE,UAAM,YAAWA,MAAA,QAAQ,IAAI,MAAM,GAAG,MAArB,OAAAA,MAA0B;AAC3C,YAAQ,IAAI,MAAM,KAAK,WAAW,CAAC;AACnC,gBAAY;AAAA,EACb;AACD","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | null>({\n\tkey: `myId__INTERNAL`,\n\tdefault: null,\n})\nexport const myIdState = AtomIO.selector<string | null>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.AtomToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tAtomIO.setState(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tAtomIO.setState(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tsubscriptionKey: string,\n\tstore: Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tAtomIO.subscribe(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\tsubscriptionKey,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nconst TX_SUBS = new Map<string, number>()\nexport function synchronizeTransactionResults(\n\ttoken: AtomIO.TransactionToken<any>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst count = TX_SUBS.get(token.key) ?? 0\n\tTX_SUBS.set(token.key, count + 1)\n\tconst unsubscribe =\n\t\tcount === 0\n\t\t\t? AtomIO.subscribeToTransaction(\n\t\t\t\t\ttoken,\n\t\t\t\t\t(clientUpdate) => {\n\t\t\t\t\t\tconst transactionId = Math.random().toString(36).slice(2)\n\t\t\t\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\t\t\t\tconst topic = `tx:sync:${transactionId}`\n\t\t\t\t\t\tconst sync = (serverUpdate: typeof clientUpdate) => {\n\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t`🔄`,\n\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t`syncing client and server`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tsocket.off(topic, sync)\n\t\t\t\t\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\t\t\t\t\tif (clientResult !== serverResult) {\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`results do not match between client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`client:`,\n\t\t\t\t\t\t\t\t\tclientResult,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`server:`,\n\t\t\t\t\t\t\t\t\tserverResult,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t\t`✅`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`results match between client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsocket.on(topic, sync)\n\t\t\t\t\t\tsocket.emit(`tx:${token.key}`, clientUpdate, transactionId)\n\t\t\t\t\t},\n\t\t\t\t\t`use-server-action`,\n\t\t\t\t\tstore,\n\t\t\t )\n\t\t\t: () => null\n\treturn () => {\n\t\tconst newCount = TX_SUBS.get(token.key) ?? 0\n\t\tTX_SUBS.set(token.key, newCount - 1)\n\t\tunsubscribe()\n\t}\n}\n"]}
|
|
@@ -109,17 +109,42 @@ function synchronizeTransactionResults(token, socket, store) {
|
|
|
109
109
|
const clientResult = JSON.stringify(clientUpdate);
|
|
110
110
|
const topic = `tx:sync:${transactionId}`;
|
|
111
111
|
const sync = (serverUpdate) => {
|
|
112
|
-
store.logger.info(
|
|
112
|
+
store.logger.info(
|
|
113
|
+
`\u{1F504}`,
|
|
114
|
+
`transaction`,
|
|
115
|
+
token.key,
|
|
116
|
+
`syncing client and server`
|
|
117
|
+
);
|
|
113
118
|
socket.off(topic, sync);
|
|
114
119
|
const serverResult = JSON.stringify(serverUpdate);
|
|
115
120
|
if (clientResult !== serverResult) {
|
|
116
121
|
store.logger.error(
|
|
117
|
-
`\
|
|
122
|
+
`\u274C`,
|
|
123
|
+
`transaction`,
|
|
124
|
+
token.key,
|
|
125
|
+
`results do not match between client and server`
|
|
126
|
+
);
|
|
127
|
+
store.logger.error(
|
|
128
|
+
`\u274C`,
|
|
129
|
+
`transaction`,
|
|
130
|
+
token.key,
|
|
131
|
+
`client:`,
|
|
132
|
+
clientResult
|
|
133
|
+
);
|
|
134
|
+
store.logger.error(
|
|
135
|
+
`\u274C`,
|
|
136
|
+
`transaction`,
|
|
137
|
+
token.key,
|
|
138
|
+
`server:`,
|
|
139
|
+
serverResult
|
|
118
140
|
);
|
|
119
|
-
store.logger.error(`\u2757 Client:`, clientResult);
|
|
120
|
-
store.logger.error(`\u2757 Server:`, serverResult);
|
|
121
141
|
} else {
|
|
122
|
-
store.logger.info(
|
|
142
|
+
store.logger.info(
|
|
143
|
+
`\u2705`,
|
|
144
|
+
`transaction`,
|
|
145
|
+
token.key,
|
|
146
|
+
`results match between client and server`
|
|
147
|
+
);
|
|
123
148
|
}
|
|
124
149
|
};
|
|
125
150
|
socket.on(topic, sync);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-state.ts","../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":["AtomIO","getJsonToken","getUpdateToken","parseJson","_a"],"mappings":"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","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | null>({\n\tkey: `myId__INTERNAL`,\n\tdefault: null,\n})\nexport const myIdState = AtomIO.selector<string | null>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.AtomToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tAtomIO.setState(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tAtomIO.setState(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tsubscriptionKey: string,\n\tstore: Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tAtomIO.subscribe(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\tsubscriptionKey,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nconst TX_SUBS = new Map<string, number>()\nexport function synchronizeTransactionResults(\n\ttoken: AtomIO.TransactionToken<any>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst count = TX_SUBS.get(token.key) ?? 0\n\tTX_SUBS.set(token.key, count + 1)\n\tconst unsubscribe =\n\t\tcount === 0\n\t\t\t? AtomIO.subscribeToTransaction(\n\t\t\t\t\ttoken,\n\t\t\t\t\t(clientUpdate) => {\n\t\t\t\t\t\tconst transactionId = Math.random().toString(36).slice(2)\n\t\t\t\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\t\t\t\tconst topic = `tx:sync:${transactionId}`\n\t\t\t\t\t\tconst sync = (serverUpdate: typeof clientUpdate) => {\n\t\t\t\t\t\t\tstore.logger.info(`♻️ Transaction \"${token.key}\" synced`)\n\t\t\t\t\t\t\tsocket.off(topic, sync)\n\t\t\t\t\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\t\t\t\t\tif (clientResult !== serverResult) {\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❗ Transaction \"${token.key}\" produced different results on client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(`❗ Client:`, clientResult)\n\t\t\t\t\t\t\t\tstore.logger.error(`❗ Server:`, serverResult)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstore.logger.info(`✅ Transaction ${token.key} results match`)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsocket.on(topic, sync)\n\t\t\t\t\t\tsocket.emit(`tx:${token.key}`, clientUpdate, transactionId)\n\t\t\t\t\t},\n\t\t\t\t\t`use-server-action`,\n\t\t\t\t\tstore,\n\t\t\t )\n\t\t\t: () => null\n\treturn () => {\n\t\tconst newCount = TX_SUBS.get(token.key) ?? 0\n\t\tTX_SUBS.set(token.key, newCount - 1)\n\t\tunsubscribe()\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/realtime-state.ts","../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":["AtomIO","getJsonToken","getUpdateToken","parseJson","_a"],"mappings":";AAAA,YAAY,YAAY;AAEjB,IAAM,sBAA6B,YAAoB;AAAA,EAC7D,KAAK;AAAA,EACL,SAAS;AACV,CAAC;AACM,IAAM,YAAmB,gBAAwB;AAAA,EACvD,KAAK;AAAA,EACL,KAAK,CAAC,EAAE,IAAI,MAAM,IAAI,mBAAmB;AAC1C,CAAC;;;ACTD,YAAYA,aAAY;AAKjB,SAAS,UACf,OACA,QACA,OACa;AACb,SAAO,GAAG,SAAS,MAAM,GAAG,IAAI,CAAC,SAAS;AACzC,IAAO,iBAAS,OAAO,MAAM,KAAK;AAAA,EACnC,CAAC;AACD,SAAO,KAAK,OAAO,MAAM,GAAG,EAAE;AAC9B,SAAO,MAAM;AACZ,WAAO,IAAI,SAAS,MAAM,GAAG,EAAE;AAC/B,WAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAAA,EACjC;AACD;;;AClBA,YAAYA,aAAY;AAGxB,SAAS,iBAAiB;AAGnB,SAAS,iBACf,OACA,QACA,OACa;AACb,MAAI,EAAE,YAAY,QAAQ;AACzB,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,MAAM;AAAA,IAAC;AAAA,EACf;AACA,QAAM,EAAE,KAAK,WAAW,QAAQ,iBAAiB,IAAI,MAAM;AAC3D,QAAM,SAAS,UAAU,gBAAgB;AACzC,mCAAQ,GAAG,SAAS,MAAM,GAAG,IAAI,CAAC,SAAY;AAC7C,IAAO,iBAAS,OAAO,MAAM,KAAK;AAAA,EACnC;AACA,mCAAQ,KAAK,OAAO,SAAS,IAAI;AACjC,SAAO,MAAM;AACZ,qCAAQ,IAAI,SAAS,MAAM,GAAG;AAC9B,qCAAQ,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AACD;;;ACzBA,YAAYA,aAAY;AAExB,SAAS,cAAc,sBAAsB;AAItC,SAAS,iBAIf,OACA,QACA,OACa;AACb,QAAM,YAAY,aAAa,KAAK;AACpC,QAAM,cAAc,eAAe,KAAK;AACxC,SAAO,GAAG,QAAQ,MAAM,GAAG,IAAI,CAAC,SAAY;AAC3C,IAAO,iBAAS,WAAW,MAAM,KAAK;AAAA,EACvC,CAAC;AACD,SAAO;AAAA,IACN,QAAQ,MAAM,GAAG;AAAA,IACjB,CAAC,SAA+D;AAC/D,MAAO,iBAAS,aAAa,MAAM,KAAK;AAAA,IACzC;AAAA,EACD;AACA,SAAO,KAAK,OAAO,MAAM,GAAG,EAAE;AAC9B,SAAO,MAAM;AACZ,WAAO,IAAI,QAAQ,MAAM,GAAG,EAAE;AAC9B,WAAO,IAAI,QAAQ,MAAM,GAAG,EAAE;AAC9B,WAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAAA,EACjC;AACD;;;AC/BA,YAAYA,aAAY;AACxB,SAAS,gBAAAC,eAAc,kBAAAC,uBAAsB;AAE7C,SAAS,aAAAC,kBAAiB;AAInB,SAAS,wBAIf,OACA,QACA,OACa;AACb,MAAI,EAAE,YAAY,QAAQ;AACzB,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,MAAM;AAAA,IAAC;AAAA,EACf;AACA,QAAM,EAAE,KAAK,WAAW,QAAQ,iBAAiB,IAAI,MAAM;AAC3D,QAAM,SAASA,WAAU,gBAAgB;AACzC,mCAAQ,GAAG,QAAQ,MAAM,GAAG,IAAI,CAAC,SAAY;AAC5C,UAAM,YAAYF,cAAa,KAAK;AACpC,IAAO,iBAAS,WAAW,MAAM,KAAK;AAAA,EACvC;AACA,mCAAQ;AAAA,IACP,QAAQ,MAAM,GAAG;AAAA,IACjB,CAAC,SAA+D;AAC/D,YAAM,eAAeC,gBAAe,KAAK;AACzC,MAAO,iBAAS,cAAc,MAAM,KAAK;AAAA,IAC1C;AAAA;AAED,mCAAQ,KAAK,OAAO,SAAS,IAAI;AACjC,SAAO,MAAM;AACZ,qCAAQ,IAAI,SAAS,MAAM,GAAG;AAC9B,qCAAQ,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AACD;;;ACrCA,YAAYF,aAAY;AAKjB,SAAS,UACf,OACA,QACA,iBACA,OACa;AACb,SAAO,KAAK,SAAS,MAAM,GAAG,EAAE;AAChC,EAAO;AAAA,IACN;AAAA,IACA,CAAC,EAAE,SAAS,MAAM;AACjB,aAAO,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,SAAO,MAAM;AACZ,WAAO,IAAI,OAAO,MAAM,GAAG,EAAE;AAC7B,WAAO,KAAK,WAAW,MAAM,GAAG,EAAE;AAAA,EACnC;AACD;;;ACxBA,YAAYA,aAAY;AAIxB,IAAM,UAAU,oBAAI,IAAoB;AACjC,SAAS,8BACf,OACA,QACA,OACa;AATd;AAUC,QAAM,SAAQ,aAAQ,IAAI,MAAM,GAAG,MAArB,YAA0B;AACxC,UAAQ,IAAI,MAAM,KAAK,QAAQ,CAAC;AAChC,QAAM,cACL,UAAU,IACA;AAAA,IACP;AAAA,IACA,CAAC,iBAAiB;AACjB,YAAM,gBAAgB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AACxD,YAAM,eAAe,KAAK,UAAU,YAAY;AAChD,YAAM,QAAQ,WAAW,aAAa;AACtC,YAAM,OAAO,CAAC,iBAAsC;AACnD,cAAM,OAAO;AAAA,UACZ;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACD;AACA,eAAO,IAAI,OAAO,IAAI;AACtB,cAAM,eAAe,KAAK,UAAU,YAAY;AAChD,YAAI,iBAAiB,cAAc;AAClC,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACD;AACA,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACD;AACA,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACD;AAAA,QACD,OAAO;AACN,gBAAM,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACD;AAAA,QACD;AAAA,MACD;AACA,aAAO,GAAG,OAAO,IAAI;AACrB,aAAO,KAAK,MAAM,MAAM,GAAG,IAAI,cAAc,aAAa;AAAA,IAC3D;AAAA,IACA;AAAA,IACA;AAAA,EACA,IACA,MAAM;AACV,SAAO,MAAM;AAlEd,QAAAI;AAmEE,UAAM,YAAWA,MAAA,QAAQ,IAAI,MAAM,GAAG,MAArB,OAAAA,MAA0B;AAC3C,YAAQ,IAAI,MAAM,KAAK,WAAW,CAAC;AACnC,gBAAY;AAAA,EACb;AACD","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | null>({\n\tkey: `myId__INTERNAL`,\n\tdefault: null,\n})\nexport const myIdState = AtomIO.selector<string | null>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.AtomToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tAtomIO.setState(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<Json.Serializable>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tAtomIO.setState(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.StateToken<J>,\n\tsocket: Socket,\n\tsubscriptionKey: string,\n\tstore: Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tAtomIO.subscribe(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\tsubscriptionKey,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nconst TX_SUBS = new Map<string, number>()\nexport function synchronizeTransactionResults(\n\ttoken: AtomIO.TransactionToken<any>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst count = TX_SUBS.get(token.key) ?? 0\n\tTX_SUBS.set(token.key, count + 1)\n\tconst unsubscribe =\n\t\tcount === 0\n\t\t\t? AtomIO.subscribeToTransaction(\n\t\t\t\t\ttoken,\n\t\t\t\t\t(clientUpdate) => {\n\t\t\t\t\t\tconst transactionId = Math.random().toString(36).slice(2)\n\t\t\t\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\t\t\t\tconst topic = `tx:sync:${transactionId}`\n\t\t\t\t\t\tconst sync = (serverUpdate: typeof clientUpdate) => {\n\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t`🔄`,\n\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t`syncing client and server`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tsocket.off(topic, sync)\n\t\t\t\t\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\t\t\t\t\tif (clientResult !== serverResult) {\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`results do not match between client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`client:`,\n\t\t\t\t\t\t\t\t\tclientResult,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`server:`,\n\t\t\t\t\t\t\t\t\tserverResult,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t\t`✅`,\n\t\t\t\t\t\t\t\t\t`transaction`,\n\t\t\t\t\t\t\t\t\ttoken.key,\n\t\t\t\t\t\t\t\t\t`results match between client and server`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsocket.on(topic, sync)\n\t\t\t\t\t\tsocket.emit(`tx:${token.key}`, clientUpdate, transactionId)\n\t\t\t\t\t},\n\t\t\t\t\t`use-server-action`,\n\t\t\t\t\tstore,\n\t\t\t )\n\t\t\t: () => null\n\treturn () => {\n\t\tconst newCount = TX_SUBS.get(token.key) ?? 0\n\t\tTX_SUBS.set(token.key, newCount - 1)\n\t\tunsubscribe()\n\t}\n}\n"]}
|
|
@@ -19,17 +19,42 @@ export function synchronizeTransactionResults(
|
|
|
19
19
|
const clientResult = JSON.stringify(clientUpdate)
|
|
20
20
|
const topic = `tx:sync:${transactionId}`
|
|
21
21
|
const sync = (serverUpdate: typeof clientUpdate) => {
|
|
22
|
-
store.logger.info(
|
|
22
|
+
store.logger.info(
|
|
23
|
+
`🔄`,
|
|
24
|
+
`transaction`,
|
|
25
|
+
token.key,
|
|
26
|
+
`syncing client and server`,
|
|
27
|
+
)
|
|
23
28
|
socket.off(topic, sync)
|
|
24
29
|
const serverResult = JSON.stringify(serverUpdate)
|
|
25
30
|
if (clientResult !== serverResult) {
|
|
26
31
|
store.logger.error(
|
|
27
|
-
|
|
32
|
+
`❌`,
|
|
33
|
+
`transaction`,
|
|
34
|
+
token.key,
|
|
35
|
+
`results do not match between client and server`,
|
|
36
|
+
)
|
|
37
|
+
store.logger.error(
|
|
38
|
+
`❌`,
|
|
39
|
+
`transaction`,
|
|
40
|
+
token.key,
|
|
41
|
+
`client:`,
|
|
42
|
+
clientResult,
|
|
43
|
+
)
|
|
44
|
+
store.logger.error(
|
|
45
|
+
`❌`,
|
|
46
|
+
`transaction`,
|
|
47
|
+
token.key,
|
|
48
|
+
`server:`,
|
|
49
|
+
serverResult,
|
|
28
50
|
)
|
|
29
|
-
store.logger.error(`❗ Client:`, clientResult)
|
|
30
|
-
store.logger.error(`❗ Server:`, serverResult)
|
|
31
51
|
} else {
|
|
32
|
-
store.logger.info(
|
|
52
|
+
store.logger.info(
|
|
53
|
+
`✅`,
|
|
54
|
+
`transaction`,
|
|
55
|
+
token.key,
|
|
56
|
+
`results match between client and server`,
|
|
57
|
+
)
|
|
33
58
|
}
|
|
34
59
|
}
|
|
35
60
|
socket.on(topic, sync)
|
package/src/logger.ts
CHANGED
|
@@ -1,31 +1,99 @@
|
|
|
1
|
-
|
|
1
|
+
const LoggerIconDictionary = {
|
|
2
|
+
"⌛": `Timeline event fully captured`,
|
|
3
|
+
"⏩": `Timeline redo`,
|
|
4
|
+
"⏪": `Timeline undo`,
|
|
5
|
+
"⏭️": `Transaction redo`,
|
|
6
|
+
"⏮️": `Transaction undo`,
|
|
7
|
+
"⏳": `Timeline event partially captured`,
|
|
8
|
+
"⏹️": `Time-travel complete`,
|
|
9
|
+
"💁": `Notice`,
|
|
10
|
+
"🔄": `Realtime transaction synchronized`,
|
|
11
|
+
"✅": `Realtime transaction success`,
|
|
12
|
+
"✨": `Computation complete`,
|
|
13
|
+
"❌": `Conflict prevents attempted action`,
|
|
14
|
+
"⭕": `Operation start`,
|
|
15
|
+
"🐞": `Possible bug in AtomIO`,
|
|
16
|
+
"👀": `Subscription added`,
|
|
17
|
+
"👪": `Family member added`,
|
|
18
|
+
"📁": `Stow update`,
|
|
19
|
+
"📃": `Copy mutable`,
|
|
20
|
+
"📖": `Read state`,
|
|
21
|
+
"📝": `Write state`,
|
|
22
|
+
"📢": `Notify subscribers`,
|
|
23
|
+
"🔌": `Register dependency`,
|
|
24
|
+
"🔍": `Discover root`,
|
|
25
|
+
"🔥": `Delete state`,
|
|
26
|
+
"🔧": `Create mutable atom`,
|
|
27
|
+
"🔨": `Create immutable atom`,
|
|
28
|
+
"🔴": `Operation complete`,
|
|
29
|
+
"🗑": `Evict cached value`,
|
|
30
|
+
"💥": `Caught`,
|
|
31
|
+
"🙈": `Subscription canceled`,
|
|
32
|
+
"🛄": `Apply transaction`,
|
|
33
|
+
"🛠️": `Install atom into store`,
|
|
34
|
+
"🛫": `Begin transaction`,
|
|
35
|
+
"🛬": `Complete transaction`,
|
|
36
|
+
"🧮": `Computing selector`,
|
|
37
|
+
"🧹": `Prepare to evict`,
|
|
38
|
+
"🪂": `Abort transaction`,
|
|
39
|
+
} as const
|
|
40
|
+
export type LoggerIcon = keyof typeof LoggerIconDictionary
|
|
2
41
|
|
|
3
|
-
export const LOG_LEVELS
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
42
|
+
export const LOG_LEVELS = [`info`, `warn`, `error`] as const
|
|
43
|
+
export type LogLevel = typeof LOG_LEVELS[number]
|
|
44
|
+
|
|
45
|
+
export type LogFn = (
|
|
46
|
+
icon: LoggerIcon,
|
|
47
|
+
tokenType:
|
|
48
|
+
| `atom`
|
|
49
|
+
| `readonly_selector`
|
|
50
|
+
| `selector`
|
|
51
|
+
| `state`
|
|
52
|
+
| `timeline`
|
|
53
|
+
| `transaction`
|
|
54
|
+
| `unknown`,
|
|
55
|
+
tokenKey: string,
|
|
56
|
+
message: string,
|
|
57
|
+
...rest: any[]
|
|
58
|
+
) => void
|
|
59
|
+
export type LogFilter = (...params: Parameters<LogFn>) => boolean
|
|
60
|
+
|
|
61
|
+
export type Logger = Record<LogLevel, LogFn>
|
|
62
|
+
|
|
63
|
+
export const simpleLog =
|
|
64
|
+
(logLevel: keyof Logger): LogFn =>
|
|
65
|
+
(icon, tokenType, tokenKey, message, ...rest) => {
|
|
66
|
+
console[logLevel](
|
|
67
|
+
`${icon} ${tokenType} "${tokenKey}" ${message}`,
|
|
68
|
+
...rest.map((arg) => JSON.stringify(arg)),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
export const simpleLogger: Logger = {
|
|
72
|
+
error: simpleLog(`error`),
|
|
73
|
+
info: simpleLog(`info`),
|
|
74
|
+
warn: simpleLog(`warn`),
|
|
75
|
+
}
|
|
8
76
|
|
|
9
77
|
export class AtomIOLogger implements Logger {
|
|
10
78
|
public constructor(
|
|
11
|
-
private readonly logger: Logger,
|
|
12
79
|
public logLevel: `error` | `info` | `warn` | null,
|
|
13
|
-
private readonly filter?:
|
|
80
|
+
private readonly filter?: LogFilter,
|
|
81
|
+
private readonly logger: Logger = simpleLogger,
|
|
14
82
|
) {}
|
|
15
83
|
|
|
16
|
-
public error(...args
|
|
17
|
-
if ((this.filter?.(args
|
|
84
|
+
public error: LogFn = (...args) => {
|
|
85
|
+
if ((this.filter?.(...args) ?? true) && this.logLevel !== null) {
|
|
18
86
|
this.logger.error(...args)
|
|
19
87
|
}
|
|
20
88
|
}
|
|
21
|
-
public info(...args
|
|
22
|
-
if ((this.filter?.(args
|
|
89
|
+
public info: LogFn = (...args) => {
|
|
90
|
+
if ((this.filter?.(...args) ?? true) && this.logLevel === `info`) {
|
|
23
91
|
this.logger.info(...args)
|
|
24
92
|
}
|
|
25
93
|
}
|
|
26
|
-
public warn(...args
|
|
94
|
+
public warn: LogFn = (...args) => {
|
|
27
95
|
if (
|
|
28
|
-
(this.filter?.(args
|
|
96
|
+
(this.filter?.(...args) ?? true) &&
|
|
29
97
|
this.logLevel !== `error` &&
|
|
30
98
|
this.logLevel !== null
|
|
31
99
|
) {
|