atom.io 0.17.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/dist/index.cjs +62 -40
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +8 -2
- package/data/dist/index.js +64 -42
- package/data/dist/index.js.map +1 -1
- package/data/src/dict.ts +8 -4
- package/data/src/join.ts +74 -33
- package/data/src/struct-family.ts +18 -17
- package/dist/chunk-IZHOMSXA.js +331 -0
- package/dist/chunk-IZHOMSXA.js.map +1 -0
- package/dist/chunk-JDUNWJFB.js +18 -0
- package/dist/chunk-JDUNWJFB.js.map +1 -0
- package/dist/index.cjs +4 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +66 -51
- package/dist/index.js +5 -11
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +187 -58
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +95 -71
- package/internal/dist/index.js +179 -53
- package/internal/dist/index.js.map +1 -1
- package/internal/src/arbitrary.ts +3 -0
- package/internal/src/atom/delete-atom.ts +7 -6
- package/internal/src/caching.ts +6 -4
- package/internal/src/families/find-in-store.ts +16 -0
- package/internal/src/get-environment-data.ts +4 -7
- package/internal/src/index.ts +6 -5
- package/internal/src/ingest-updates/ingest-atom-update.ts +6 -2
- package/internal/src/ingest-updates/ingest-transaction-update.ts +0 -1
- package/internal/src/selector/create-standalone-selector.ts +0 -2
- package/internal/src/set-state/copy-mutable-if-needed.ts +5 -0
- package/internal/src/set-state/emit-update.ts +25 -11
- package/internal/src/set-state/set-atom.ts +15 -18
- package/internal/src/store/store.ts +14 -2
- package/internal/src/store/withdraw.ts +72 -2
- package/internal/src/subscribe/subscribe-to-timeline.ts +2 -2
- package/internal/src/subscribe/subscribe-to-transaction.ts +2 -2
- package/internal/src/timeline/create-timeline.ts +12 -1
- package/internal/src/transaction/act-upon-store.ts +19 -0
- package/internal/src/transaction/apply-transaction.ts +6 -1
- package/internal/src/transaction/assign-transaction-to-continuity.ts +18 -0
- package/internal/src/transaction/build-transaction.ts +7 -6
- package/internal/src/transaction/create-transaction.ts +1 -1
- package/internal/src/transaction/get-epoch-number.ts +40 -0
- package/internal/src/transaction/index.ts +10 -1
- package/internal/src/transaction/set-epoch-number.ts +30 -0
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +3 -3
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-introspection-states.ts +6 -2
- package/introspection/src/attach-timeline-family.ts +5 -2
- package/introspection/src/attach-transaction-logs.ts +2 -2
- package/json/dist/index.d.ts +3 -1
- package/json/src/index.ts +4 -0
- package/package.json +241 -230
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.ts +1 -1
- package/react/dist/index.js.map +1 -1
- package/react/src/use-json.ts +1 -1
- package/react-devtools/dist/index.cjs +131 -134
- package/react-devtools/dist/index.cjs.map +1 -1
- package/react-devtools/dist/index.css +2 -2
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.ts +3 -3
- package/react-devtools/dist/index.js +91 -108
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/src/StateEditor.tsx +4 -4
- package/react-devtools/src/StateIndex.tsx +1 -4
- package/react-devtools/src/TimelineIndex.tsx +3 -3
- package/react-devtools/src/TransactionIndex.tsx +9 -8
- package/react-devtools/src/index.ts +2 -2
- package/realtime/dist/index.cjs +120 -0
- package/realtime/dist/index.cjs.map +1 -0
- package/realtime/dist/index.d.ts +146 -0
- package/realtime/dist/index.js +111 -0
- package/realtime/dist/index.js.map +1 -0
- package/realtime/package.json +16 -0
- package/realtime/src/index.ts +2 -0
- package/realtime/src/realtime-continuity.ts +162 -0
- package/realtime/src/shared-room-store.ts +48 -0
- package/realtime-client/dist/index.cjs +424 -170
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +15 -11
- package/realtime-client/dist/index.js +96 -177
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/index.ts +8 -7
- package/realtime-client/src/{pull-family-member.ts → pull-atom-family-member.ts} +2 -2
- package/realtime-client/src/{pull-state.ts → pull-atom.ts} +2 -2
- package/realtime-client/src/{pull-mutable-family-member.ts → pull-mutable-atom-family-member.ts} +6 -6
- package/realtime-client/src/{pull-mutable.ts → pull-mutable-atom.ts} +1 -1
- package/realtime-client/src/pull-selector-family-member.ts +42 -0
- package/realtime-client/src/pull-selector.ts +38 -0
- package/realtime-client/src/realtime-client-stores/client-main-store.ts +12 -2
- package/realtime-client/src/realtime-client-stores/client-sync-store.ts +7 -7
- package/realtime-client/src/sync-continuity.ts +368 -0
- package/realtime-react/dist/index.cjs +367 -27
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +24 -8
- package/realtime-react/dist/index.js +38 -22
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/index.ts +6 -5
- package/realtime-react/src/use-pull-atom-family-member.ts +21 -0
- package/realtime-react/src/{use-sync.ts → use-pull-atom.ts} +4 -4
- package/realtime-react/src/{use-pull-mutable.ts → use-pull-mutable-atom.ts} +4 -3
- package/realtime-react/src/use-pull-mutable-family-member.ts +9 -4
- package/realtime-react/src/use-pull-selector-family-member.ts +21 -0
- package/realtime-react/src/{use-pull.ts → use-pull-selector.ts} +7 -5
- package/realtime-react/src/use-push.ts +3 -2
- package/realtime-react/src/use-server-action.ts +3 -2
- package/realtime-react/src/use-sync-continuity.ts +12 -0
- package/realtime-server/dist/index.cjs +769 -371
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.ts +130 -60
- package/realtime-server/dist/index.js +753 -361
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/src/index.ts +17 -3
- package/realtime-server/src/ipc-sockets/child-socket.ts +135 -0
- package/realtime-server/src/ipc-sockets/custom-socket.ts +90 -0
- package/realtime-server/src/ipc-sockets/index.ts +3 -0
- package/realtime-server/src/ipc-sockets/parent-socket.ts +185 -0
- package/realtime-server/src/realtime-action-receiver.ts +8 -5
- package/realtime-server/src/realtime-continuity-synchronizer.ts +376 -0
- package/realtime-server/src/realtime-family-provider.ts +30 -71
- package/realtime-server/src/realtime-mutable-family-provider.ts +24 -86
- package/realtime-server/src/realtime-server-stores/index.ts +4 -1
- package/realtime-server/src/realtime-server-stores/realtime-continuity-store.ts +109 -0
- package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +64 -0
- package/realtime-server/src/realtime-server-stores/server-room-external-store.ts +42 -0
- package/realtime-server/src/realtime-server-stores/server-sync-store.ts +51 -98
- package/realtime-server/src/realtime-server-stores/server-user-store.ts +14 -29
- package/realtime-server/src/realtime-state-receiver.ts +0 -1
- package/realtime-testing/dist/index.cjs +34 -32
- package/realtime-testing/dist/index.cjs.map +1 -1
- package/realtime-testing/dist/index.d.ts +1 -0
- package/realtime-testing/dist/index.js +33 -31
- package/realtime-testing/dist/index.js.map +1 -1
- package/realtime-testing/src/setup-realtime-test.tsx +44 -32
- package/src/atom.ts +49 -31
- package/src/logger.ts +14 -5
- package/src/selector.ts +44 -25
- package/src/subscribe.ts +2 -1
- package/src/timeline.ts +4 -4
- package/src/transaction.ts +13 -17
- package/src/validators.ts +15 -9
- package/dist/chunk-H4Q5FTPZ.js +0 -11
- package/dist/chunk-H4Q5FTPZ.js.map +0 -1
- package/internal/src/set-state/copy-mutable-in-transaction.ts +0 -19
- package/realtime-client/src/sync-server-action.ts +0 -170
- package/realtime-client/src/sync-state.ts +0 -19
- package/realtime-react/src/use-pull-family-member.ts +0 -16
- package/realtime-react/src/use-sync-server-action.ts +0 -16
- package/realtime-server/src/realtime-action-synchronizer.ts +0 -152
|
@@ -1,118 +1,728 @@
|
|
|
1
1
|
import { __spreadProps, __spreadValues } from '../../dist/chunk-PZLG2HP3.js';
|
|
2
|
+
import { parseJson, stringifyJson } from 'atom.io/json';
|
|
3
|
+
import { getUpdateToken, IMPLICIT, Subject, findInStore, getFromStore, subscribeToState, getJsonToken, isRootStore, subscribeToTransaction, actUponStore, setIntoStore } from 'atom.io/internal';
|
|
4
|
+
import { SetRTX } from 'atom.io/transceivers/set-rtx';
|
|
2
5
|
import * as AtomIO from 'atom.io';
|
|
3
|
-
import {
|
|
6
|
+
import { selectorFamily, atomFamily, atom } from 'atom.io';
|
|
7
|
+
import { SyncGroup, roomIndex, usersInRooms } from 'atom.io/realtime';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
4
9
|
import { join } from 'atom.io/data';
|
|
5
|
-
import { SetRTX } from 'atom.io/transceivers/set-rtx';
|
|
6
|
-
import { IMPLICIT, getJsonToken, getUpdateToken, findInStore, getFromStore, setIntoStore, subscribeToState, subscribeToTransaction } from 'atom.io/internal';
|
|
7
|
-
import { parseJson } from 'atom.io/json';
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
// realtime-server/src/ipc-sockets/custom-socket.ts
|
|
12
|
+
var CustomSocket = class {
|
|
13
|
+
constructor(emit) {
|
|
14
|
+
this.emit = emit;
|
|
15
|
+
this.id = `no_id_retrieved`;
|
|
16
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
17
|
+
this.globalListeners = /* @__PURE__ */ new Set();
|
|
18
|
+
}
|
|
19
|
+
handleEvent(event, ...args) {
|
|
20
|
+
for (const listener of this.globalListeners) {
|
|
21
|
+
listener(event, ...args);
|
|
22
|
+
}
|
|
23
|
+
const listeners = this.listeners.get(event);
|
|
24
|
+
if (listeners) {
|
|
25
|
+
for (const listener of listeners) {
|
|
26
|
+
listener(...args);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
on(event, listener) {
|
|
31
|
+
const listeners = this.listeners.get(event);
|
|
32
|
+
if (listeners) {
|
|
33
|
+
listeners.add(listener);
|
|
34
|
+
} else {
|
|
35
|
+
this.listeners.set(event, /* @__PURE__ */ new Set([listener]));
|
|
36
|
+
}
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
onAny(listener) {
|
|
40
|
+
this.globalListeners.add(listener);
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
off(event, listener) {
|
|
44
|
+
const listeners = this.listeners.get(event);
|
|
45
|
+
if (listeners) {
|
|
46
|
+
if (listener) {
|
|
47
|
+
listeners.delete(listener);
|
|
48
|
+
} else {
|
|
49
|
+
this.listeners.delete(event);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
offAny(listener) {
|
|
55
|
+
this.globalListeners.delete(listener);
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// realtime-server/src/ipc-sockets/child-socket.ts
|
|
61
|
+
var ChildSocket = class extends CustomSocket {
|
|
62
|
+
constructor(process2, key, logger = console) {
|
|
63
|
+
super((event, ...args) => {
|
|
64
|
+
const stringifiedEvent = JSON.stringify([event, ...args]) + ``;
|
|
65
|
+
const errorHandler = (err) => {
|
|
66
|
+
if (err.code === `EPIPE`) {
|
|
67
|
+
console.error(`EPIPE error during write`, this.process.stdin);
|
|
68
|
+
}
|
|
69
|
+
this.process.stdin.removeListener(`error`, errorHandler);
|
|
70
|
+
};
|
|
71
|
+
this.process.stdin.once(`error`, errorHandler);
|
|
72
|
+
this.process.stdin.write(stringifiedEvent);
|
|
73
|
+
return this;
|
|
74
|
+
});
|
|
75
|
+
this.process = process2;
|
|
76
|
+
this.key = key;
|
|
77
|
+
this.logger = logger;
|
|
78
|
+
this.incompleteData = ``;
|
|
79
|
+
this.unprocessedEvents = [];
|
|
80
|
+
this.incompleteLog = ``;
|
|
81
|
+
this.unprocessedLogs = [];
|
|
82
|
+
this.id = `#####`;
|
|
83
|
+
this.process = process2;
|
|
84
|
+
this.process.stdout.on(
|
|
85
|
+
`data`,
|
|
86
|
+
(buffer) => {
|
|
87
|
+
const chunk = buffer.toString();
|
|
88
|
+
if (chunk === `\u2728`) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.unprocessedEvents.push(...chunk.split(``));
|
|
92
|
+
const newInput = this.unprocessedEvents.shift();
|
|
93
|
+
this.incompleteData += newInput || ``;
|
|
94
|
+
try {
|
|
95
|
+
if (this.incompleteData.startsWith(`error`)) {
|
|
96
|
+
console.log(`\u2757`, this.incompleteData);
|
|
97
|
+
}
|
|
98
|
+
const parsedEvent = parseJson(this.incompleteData);
|
|
99
|
+
this.handleEvent(...parsedEvent);
|
|
100
|
+
while (this.unprocessedEvents.length > 0) {
|
|
101
|
+
const event = this.unprocessedEvents.shift();
|
|
102
|
+
if (event) {
|
|
103
|
+
if (this.unprocessedEvents.length === 0) {
|
|
104
|
+
this.incompleteData = event;
|
|
105
|
+
}
|
|
106
|
+
const parsedEvent2 = parseJson(event);
|
|
107
|
+
this.handleEvent(...parsedEvent2);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.incompleteData = ``;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
|
|
113
|
+
console.warn(this.incompleteData);
|
|
114
|
+
console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
|
|
115
|
+
console.error(error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
this.process.stderr.on(`data`, (buf) => {
|
|
120
|
+
var _a;
|
|
121
|
+
const chunk = buf.toString();
|
|
122
|
+
this.unprocessedLogs.push(...chunk.split(``));
|
|
123
|
+
const newInput = this.unprocessedLogs.shift();
|
|
124
|
+
this.incompleteLog += newInput || ``;
|
|
125
|
+
try {
|
|
126
|
+
const parsedLog = parseJson(this.incompleteLog);
|
|
127
|
+
this.handleLog(parsedLog);
|
|
128
|
+
while (this.unprocessedLogs.length > 0) {
|
|
129
|
+
this.incompleteLog = (_a = this.unprocessedLogs.shift()) != null ? _a : ``;
|
|
130
|
+
if (this.incompleteLog) {
|
|
131
|
+
const parsedLog2 = parseJson(this.incompleteLog);
|
|
132
|
+
this.handleLog(parsedLog2);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(`\u274C\u274C\u274C`);
|
|
137
|
+
console.error(this.incompleteLog);
|
|
138
|
+
console.error(error);
|
|
139
|
+
console.error(`\u274C\u274C\u274C\uFE0F`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
if (process2.pid) {
|
|
143
|
+
this.id = process2.pid.toString();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
handleLog(arg) {
|
|
147
|
+
if (Array.isArray(arg)) {
|
|
148
|
+
const [level, ...rest] = arg;
|
|
149
|
+
switch (level) {
|
|
150
|
+
case `i`:
|
|
151
|
+
this.logger.info(this.id, this.key, ...rest);
|
|
152
|
+
break;
|
|
153
|
+
case `w`:
|
|
154
|
+
this.logger.warn(this.id, this.key, ...rest);
|
|
155
|
+
break;
|
|
156
|
+
case `e`:
|
|
157
|
+
this.logger.error(this.id, this.key, ...rest);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
var SubjectSocket = class extends CustomSocket {
|
|
164
|
+
constructor(id) {
|
|
165
|
+
super((...args) => {
|
|
166
|
+
this.out.next(args);
|
|
167
|
+
return this;
|
|
168
|
+
});
|
|
169
|
+
this.id = `no_id_retrieved`;
|
|
170
|
+
this.disposalFunctions = [];
|
|
171
|
+
this.id = id;
|
|
172
|
+
this.in = new Subject();
|
|
173
|
+
this.out = new Subject();
|
|
174
|
+
this.in.subscribe(`socket`, (event) => {
|
|
175
|
+
this.handleEvent(...event);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
dispose() {
|
|
179
|
+
for (const dispose of this.disposalFunctions) {
|
|
180
|
+
dispose();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var ParentSocket = class extends CustomSocket {
|
|
185
|
+
constructor() {
|
|
186
|
+
var _a;
|
|
187
|
+
super((event, ...args) => {
|
|
188
|
+
const stringifiedEvent = JSON.stringify([event, ...args]);
|
|
189
|
+
this.process.stdout.write(stringifiedEvent + ``);
|
|
190
|
+
return this;
|
|
191
|
+
});
|
|
192
|
+
this.incompleteData = ``;
|
|
193
|
+
this.unprocessedEvents = [];
|
|
194
|
+
this.id = `#####`;
|
|
195
|
+
this.logger = {
|
|
196
|
+
info: (...args) => this.log(`i`, ...args),
|
|
197
|
+
warn: (...args) => this.log(`w`, ...args),
|
|
198
|
+
error: (...args) => this.log(`e`, ...args)
|
|
199
|
+
};
|
|
200
|
+
this.process = process;
|
|
201
|
+
this.process.stdin.resume();
|
|
202
|
+
this.relays = /* @__PURE__ */ new Map();
|
|
203
|
+
this.relayServices = [];
|
|
204
|
+
this.process.stdin.on(
|
|
205
|
+
`data`,
|
|
206
|
+
(buffer) => {
|
|
207
|
+
const chunk = buffer.toString();
|
|
208
|
+
this.unprocessedEvents.push(...chunk.split(``));
|
|
209
|
+
const newInput = this.unprocessedEvents.shift();
|
|
210
|
+
this.incompleteData += newInput || ``;
|
|
211
|
+
try {
|
|
212
|
+
const parsedEvent = parseJson(this.incompleteData);
|
|
213
|
+
this.logger.info(`\u{1F3B0}`, `received`, parsedEvent);
|
|
214
|
+
this.handleEvent(...parsedEvent);
|
|
215
|
+
while (this.unprocessedEvents.length > 0) {
|
|
216
|
+
const event = this.unprocessedEvents.shift();
|
|
217
|
+
if (event) {
|
|
218
|
+
if (this.unprocessedEvents.length === 0) {
|
|
219
|
+
this.incompleteData = event;
|
|
220
|
+
}
|
|
221
|
+
const parsedEvent2 = parseJson(event);
|
|
222
|
+
this.handleEvent(...parsedEvent2);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
this.incompleteData = ``;
|
|
226
|
+
} catch (thrown) {
|
|
227
|
+
if (thrown instanceof Error) {
|
|
228
|
+
this.logger.error(`\u2757`, thrown.message, thrown.cause, thrown.stack);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
this.on(`exit`, () => {
|
|
234
|
+
process.exit(0);
|
|
235
|
+
});
|
|
236
|
+
process.on(`exit`, () => {
|
|
237
|
+
this.logger.info(`\u{1F525}`, this.id, `exited`);
|
|
238
|
+
process.exit(0);
|
|
239
|
+
});
|
|
240
|
+
process.on(`end`, () => {
|
|
241
|
+
this.logger.info(`\u{1F525}`, this.id, `ended`);
|
|
242
|
+
process.exit(0);
|
|
243
|
+
});
|
|
244
|
+
process.on(`SIGTERM`, () => {
|
|
245
|
+
this.logger.error(`\u{1F525}`, this.id, `terminated`);
|
|
246
|
+
process.exit(0);
|
|
247
|
+
});
|
|
248
|
+
process.on(`SIGINT`, () => {
|
|
249
|
+
this.logger.error(`\u{1F525}`, this.id, `interrupted`);
|
|
250
|
+
process.exit(0);
|
|
251
|
+
});
|
|
252
|
+
if (process.pid) {
|
|
253
|
+
this.id = (_a = process.pid) == null ? void 0 : _a.toString();
|
|
254
|
+
}
|
|
255
|
+
this.on(`user-joins`, (username) => {
|
|
256
|
+
this.logger.info(`\u{1F464}`, `user`, username, `joined`);
|
|
257
|
+
const relay = new SubjectSocket(`user:${username}`);
|
|
258
|
+
this.relays.set(username, relay);
|
|
259
|
+
this.logger.info(
|
|
260
|
+
`\u{1F517}`,
|
|
261
|
+
`attaching services:`,
|
|
262
|
+
`[${[...this.relayServices.keys()].join(`, `)}]`
|
|
263
|
+
);
|
|
264
|
+
for (const attachServices of this.relayServices) {
|
|
265
|
+
const cleanup = attachServices(relay);
|
|
266
|
+
if (cleanup) {
|
|
267
|
+
relay.disposalFunctions.push(cleanup);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
this.on(`user:${username}`, (...data) => {
|
|
271
|
+
relay.in.next(data);
|
|
272
|
+
});
|
|
273
|
+
relay.out.subscribe(`socket`, (data) => {
|
|
274
|
+
this.emit(...data);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
this.on(`user-leaves`, (username) => {
|
|
278
|
+
const relay = this.relays.get(username);
|
|
279
|
+
this.off(`relay:${username}`);
|
|
280
|
+
if (relay) {
|
|
281
|
+
relay.dispose();
|
|
282
|
+
this.relays.delete(username);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
process.stdout.write(`\u2728`);
|
|
286
|
+
}
|
|
287
|
+
log(...args) {
|
|
288
|
+
this.process.stderr.write(
|
|
289
|
+
stringifyJson(
|
|
290
|
+
args.map(
|
|
291
|
+
(arg) => arg instanceof SetRTX ? `{ ${arg.toJSON().members.join(` | `)} }` : arg
|
|
292
|
+
)
|
|
293
|
+
) + ``
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
relay(attachServices) {
|
|
297
|
+
this.logger.info(`\u{1F517}`, `running relay method`);
|
|
298
|
+
this.relayServices.push(attachServices);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
selectorFamily({
|
|
302
|
+
key: `perspectiveRedactor`,
|
|
303
|
+
get: ({ userId, syncGroupKey }) => ({ get, find }) => {
|
|
304
|
+
const syncGroup = SyncGroup.existing.get(syncGroupKey);
|
|
305
|
+
if (!syncGroup) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
`Tried to create a synchronizer for a sync group that does not exist.`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
const userPerspectiveTokens = syncGroup.perspectives.flatMap(
|
|
311
|
+
({ viewAtoms }) => {
|
|
312
|
+
const userPerspectiveToken = find(viewAtoms, userId);
|
|
313
|
+
const userPerspective = get(userPerspectiveToken);
|
|
314
|
+
const visibleTokens = [...userPerspective].map((token) => {
|
|
315
|
+
return token.type === `mutable_atom` ? getUpdateToken(token).key : token.key;
|
|
316
|
+
});
|
|
317
|
+
IMPLICIT.STORE.logger.info(
|
|
318
|
+
`\u{1F52D}`,
|
|
319
|
+
`continuity`,
|
|
320
|
+
syncGroupKey,
|
|
321
|
+
`${userId} can see ${visibleTokens.length} tokens in ${viewAtoms.key}`,
|
|
322
|
+
visibleTokens
|
|
323
|
+
);
|
|
324
|
+
return visibleTokens;
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
const filterTransactionUpdate = (visible, transactionUpdate) => {
|
|
328
|
+
IMPLICIT.STORE.logger.info(
|
|
329
|
+
`\u{1F58C}`,
|
|
330
|
+
`continuity`,
|
|
331
|
+
syncGroupKey,
|
|
332
|
+
`redacting updates from ${transactionUpdate.epoch}:${transactionUpdate.key}:${transactionUpdate.id}`,
|
|
333
|
+
visible,
|
|
334
|
+
transactionUpdate.updates
|
|
335
|
+
);
|
|
336
|
+
const updates = transactionUpdate.updates.filter((update) => {
|
|
337
|
+
if (`newValue` in update) {
|
|
338
|
+
return visible.includes(update.key);
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
}).map((update) => {
|
|
342
|
+
if (`updates` in update) {
|
|
343
|
+
return filterTransactionUpdate(visible, update);
|
|
344
|
+
}
|
|
345
|
+
return update;
|
|
346
|
+
});
|
|
347
|
+
const filtered = __spreadProps(__spreadValues({}, transactionUpdate), {
|
|
348
|
+
updates
|
|
349
|
+
});
|
|
350
|
+
return filtered;
|
|
351
|
+
};
|
|
352
|
+
const filter = (update) => {
|
|
353
|
+
const visibleKeys = syncGroup.globals.map(
|
|
354
|
+
(atomToken) => atomToken.type === `mutable_atom` ? getUpdateToken(atomToken).key : atomToken.key
|
|
355
|
+
);
|
|
356
|
+
visibleKeys.push(...userPerspectiveTokens);
|
|
357
|
+
return filterTransactionUpdate(visibleKeys, update);
|
|
358
|
+
};
|
|
359
|
+
return filter;
|
|
360
|
+
}
|
|
15
361
|
});
|
|
16
|
-
var
|
|
17
|
-
key: `
|
|
18
|
-
|
|
19
|
-
cardinality: `1:1`
|
|
362
|
+
var roomArgumentsAtoms = atomFamily({
|
|
363
|
+
key: `roomArguments`,
|
|
364
|
+
default: [`echo`, [`Hello World!`]]
|
|
20
365
|
});
|
|
21
|
-
var
|
|
22
|
-
key: `
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
366
|
+
var roomSelectors = selectorFamily({
|
|
367
|
+
key: `room`,
|
|
368
|
+
get: (roomId) => async ({ get, find }) => {
|
|
369
|
+
const argumentsState = find(roomArgumentsAtoms, roomId);
|
|
370
|
+
const args = get(argumentsState);
|
|
371
|
+
const [script, options] = args;
|
|
372
|
+
const child = await new Promise(
|
|
373
|
+
(resolve) => {
|
|
374
|
+
const room = spawn(script, options, { env: process.env });
|
|
375
|
+
const resolver = (data) => {
|
|
376
|
+
if (data.toString() === `\u2728`) {
|
|
377
|
+
room.stdout.off(`data`, resolver);
|
|
378
|
+
resolve(room);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
room.stdout.on(`data`, resolver);
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
return new ChildSocket(child, roomId);
|
|
385
|
+
}
|
|
27
386
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
default: null
|
|
387
|
+
|
|
388
|
+
// realtime-server/src/realtime-server-stores/server-room-external-actions.ts
|
|
389
|
+
var createRoomTX = AtomIO.transaction({
|
|
390
|
+
key: `createRoom`,
|
|
391
|
+
do: ({ get, set, find }, roomId, script, options) => {
|
|
392
|
+
const args = options ? [script, options] : [script];
|
|
393
|
+
const roomArgumentsState = find(roomArgumentsAtoms, roomId);
|
|
394
|
+
set(roomArgumentsState, args);
|
|
395
|
+
set(roomIndex, (s) => s.add(roomId));
|
|
396
|
+
const roomState = find(roomSelectors, roomId);
|
|
397
|
+
const room = get(roomState);
|
|
398
|
+
return room;
|
|
399
|
+
}
|
|
42
400
|
});
|
|
43
|
-
var
|
|
44
|
-
key: `
|
|
45
|
-
|
|
401
|
+
var joinRoomTX = AtomIO.transaction({
|
|
402
|
+
key: `joinRoom`,
|
|
403
|
+
do: (transactors, roomId, userId, enteredAtEpoch) => {
|
|
404
|
+
const meta = { enteredAtEpoch };
|
|
405
|
+
usersInRooms.transact(transactors, ({ relations }) => {
|
|
406
|
+
relations.set(roomId, userId, meta);
|
|
407
|
+
});
|
|
408
|
+
return meta;
|
|
409
|
+
}
|
|
46
410
|
});
|
|
47
|
-
var
|
|
48
|
-
key: `
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return __spreadProps(__spreadValues({}, update), { updates: filter(update.updates) });
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
411
|
+
var leaveRoomTX = AtomIO.transaction({
|
|
412
|
+
key: `leaveRoom`,
|
|
413
|
+
do: (transactors, roomId, userId) => {
|
|
414
|
+
usersInRooms.transact(transactors, ({ relations }) => {
|
|
415
|
+
relations.delete({ room: roomId, user: userId });
|
|
416
|
+
});
|
|
56
417
|
}
|
|
57
418
|
});
|
|
58
|
-
var
|
|
59
|
-
key: `
|
|
60
|
-
|
|
419
|
+
var destroyRoomTX = AtomIO.transaction({
|
|
420
|
+
key: `destroyRoom`,
|
|
421
|
+
do: (transactors, roomId) => {
|
|
422
|
+
usersInRooms.transact(transactors, ({ relations }) => {
|
|
423
|
+
relations.delete({ room: roomId });
|
|
424
|
+
});
|
|
425
|
+
transactors.set(roomIndex, (s) => (s.delete(roomId), s));
|
|
426
|
+
}
|
|
61
427
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const userKey = get(userKeyState);
|
|
67
|
-
if (!userKey) {
|
|
68
|
-
return [];
|
|
428
|
+
function redactTransactionUpdateContent(visibleStateKeys, updates) {
|
|
429
|
+
return updates.map((update) => {
|
|
430
|
+
if (`newValue` in update) {
|
|
431
|
+
return update;
|
|
69
432
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
433
|
+
const redacted = redactTransactionUpdateContent(
|
|
434
|
+
visibleStateKeys,
|
|
435
|
+
update.updates
|
|
73
436
|
);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
|
|
79
|
-
const userKey = get(userKeyState);
|
|
80
|
-
if (!userKey) {
|
|
81
|
-
return;
|
|
437
|
+
return __spreadProps(__spreadValues({}, update), { updates: redacted });
|
|
438
|
+
}).filter((update) => {
|
|
439
|
+
if (`newValue` in update) {
|
|
440
|
+
return visibleStateKeys.includes(update.key);
|
|
82
441
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
442
|
+
return true;
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
var actionOcclusionAtoms = atomFamily({
|
|
446
|
+
key: `transactionRedactor`,
|
|
447
|
+
default: { occlude: (updates) => updates }
|
|
89
448
|
});
|
|
90
|
-
var
|
|
91
|
-
key: `
|
|
449
|
+
var userUnacknowledgedQueues = atomFamily({
|
|
450
|
+
key: `unacknowledgedUpdates`,
|
|
451
|
+
default: () => []
|
|
452
|
+
});
|
|
453
|
+
var socketAtoms = atomFamily({
|
|
454
|
+
key: `sockets`,
|
|
92
455
|
default: null
|
|
93
456
|
});
|
|
94
|
-
var
|
|
95
|
-
key: `
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
457
|
+
var socketIndex = atom({
|
|
458
|
+
key: `socketsIndex`,
|
|
459
|
+
mutable: true,
|
|
460
|
+
default: () => new SetRTX(),
|
|
461
|
+
toJson: (set) => set.toJSON(),
|
|
462
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
463
|
+
});
|
|
464
|
+
var userIndex = atom({
|
|
465
|
+
key: `usersIndex`,
|
|
466
|
+
mutable: true,
|
|
467
|
+
default: () => new SetRTX(),
|
|
468
|
+
toJson: (set) => set.toJSON(),
|
|
469
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
470
|
+
});
|
|
471
|
+
var usersOfSockets = join({
|
|
472
|
+
key: `usersOfSockets`,
|
|
473
|
+
between: [`user`, `socket`],
|
|
474
|
+
cardinality: `1:1`
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
// realtime-server/src/realtime-continuity-synchronizer.ts
|
|
478
|
+
function realtimeContinuitySynchronizer({
|
|
479
|
+
socket: initialSocket,
|
|
480
|
+
store = IMPLICIT.STORE
|
|
481
|
+
}) {
|
|
482
|
+
return function synchronizer(continuity) {
|
|
483
|
+
let socket = initialSocket;
|
|
484
|
+
const continuityKey = continuity.key;
|
|
485
|
+
const userKeyState = findInStore(
|
|
486
|
+
usersOfSockets.states.userKeyOfSocket,
|
|
487
|
+
socket.id,
|
|
488
|
+
store
|
|
489
|
+
);
|
|
490
|
+
const userKey = getFromStore(userKeyState, store);
|
|
109
491
|
if (!userKey) {
|
|
110
|
-
|
|
492
|
+
store.logger.error(
|
|
493
|
+
`\u274C`,
|
|
494
|
+
`continuity`,
|
|
495
|
+
continuityKey,
|
|
496
|
+
`Tried to create a synchronizer for a socket (${socket.id}) that is not connected to a user.`
|
|
497
|
+
);
|
|
498
|
+
return () => {
|
|
499
|
+
};
|
|
111
500
|
}
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
501
|
+
const socketKeyState = findInStore(
|
|
502
|
+
usersOfSockets.states.socketKeyOfUser,
|
|
503
|
+
userKey,
|
|
504
|
+
store
|
|
505
|
+
);
|
|
506
|
+
subscribeToState(
|
|
507
|
+
socketKeyState,
|
|
508
|
+
({ newValue: newSocketKey }) => {
|
|
509
|
+
store.logger.info(
|
|
510
|
+
`\u{1F44B}`,
|
|
511
|
+
`continuity`,
|
|
512
|
+
continuityKey,
|
|
513
|
+
`seeing ${userKey} on new socket ${newSocketKey}`
|
|
514
|
+
);
|
|
515
|
+
if (newSocketKey === null) {
|
|
516
|
+
store.logger.error(
|
|
517
|
+
`\u274C`,
|
|
518
|
+
`continuity`,
|
|
519
|
+
continuityKey,
|
|
520
|
+
`Tried to create a synchronizer for a user (${userKey}) that is not connected to a socket.`
|
|
521
|
+
);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const newSocketState = findInStore(socketAtoms, newSocketKey, store);
|
|
525
|
+
const newSocket = getFromStore(newSocketState, store);
|
|
526
|
+
socket = newSocket;
|
|
527
|
+
},
|
|
528
|
+
`sync-continuity:${continuityKey}:${userKey}`,
|
|
529
|
+
store
|
|
530
|
+
);
|
|
531
|
+
const userUnacknowledgedQueue = findInStore(
|
|
532
|
+
userUnacknowledgedQueues,
|
|
533
|
+
userKey,
|
|
534
|
+
store
|
|
535
|
+
);
|
|
536
|
+
getFromStore(
|
|
537
|
+
userUnacknowledgedQueue,
|
|
538
|
+
store
|
|
539
|
+
);
|
|
540
|
+
const unsubscribeFunctions = [];
|
|
541
|
+
const revealPerspectives = () => {
|
|
542
|
+
const unsubscribeFunctions2 = [];
|
|
543
|
+
for (const perspective of continuity.perspectives) {
|
|
544
|
+
const { viewAtoms } = perspective;
|
|
545
|
+
const userViewState = findInStore(viewAtoms, userKey, store);
|
|
546
|
+
const unsubscribe = subscribeToState(
|
|
547
|
+
userViewState,
|
|
548
|
+
({ oldValue, newValue }) => {
|
|
549
|
+
const oldKeys = oldValue.map((token) => token.key);
|
|
550
|
+
const newKeys = newValue.map((token) => token.key);
|
|
551
|
+
const concealed = oldValue.filter(
|
|
552
|
+
(token) => !newKeys.includes(token.key)
|
|
553
|
+
);
|
|
554
|
+
const revealed = newValue.filter((token) => !oldKeys.includes(token.key)).flatMap((token) => {
|
|
555
|
+
const resourceToken = token.type === `mutable_atom` ? getJsonToken(token) : token;
|
|
556
|
+
const resource = getFromStore(resourceToken, store);
|
|
557
|
+
return [resourceToken, resource];
|
|
558
|
+
});
|
|
559
|
+
store.logger.info(
|
|
560
|
+
`\u{1F441}`,
|
|
561
|
+
`atom`,
|
|
562
|
+
perspective.resourceAtoms.key,
|
|
563
|
+
`${userKey} has a new perspective`,
|
|
564
|
+
{ oldKeys, newKeys, revealed, concealed }
|
|
565
|
+
);
|
|
566
|
+
if (revealed.length > 0) {
|
|
567
|
+
socket == null ? void 0 : socket.emit(`reveal:${continuityKey}`, revealed);
|
|
568
|
+
}
|
|
569
|
+
if (concealed.length > 0) {
|
|
570
|
+
socket == null ? void 0 : socket.emit(`conceal:${continuityKey}`, concealed);
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
`sync-continuity:${continuityKey}:${userKey}:perspective:${perspective.resourceAtoms.key}`,
|
|
574
|
+
store
|
|
575
|
+
);
|
|
576
|
+
unsubscribeFunctions2.push(unsubscribe);
|
|
577
|
+
}
|
|
578
|
+
return () => {
|
|
579
|
+
for (const unsubscribe of unsubscribeFunctions2)
|
|
580
|
+
unsubscribe();
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
const unsubscribeFromPerspectives = revealPerspectives();
|
|
584
|
+
const sendInitialPayload = () => {
|
|
585
|
+
var _a;
|
|
586
|
+
const initialPayload = [];
|
|
587
|
+
for (const atom2 of continuity.globals) {
|
|
588
|
+
const resourceToken = atom2.type === `mutable_atom` ? getJsonToken(atom2) : atom2;
|
|
589
|
+
initialPayload.push(resourceToken, getFromStore(atom2, store));
|
|
590
|
+
}
|
|
591
|
+
for (const perspective of continuity.perspectives) {
|
|
592
|
+
const { viewAtoms, resourceAtoms } = perspective;
|
|
593
|
+
const userViewState = findInStore(viewAtoms, userKey, store);
|
|
594
|
+
const userView = getFromStore(userViewState, store);
|
|
595
|
+
store.logger.info(`\u{1F441}`, `atom`, resourceAtoms.key, `${userKey} can see`, {
|
|
596
|
+
viewAtoms,
|
|
597
|
+
resourceAtoms,
|
|
598
|
+
userView
|
|
599
|
+
});
|
|
600
|
+
for (const visibleToken of userView) {
|
|
601
|
+
const resourceToken = visibleToken.type === `mutable_atom` ? getJsonToken(visibleToken) : visibleToken;
|
|
602
|
+
const resource = getFromStore(resourceToken, store);
|
|
603
|
+
initialPayload.push(resourceToken, resource);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
const epoch = isRootStore(store) ? (_a = store.transactionMeta.epoch.get(continuityKey)) != null ? _a : null : null;
|
|
607
|
+
socket == null ? void 0 : socket.emit(`continuity-init:${continuityKey}`, epoch, initialPayload);
|
|
608
|
+
for (const transaction2 of continuity.actions) {
|
|
609
|
+
const unsubscribeFromTransaction = subscribeToTransaction(
|
|
610
|
+
transaction2,
|
|
611
|
+
(update) => {
|
|
612
|
+
try {
|
|
613
|
+
const visibleKeys = continuity.globals.map((atom2) => atom2.key).concat(
|
|
614
|
+
continuity.perspectives.flatMap((perspective) => {
|
|
615
|
+
const { viewAtoms } = perspective;
|
|
616
|
+
const userPerspectiveTokenState = findInStore(
|
|
617
|
+
viewAtoms,
|
|
618
|
+
userKey,
|
|
619
|
+
store
|
|
620
|
+
);
|
|
621
|
+
const visibleTokens = getFromStore(
|
|
622
|
+
userPerspectiveTokenState,
|
|
623
|
+
store
|
|
624
|
+
);
|
|
625
|
+
return visibleTokens.map((token) => {
|
|
626
|
+
const key = token.type === `mutable_atom` ? `*` + token.key : token.key;
|
|
627
|
+
return key;
|
|
628
|
+
});
|
|
629
|
+
})
|
|
630
|
+
);
|
|
631
|
+
const redactedUpdates = redactTransactionUpdateContent(
|
|
632
|
+
visibleKeys,
|
|
633
|
+
update.updates
|
|
634
|
+
);
|
|
635
|
+
const redactedUpdate = __spreadProps(__spreadValues({}, update), {
|
|
636
|
+
updates: redactedUpdates
|
|
637
|
+
});
|
|
638
|
+
socket == null ? void 0 : socket.emit(
|
|
639
|
+
`tx-new:${continuityKey}`,
|
|
640
|
+
redactedUpdate
|
|
641
|
+
);
|
|
642
|
+
} catch (thrown) {
|
|
643
|
+
if (thrown instanceof Error) {
|
|
644
|
+
store.logger.error(
|
|
645
|
+
`\u274C`,
|
|
646
|
+
`continuity`,
|
|
647
|
+
continuityKey,
|
|
648
|
+
`failed to send update from transaction ${transaction2.key} to ${userKey}`,
|
|
649
|
+
thrown.message
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
`sync-continuity:${continuityKey}:${userKey}`,
|
|
655
|
+
store
|
|
656
|
+
);
|
|
657
|
+
unsubscribeFunctions.push(unsubscribeFromTransaction);
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
socket.off(`get:${continuityKey}`, sendInitialPayload);
|
|
661
|
+
socket.on(`get:${continuityKey}`, sendInitialPayload);
|
|
662
|
+
const fillTransactionRequest = (update) => {
|
|
663
|
+
store.logger.info(`\u{1F6CE}\uFE0F`, `continuity`, continuityKey, `received`, update);
|
|
664
|
+
const transactionKey = update.key;
|
|
665
|
+
const updateId = update.id;
|
|
666
|
+
const performanceKey = `tx-run:${transactionKey}:${updateId}`;
|
|
667
|
+
const performanceKeyStart = `${performanceKey}:start`;
|
|
668
|
+
const performanceKeyEnd = `${performanceKey}:end`;
|
|
669
|
+
performance.mark(performanceKeyStart);
|
|
670
|
+
try {
|
|
671
|
+
actUponStore(
|
|
672
|
+
{ type: `transaction`, key: transactionKey },
|
|
673
|
+
updateId,
|
|
674
|
+
store
|
|
675
|
+
)(...update.params);
|
|
676
|
+
} catch (thrown) {
|
|
677
|
+
if (thrown instanceof Error) {
|
|
678
|
+
store.logger.error(
|
|
679
|
+
`\u274C`,
|
|
680
|
+
`continuity`,
|
|
681
|
+
continuityKey,
|
|
682
|
+
`failed to run transaction ${transactionKey} with update ${updateId}`,
|
|
683
|
+
thrown.message
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
performance.mark(performanceKeyEnd);
|
|
688
|
+
const metric = performance.measure(
|
|
689
|
+
performanceKey,
|
|
690
|
+
performanceKeyStart,
|
|
691
|
+
performanceKeyEnd
|
|
692
|
+
);
|
|
693
|
+
store == null ? void 0 : store.logger.info(
|
|
694
|
+
`\u{1F680}`,
|
|
695
|
+
`transaction`,
|
|
696
|
+
transactionKey,
|
|
697
|
+
updateId,
|
|
698
|
+
metric.duration
|
|
699
|
+
);
|
|
700
|
+
const valuesOfCardsViewKey = `valuesOfCardsView("${userKey}")`;
|
|
701
|
+
const rootsOfCardValueView = store.selectorAtoms.getRelatedKeys(valuesOfCardsViewKey);
|
|
702
|
+
const myCardValueView = store.valueMap.get(valuesOfCardsViewKey);
|
|
703
|
+
store.logger.info(
|
|
704
|
+
`\u{1F441}`,
|
|
705
|
+
`continuity`,
|
|
706
|
+
continuityKey,
|
|
707
|
+
`seeing ${userKey} card values`,
|
|
708
|
+
{
|
|
709
|
+
valuesOfCardsViewKey,
|
|
710
|
+
rootsOfCardValueView,
|
|
711
|
+
myCardValueView
|
|
712
|
+
}
|
|
713
|
+
);
|
|
714
|
+
};
|
|
715
|
+
socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
716
|
+
socket.on(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
717
|
+
return () => {
|
|
718
|
+
for (const unsubscribe of unsubscribeFunctions)
|
|
719
|
+
unsubscribe();
|
|
720
|
+
unsubscribeFromPerspectives();
|
|
721
|
+
socket == null ? void 0 : socket.off(`get:${continuityKey}`, sendInitialPayload);
|
|
722
|
+
socket == null ? void 0 : socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
723
|
+
};
|
|
724
|
+
};
|
|
725
|
+
}
|
|
116
726
|
function realtimeStateProvider({
|
|
117
727
|
socket,
|
|
118
728
|
store = IMPLICIT.STORE
|
|
@@ -162,89 +772,49 @@ function realtimeStateSynchronizer({
|
|
|
162
772
|
};
|
|
163
773
|
};
|
|
164
774
|
}
|
|
165
|
-
function
|
|
775
|
+
function realtimeAtomFamilyProvider({
|
|
166
776
|
socket,
|
|
167
777
|
store = IMPLICIT.STORE
|
|
168
778
|
}) {
|
|
169
779
|
return function familyProvider(family, index) {
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
unsub();
|
|
175
|
-
}
|
|
176
|
-
unsubFamilyCallbacksByKey.clear();
|
|
177
|
-
socket.off(`unsub:${family.key}`, fillFamilyUnsubRequest);
|
|
178
|
-
};
|
|
179
|
-
const fillSingleUnsubRequest = (key) => {
|
|
180
|
-
socket.off(`unsub:${key}`, fillSingleUnsubRequest);
|
|
181
|
-
const unsub = unsubSingleCallbacksByKey.get(key);
|
|
780
|
+
const unsubCallbacksByKey = /* @__PURE__ */ new Map();
|
|
781
|
+
const fillUnsubRequest = (key) => {
|
|
782
|
+
socket.off(`unsub:${key}`, fillUnsubRequest);
|
|
783
|
+
const unsub = unsubCallbacksByKey.get(key);
|
|
182
784
|
if (unsub) {
|
|
183
785
|
unsub();
|
|
184
|
-
|
|
786
|
+
unsubCallbacksByKey.delete(key);
|
|
185
787
|
}
|
|
186
788
|
};
|
|
187
789
|
const fillSubRequest = (subKey) => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
790
|
+
const exposedSubKeys = getFromStore(index, store);
|
|
791
|
+
for (const exposedSubKey of exposedSubKeys) {
|
|
792
|
+
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
793
|
+
const token = findInStore(family, subKey, store);
|
|
794
|
+
socket.emit(`serve:${token.key}`, getFromStore(token, store));
|
|
795
|
+
const unsubscribe = subscribeToState(
|
|
796
|
+
token,
|
|
797
|
+
({ newValue }) => {
|
|
798
|
+
socket.emit(`serve:${token.key}`, newValue);
|
|
799
|
+
},
|
|
800
|
+
`expose-family:${family.key}:${socket.id}`,
|
|
801
|
+
store
|
|
197
802
|
);
|
|
803
|
+
unsubCallbacksByKey.set(token.key, unsubscribe);
|
|
804
|
+
socket.on(`unsub:${token.key}`, () => {
|
|
805
|
+
fillUnsubRequest(token.key);
|
|
806
|
+
});
|
|
807
|
+
break;
|
|
198
808
|
}
|
|
199
|
-
const unsubscribeFromTokenCreation = family.subject.subscribe(
|
|
200
|
-
`expose-family:${socket.id}`,
|
|
201
|
-
(token) => {
|
|
202
|
-
const unsub = subscribeToState(
|
|
203
|
-
token,
|
|
204
|
-
({ newValue }) => {
|
|
205
|
-
var _a2;
|
|
206
|
-
socket.emit(
|
|
207
|
-
`serve:${family.key}`,
|
|
208
|
-
parseJson(((_a2 = token.family) == null ? void 0 : _a2.subKey) || `null`),
|
|
209
|
-
newValue
|
|
210
|
-
);
|
|
211
|
-
},
|
|
212
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
213
|
-
store
|
|
214
|
-
);
|
|
215
|
-
unsubFamilyCallbacksByKey.set(token.key, unsub);
|
|
216
|
-
}
|
|
217
|
-
);
|
|
218
|
-
unsubFamilyCallbacksByKey.set(family.key, unsubscribeFromTokenCreation);
|
|
219
|
-
socket.on(`unsub:${family.key}`, fillFamilyUnsubRequest);
|
|
220
|
-
} else {
|
|
221
|
-
const token = family(subKey);
|
|
222
|
-
socket.emit(`serve:${token.key}`, getFromStore(token, store));
|
|
223
|
-
const unsubscribe = subscribeToState(
|
|
224
|
-
token,
|
|
225
|
-
({ newValue }) => {
|
|
226
|
-
socket.emit(`serve:${token.key}`, newValue);
|
|
227
|
-
},
|
|
228
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
229
|
-
store
|
|
230
|
-
);
|
|
231
|
-
unsubSingleCallbacksByKey.set(token.key, unsubscribe);
|
|
232
|
-
socket.on(`unsub:${token.key}`, () => {
|
|
233
|
-
fillSingleUnsubRequest(token.key);
|
|
234
|
-
});
|
|
235
809
|
}
|
|
236
810
|
};
|
|
237
811
|
socket.on(`sub:${family.key}`, fillSubRequest);
|
|
238
812
|
return () => {
|
|
239
813
|
socket.off(`sub:${family.key}`, fillSubRequest);
|
|
240
|
-
for (const [, unsub] of
|
|
241
|
-
unsub();
|
|
242
|
-
}
|
|
243
|
-
for (const [, unsub] of unsubSingleCallbacksByKey) {
|
|
814
|
+
for (const [, unsub] of unsubCallbacksByKey) {
|
|
244
815
|
unsub();
|
|
245
816
|
}
|
|
246
|
-
|
|
247
|
-
unsubSingleCallbacksByKey.clear();
|
|
817
|
+
unsubCallbacksByKey.clear();
|
|
248
818
|
};
|
|
249
819
|
};
|
|
250
820
|
}
|
|
@@ -285,110 +855,46 @@ function realtimeMutableFamilyProvider({
|
|
|
285
855
|
store = IMPLICIT.STORE
|
|
286
856
|
}) {
|
|
287
857
|
return function mutableFamilyProvider(family, index) {
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
unsub();
|
|
293
|
-
}
|
|
294
|
-
unsubFamilyCallbacksByKey.clear();
|
|
295
|
-
socket.off(`unsub:${family.key}`, fillFamilyUnsubRequest);
|
|
296
|
-
};
|
|
297
|
-
const fillSingleUnsubRequest = (key) => {
|
|
298
|
-
socket.off(`unsub:${key}`, fillSingleUnsubRequest);
|
|
299
|
-
const unsub = unsubSingleCallbacksByKey.get(key);
|
|
858
|
+
const unsubCallbacksByKey = /* @__PURE__ */ new Map();
|
|
859
|
+
const fillUnsubRequest = (key) => {
|
|
860
|
+
socket.off(`unsub:${key}`, fillUnsubRequest);
|
|
861
|
+
const unsub = unsubCallbacksByKey.get(key);
|
|
300
862
|
if (unsub) {
|
|
301
863
|
unsub();
|
|
302
|
-
|
|
864
|
+
unsubCallbacksByKey.delete(key);
|
|
303
865
|
}
|
|
304
866
|
};
|
|
305
867
|
const fillSubRequest = (subKey) => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const token = findInStore(family, key, store);
|
|
868
|
+
const exposedSubKeys = getFromStore(index, store);
|
|
869
|
+
for (const exposedSubKey of exposedSubKeys) {
|
|
870
|
+
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
871
|
+
const token = findInStore(family, subKey, store);
|
|
311
872
|
const jsonToken = getJsonToken(token);
|
|
312
|
-
const
|
|
313
|
-
socket.emit(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
getFromStore(jsonToken, store)
|
|
317
|
-
);
|
|
318
|
-
const unsubFromUpdates = subscribeToState(
|
|
319
|
-
trackerToken,
|
|
873
|
+
const updateToken = getUpdateToken(token);
|
|
874
|
+
socket.emit(`init:${token.key}`, getFromStore(jsonToken, store));
|
|
875
|
+
const unsubscribe = subscribeToState(
|
|
876
|
+
updateToken,
|
|
320
877
|
({ newValue }) => {
|
|
321
|
-
|
|
322
|
-
socket.emit(
|
|
323
|
-
`next:${token.key}`,
|
|
324
|
-
parseJson(((_a2 = jsonToken.family) == null ? void 0 : _a2.subKey) || `null`),
|
|
325
|
-
newValue
|
|
326
|
-
);
|
|
878
|
+
socket.emit(`next:${token.key}`, newValue);
|
|
327
879
|
},
|
|
328
880
|
`expose-family:${family.key}:${socket.id}`,
|
|
329
881
|
store
|
|
330
882
|
);
|
|
331
|
-
|
|
883
|
+
unsubCallbacksByKey.set(token.key, unsubscribe);
|
|
884
|
+
socket.on(`unsub:${token.key}`, () => {
|
|
885
|
+
fillUnsubRequest(token.key);
|
|
886
|
+
});
|
|
887
|
+
break;
|
|
332
888
|
}
|
|
333
|
-
const unsubscribeFromTokenCreation = family.subject.subscribe(
|
|
334
|
-
`expose-family:${socket.id}`,
|
|
335
|
-
(token) => {
|
|
336
|
-
var _a2;
|
|
337
|
-
const jsonToken = getJsonToken(token);
|
|
338
|
-
const trackerToken = getUpdateToken(token);
|
|
339
|
-
socket.emit(
|
|
340
|
-
`init:${family.key}`,
|
|
341
|
-
parseJson(((_a2 = jsonToken.family) == null ? void 0 : _a2.subKey) || `null`),
|
|
342
|
-
getFromStore(jsonToken, store)
|
|
343
|
-
);
|
|
344
|
-
const unsubFromUpdates = subscribeToState(
|
|
345
|
-
trackerToken,
|
|
346
|
-
({ newValue }) => {
|
|
347
|
-
var _a3;
|
|
348
|
-
socket.emit(
|
|
349
|
-
`next:${token.key}`,
|
|
350
|
-
parseJson(((_a3 = jsonToken.family) == null ? void 0 : _a3.subKey) || `null`),
|
|
351
|
-
newValue
|
|
352
|
-
);
|
|
353
|
-
},
|
|
354
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
355
|
-
store
|
|
356
|
-
);
|
|
357
|
-
unsubFamilyCallbacksByKey.set(token.key, unsubFromUpdates);
|
|
358
|
-
}
|
|
359
|
-
);
|
|
360
|
-
unsubFamilyCallbacksByKey.set(family.key, unsubscribeFromTokenCreation);
|
|
361
|
-
socket.on(`unsub:${family.key}`, fillFamilyUnsubRequest);
|
|
362
|
-
} else {
|
|
363
|
-
const token = family(subKey);
|
|
364
|
-
const jsonToken = getJsonToken(token);
|
|
365
|
-
const updateToken = getUpdateToken(token);
|
|
366
|
-
socket.emit(`init:${token.key}`, getFromStore(jsonToken, store));
|
|
367
|
-
const unsubscribe = subscribeToState(
|
|
368
|
-
updateToken,
|
|
369
|
-
({ newValue }) => {
|
|
370
|
-
socket.emit(`next:${token.key}`, newValue);
|
|
371
|
-
},
|
|
372
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
373
|
-
store
|
|
374
|
-
);
|
|
375
|
-
unsubSingleCallbacksByKey.set(token.key, unsubscribe);
|
|
376
|
-
socket.on(`unsub:${token.key}`, () => {
|
|
377
|
-
fillSingleUnsubRequest(token.key);
|
|
378
|
-
});
|
|
379
889
|
}
|
|
380
890
|
};
|
|
381
891
|
socket.on(`sub:${family.key}`, fillSubRequest);
|
|
382
892
|
return () => {
|
|
383
893
|
socket.off(`sub:${family.key}`, fillSubRequest);
|
|
384
|
-
for (const [, unsub] of
|
|
385
|
-
unsub();
|
|
386
|
-
}
|
|
387
|
-
for (const [, unsub] of unsubSingleCallbacksByKey) {
|
|
894
|
+
for (const [, unsub] of unsubCallbacksByKey) {
|
|
388
895
|
unsub();
|
|
389
896
|
}
|
|
390
|
-
|
|
391
|
-
unsubSingleCallbacksByKey.clear();
|
|
897
|
+
unsubCallbacksByKey.clear();
|
|
392
898
|
};
|
|
393
899
|
};
|
|
394
900
|
}
|
|
@@ -423,7 +929,7 @@ function realtimeActionReceiver({
|
|
|
423
929
|
const performanceKeyStart = `${performanceKey}:start`;
|
|
424
930
|
const performanceKeyEnd = `${performanceKey}:end`;
|
|
425
931
|
performance.mark(performanceKeyStart);
|
|
426
|
-
|
|
932
|
+
actUponStore(tx, update.id, store)(...update.params);
|
|
427
933
|
performance.mark(performanceKeyEnd);
|
|
428
934
|
const metric = performance.measure(
|
|
429
935
|
performanceKey,
|
|
@@ -436,121 +942,7 @@ function realtimeActionReceiver({
|
|
|
436
942
|
return () => socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
|
|
437
943
|
};
|
|
438
944
|
}
|
|
439
|
-
function realtimeActionSynchronizer({
|
|
440
|
-
socket,
|
|
441
|
-
store = IMPLICIT.STORE
|
|
442
|
-
}) {
|
|
443
|
-
return function actionSynchronizer(tx, filter) {
|
|
444
|
-
const userKeyState = findInStore(
|
|
445
|
-
usersOfSockets.states.userKeyOfSocket,
|
|
446
|
-
socket.id,
|
|
447
|
-
store
|
|
448
|
-
);
|
|
449
|
-
const userKey = getFromStore(userKeyState, store);
|
|
450
|
-
const socketUnacknowledgedUpdatesState = findInStore(
|
|
451
|
-
socketUnacknowledgedUpdatesSelectors,
|
|
452
|
-
socket.id,
|
|
453
|
-
store
|
|
454
|
-
);
|
|
455
|
-
const socketUnacknowledgedUpdates = getFromStore(
|
|
456
|
-
socketUnacknowledgedUpdatesState,
|
|
457
|
-
store
|
|
458
|
-
);
|
|
459
|
-
if (filter) {
|
|
460
|
-
const redactorState = findInStore(transactionRedactorAtoms, tx.key, store);
|
|
461
|
-
setIntoStore(redactorState, { filter }, store);
|
|
462
|
-
}
|
|
463
|
-
const fillTransactionRequest = (update) => {
|
|
464
|
-
const performanceKey = `tx-run:${tx.key}:${update.id}`;
|
|
465
|
-
const performanceKeyStart = `${performanceKey}:start`;
|
|
466
|
-
const performanceKeyEnd = `${performanceKey}:end`;
|
|
467
|
-
performance.mark(performanceKeyStart);
|
|
468
|
-
AtomIO.runTransaction(tx, update.id, store)(...update.params);
|
|
469
|
-
performance.mark(performanceKeyEnd);
|
|
470
|
-
const metric = performance.measure(
|
|
471
|
-
performanceKey,
|
|
472
|
-
performanceKeyStart,
|
|
473
|
-
performanceKeyEnd
|
|
474
|
-
);
|
|
475
|
-
store == null ? void 0 : store.logger.info(`\u{1F680}`, `transaction`, tx.key, update.id, metric.duration);
|
|
476
|
-
};
|
|
477
|
-
socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
|
|
478
|
-
socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
|
|
479
|
-
let unsubscribeFromTransaction;
|
|
480
|
-
const fillTransactionSubscriptionRequest = () => {
|
|
481
|
-
unsubscribeFromTransaction = subscribeToTransaction(
|
|
482
|
-
tx,
|
|
483
|
-
(update) => {
|
|
484
|
-
const updateState = findInStore(completeUpdateAtoms, update.id, store);
|
|
485
|
-
setIntoStore(updateState, update, store);
|
|
486
|
-
const toEmit = filter ? getFromStore(
|
|
487
|
-
findInStore(redactedUpdateSelectors, [tx.key, update.id], store),
|
|
488
|
-
store
|
|
489
|
-
) : update;
|
|
490
|
-
setIntoStore(
|
|
491
|
-
socketUnacknowledgedUpdatesState,
|
|
492
|
-
(updates) => {
|
|
493
|
-
if (toEmit) {
|
|
494
|
-
updates.push(toEmit);
|
|
495
|
-
updates.sort((a, b) => a.epoch - b.epoch);
|
|
496
|
-
}
|
|
497
|
-
return updates;
|
|
498
|
-
},
|
|
499
|
-
store
|
|
500
|
-
);
|
|
501
|
-
socket.emit(`tx-new:${tx.key}`, toEmit);
|
|
502
|
-
},
|
|
503
|
-
`tx-sub:${tx.key}:${socket.id}`,
|
|
504
|
-
store
|
|
505
|
-
);
|
|
506
|
-
socket.on(`tx-unsub:${tx.key}`, unsubscribeFromTransaction);
|
|
507
|
-
};
|
|
508
|
-
socket.on(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
|
|
509
|
-
let i = 1;
|
|
510
|
-
let next = 1;
|
|
511
|
-
const retry = setInterval(() => {
|
|
512
|
-
const toEmit = socketUnacknowledgedUpdates[0];
|
|
513
|
-
console.log(userKey, socketUnacknowledgedUpdates);
|
|
514
|
-
if (toEmit && i === next) {
|
|
515
|
-
socket.emit(`tx-new:${tx.key}`, toEmit);
|
|
516
|
-
next *= 2;
|
|
517
|
-
}
|
|
518
|
-
i++;
|
|
519
|
-
}, 250);
|
|
520
|
-
const trackClientAcknowledgement = (epoch) => {
|
|
521
|
-
var _a;
|
|
522
|
-
i = 1;
|
|
523
|
-
next = 1;
|
|
524
|
-
const socketEpochState = findInStore(
|
|
525
|
-
socketEpochSelectors,
|
|
526
|
-
socket.id,
|
|
527
|
-
store
|
|
528
|
-
);
|
|
529
|
-
setIntoStore(socketEpochState, epoch, store);
|
|
530
|
-
if (((_a = socketUnacknowledgedUpdates[0]) == null ? void 0 : _a.epoch) === epoch) {
|
|
531
|
-
setIntoStore(
|
|
532
|
-
socketUnacknowledgedUpdatesState,
|
|
533
|
-
(updates) => {
|
|
534
|
-
updates.shift();
|
|
535
|
-
return updates;
|
|
536
|
-
},
|
|
537
|
-
store
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
socket.on(`tx-ack:${tx.key}`, trackClientAcknowledgement);
|
|
542
|
-
return () => {
|
|
543
|
-
if (unsubscribeFromTransaction) {
|
|
544
|
-
unsubscribeFromTransaction();
|
|
545
|
-
unsubscribeFromTransaction = void 0;
|
|
546
|
-
}
|
|
547
|
-
clearInterval(retry);
|
|
548
|
-
socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
|
|
549
|
-
socket.off(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
|
|
550
|
-
};
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
945
|
|
|
554
|
-
export {
|
|
946
|
+
export { ChildSocket, CustomSocket, ParentSocket, SubjectSocket, actionOcclusionAtoms, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeContinuitySynchronizer, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, realtimeStateSynchronizer, redactTransactionUpdateContent, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets };
|
|
555
947
|
//# sourceMappingURL=out.js.map
|
|
556
948
|
//# sourceMappingURL=index.js.map
|