@rpcbase/server 0.463.0 → 0.465.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index-BXODFGBH.js +490 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -65
- package/dist/initServer.d.ts.map +1 -1
- package/dist/rts/index.d.ts +34 -0
- package/dist/rts/index.d.ts.map +1 -0
- package/dist/rts.d.ts +2 -0
- package/dist/rts.d.ts.map +1 -0
- package/dist/rts.js +6 -0
- package/package.json +16 -2
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { loadModel } from "@rpcbase/db";
|
|
3
|
+
import { WebSocketServer } from "ws";
|
|
4
|
+
const TENANT_ID_QUERY_PARAM = "rb-tenant-id";
|
|
5
|
+
const USER_ID_HEADER = "rb-user-id";
|
|
6
|
+
const QUERY_KEY_MAX_LEN = 4096;
|
|
7
|
+
const QUERY_MAX_LIMIT = 4096;
|
|
8
|
+
const initializedServers = /* @__PURE__ */ new WeakSet();
|
|
9
|
+
const customHandlers = [];
|
|
10
|
+
const sockets = /* @__PURE__ */ new Map();
|
|
11
|
+
const socketMeta = /* @__PURE__ */ new Map();
|
|
12
|
+
const socketWrappers = /* @__PURE__ */ new Map();
|
|
13
|
+
const socketCleanup = /* @__PURE__ */ new Map();
|
|
14
|
+
const socketSubscriptions = /* @__PURE__ */ new Map();
|
|
15
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
16
|
+
const changeStreams = /* @__PURE__ */ new Map();
|
|
17
|
+
class RtsSocket {
|
|
18
|
+
id;
|
|
19
|
+
tenantId;
|
|
20
|
+
userId;
|
|
21
|
+
ws;
|
|
22
|
+
handlers = /* @__PURE__ */ new Map();
|
|
23
|
+
constructor({
|
|
24
|
+
id,
|
|
25
|
+
ws,
|
|
26
|
+
meta
|
|
27
|
+
}) {
|
|
28
|
+
this.id = id;
|
|
29
|
+
this.ws = ws;
|
|
30
|
+
this.tenantId = meta.tenantId;
|
|
31
|
+
this.userId = meta.userId;
|
|
32
|
+
}
|
|
33
|
+
on(event, handler) {
|
|
34
|
+
const set = this.handlers.get(event) ?? /* @__PURE__ */ new Set();
|
|
35
|
+
set.add(handler);
|
|
36
|
+
this.handlers.set(event, set);
|
|
37
|
+
return () => this.off(event, handler);
|
|
38
|
+
}
|
|
39
|
+
off(event, handler) {
|
|
40
|
+
const set = this.handlers.get(event);
|
|
41
|
+
if (!set) return;
|
|
42
|
+
set.delete(handler);
|
|
43
|
+
if (!set.size) this.handlers.delete(event);
|
|
44
|
+
}
|
|
45
|
+
emit(event, payload) {
|
|
46
|
+
sendWs(this.ws, { type: "event", event, payload });
|
|
47
|
+
}
|
|
48
|
+
close() {
|
|
49
|
+
try {
|
|
50
|
+
this.ws.close();
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
dispatch(event, payload) {
|
|
55
|
+
const set = this.handlers.get(event);
|
|
56
|
+
if (!set) return;
|
|
57
|
+
for (const handler of set) {
|
|
58
|
+
handler(payload);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const rawToText = (raw) => {
|
|
63
|
+
if (typeof raw === "string") return raw;
|
|
64
|
+
if (raw instanceof ArrayBuffer) return Buffer.from(raw).toString();
|
|
65
|
+
if (Array.isArray(raw)) return Buffer.concat(raw).toString();
|
|
66
|
+
return raw.toString();
|
|
67
|
+
};
|
|
68
|
+
const safeJsonParse = (raw) => JSON.parse(rawToText(raw));
|
|
69
|
+
const sendWs = (ws, message) => {
|
|
70
|
+
if (ws.readyState !== 1) return;
|
|
71
|
+
ws.send(JSON.stringify(message));
|
|
72
|
+
};
|
|
73
|
+
const unauthorized = (socket, message = "Unauthorized") => {
|
|
74
|
+
try {
|
|
75
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
|
|
76
|
+
socket.write(`Error: ${message}\r
|
|
77
|
+
`);
|
|
78
|
+
socket.end();
|
|
79
|
+
} catch {
|
|
80
|
+
socket.destroy();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const badRequest = (socket, message = "Bad Request") => {
|
|
84
|
+
try {
|
|
85
|
+
socket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
86
|
+
socket.write(`Error: ${message}\r
|
|
87
|
+
`);
|
|
88
|
+
socket.end();
|
|
89
|
+
} catch {
|
|
90
|
+
socket.destroy();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const runSessionMiddleware = async (sessionMiddleware, req) => {
|
|
94
|
+
await new Promise((resolve, reject) => {
|
|
95
|
+
sessionMiddleware(req, {}, (err) => {
|
|
96
|
+
if (err) reject(err);
|
|
97
|
+
else resolve();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const parseUpgradeMeta = async ({
|
|
102
|
+
req,
|
|
103
|
+
url,
|
|
104
|
+
sessionMiddleware
|
|
105
|
+
}) => {
|
|
106
|
+
const tenantId = url.searchParams.get(TENANT_ID_QUERY_PARAM);
|
|
107
|
+
if (!tenantId) {
|
|
108
|
+
throw new Error("Missing rb-tenant-id query parameter");
|
|
109
|
+
}
|
|
110
|
+
const raw = req.headers[USER_ID_HEADER];
|
|
111
|
+
const headerUserId = Array.isArray(raw) ? raw[0] : raw;
|
|
112
|
+
if (headerUserId) return { tenantId, userId: headerUserId };
|
|
113
|
+
if (!sessionMiddleware) {
|
|
114
|
+
throw new Error("Missing rb-user-id header (reverse-proxy) and no session middleware configured");
|
|
115
|
+
}
|
|
116
|
+
const upgradeReq = req;
|
|
117
|
+
try {
|
|
118
|
+
await runSessionMiddleware(sessionMiddleware, upgradeReq);
|
|
119
|
+
} catch {
|
|
120
|
+
throw new Error("Failed to load session for RTS");
|
|
121
|
+
}
|
|
122
|
+
const sessionUser = upgradeReq.session?.user;
|
|
123
|
+
const sessionUserId = sessionUser?.id;
|
|
124
|
+
if (!sessionUserId) {
|
|
125
|
+
throw new Error("Not signed in (missing session.user.id)");
|
|
126
|
+
}
|
|
127
|
+
const signedInTenants = sessionUser?.signed_in_tenants;
|
|
128
|
+
const currentTenantId = sessionUser?.current_tenant_id;
|
|
129
|
+
if (Array.isArray(signedInTenants) && signedInTenants.length > 0) {
|
|
130
|
+
if (!signedInTenants.includes(tenantId)) {
|
|
131
|
+
throw new Error("Tenant not authorized for this session");
|
|
132
|
+
}
|
|
133
|
+
} else if (currentTenantId) {
|
|
134
|
+
if (currentTenantId !== tenantId) {
|
|
135
|
+
throw new Error("Tenant not authorized for this session");
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
throw new Error("Tenant not authorized for this session");
|
|
139
|
+
}
|
|
140
|
+
return { tenantId, userId: sessionUserId };
|
|
141
|
+
};
|
|
142
|
+
const getTenantModel = async (tenantId, modelName) => {
|
|
143
|
+
const ctx = {
|
|
144
|
+
req: {
|
|
145
|
+
session: {
|
|
146
|
+
user: {
|
|
147
|
+
current_tenant_id: tenantId
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
return loadModel(modelName, ctx);
|
|
153
|
+
};
|
|
154
|
+
const normalizeLimit = (limit) => {
|
|
155
|
+
if (typeof limit !== "number") return QUERY_MAX_LIMIT;
|
|
156
|
+
if (!Number.isFinite(limit)) return QUERY_MAX_LIMIT;
|
|
157
|
+
return Math.min(QUERY_MAX_LIMIT, Math.abs(limit));
|
|
158
|
+
};
|
|
159
|
+
const normalizeOptions = (options) => {
|
|
160
|
+
if (!options || typeof options !== "object") return {};
|
|
161
|
+
const normalized = {};
|
|
162
|
+
if (options.projection && typeof options.projection === "object") {
|
|
163
|
+
normalized.projection = options.projection;
|
|
164
|
+
}
|
|
165
|
+
if (options.sort && typeof options.sort === "object") {
|
|
166
|
+
normalized.sort = options.sort;
|
|
167
|
+
}
|
|
168
|
+
normalized.limit = normalizeLimit(options.limit);
|
|
169
|
+
return normalized;
|
|
170
|
+
};
|
|
171
|
+
const runAndSendQuery = async ({
|
|
172
|
+
tenantId,
|
|
173
|
+
targetSocketIds,
|
|
174
|
+
modelName,
|
|
175
|
+
queryKey,
|
|
176
|
+
query,
|
|
177
|
+
options
|
|
178
|
+
}) => {
|
|
179
|
+
const model = await getTenantModel(tenantId, modelName);
|
|
180
|
+
const projection = options.projection ?? void 0;
|
|
181
|
+
const sort = options.sort;
|
|
182
|
+
const limit = normalizeLimit(options.limit);
|
|
183
|
+
const queryPromise = model.find(query, projection);
|
|
184
|
+
if (sort && Object.keys(sort).length) {
|
|
185
|
+
queryPromise.sort(sort);
|
|
186
|
+
}
|
|
187
|
+
queryPromise.limit(limit);
|
|
188
|
+
const data = await queryPromise;
|
|
189
|
+
const payload = { type: "query_payload", modelName, queryKey, data };
|
|
190
|
+
for (const socketId of targetSocketIds) {
|
|
191
|
+
const ws = sockets.get(socketId);
|
|
192
|
+
if (!ws) continue;
|
|
193
|
+
sendWs(ws, payload);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
const dispatchSubscriptionsForModel = async (tenantId, modelName) => {
|
|
197
|
+
const tenantSubs = subscriptions.get(tenantId);
|
|
198
|
+
const modelSubs = tenantSubs?.get(modelName);
|
|
199
|
+
if (!modelSubs || !modelSubs.size) return;
|
|
200
|
+
for (const [queryKey, sub] of modelSubs.entries()) {
|
|
201
|
+
const targetSocketIds = Array.from(sub.socketIds);
|
|
202
|
+
if (!targetSocketIds.length) continue;
|
|
203
|
+
try {
|
|
204
|
+
await runAndSendQuery({
|
|
205
|
+
tenantId,
|
|
206
|
+
targetSocketIds,
|
|
207
|
+
modelName,
|
|
208
|
+
queryKey,
|
|
209
|
+
query: sub.query,
|
|
210
|
+
options: sub.options
|
|
211
|
+
});
|
|
212
|
+
} catch (err) {
|
|
213
|
+
const error = err instanceof Error ? err.message : "Unknown error";
|
|
214
|
+
const payload = { type: "query_payload", modelName, queryKey, error };
|
|
215
|
+
for (const socketId of targetSocketIds) {
|
|
216
|
+
const ws = sockets.get(socketId);
|
|
217
|
+
if (!ws) continue;
|
|
218
|
+
sendWs(ws, payload);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
const ensureChangeStream = async (tenantId, modelName) => {
|
|
224
|
+
const tenantStreams = changeStreams.get(tenantId) ?? /* @__PURE__ */ new Map();
|
|
225
|
+
changeStreams.set(tenantId, tenantStreams);
|
|
226
|
+
if (tenantStreams.has(modelName)) return;
|
|
227
|
+
const model = await getTenantModel(tenantId, modelName);
|
|
228
|
+
const stream = model.watch([], {
|
|
229
|
+
fullDocument: "updateLookup"
|
|
230
|
+
});
|
|
231
|
+
stream.on("change", () => {
|
|
232
|
+
void dispatchSubscriptionsForModel(tenantId, modelName);
|
|
233
|
+
});
|
|
234
|
+
stream.on("close", () => {
|
|
235
|
+
const map = changeStreams.get(tenantId);
|
|
236
|
+
map?.delete(modelName);
|
|
237
|
+
if (map && map.size === 0) changeStreams.delete(tenantId);
|
|
238
|
+
});
|
|
239
|
+
stream.on("error", () => {
|
|
240
|
+
try {
|
|
241
|
+
stream.close();
|
|
242
|
+
} catch {
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
tenantStreams.set(modelName, stream);
|
|
246
|
+
};
|
|
247
|
+
const addSocketSubscription = ({
|
|
248
|
+
socketId,
|
|
249
|
+
tenantId,
|
|
250
|
+
modelName,
|
|
251
|
+
queryKey,
|
|
252
|
+
query,
|
|
253
|
+
options
|
|
254
|
+
}) => {
|
|
255
|
+
const tenantSubs = subscriptions.get(tenantId) ?? /* @__PURE__ */ new Map();
|
|
256
|
+
subscriptions.set(tenantId, tenantSubs);
|
|
257
|
+
const modelSubs = tenantSubs.get(modelName) ?? /* @__PURE__ */ new Map();
|
|
258
|
+
tenantSubs.set(modelName, modelSubs);
|
|
259
|
+
const existing = modelSubs.get(queryKey);
|
|
260
|
+
if (existing) {
|
|
261
|
+
existing.socketIds.add(socketId);
|
|
262
|
+
} else {
|
|
263
|
+
modelSubs.set(queryKey, {
|
|
264
|
+
query,
|
|
265
|
+
options,
|
|
266
|
+
socketIds: /* @__PURE__ */ new Set([socketId])
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const byModel = socketSubscriptions.get(socketId) ?? /* @__PURE__ */ new Map();
|
|
270
|
+
socketSubscriptions.set(socketId, byModel);
|
|
271
|
+
const querySet = byModel.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
272
|
+
byModel.set(modelName, querySet);
|
|
273
|
+
querySet.add(queryKey);
|
|
274
|
+
};
|
|
275
|
+
const removeSocketSubscription = ({
|
|
276
|
+
socketId,
|
|
277
|
+
tenantId,
|
|
278
|
+
modelName,
|
|
279
|
+
queryKey
|
|
280
|
+
}) => {
|
|
281
|
+
const tenantSubs = subscriptions.get(tenantId);
|
|
282
|
+
const modelSubs = tenantSubs?.get(modelName);
|
|
283
|
+
const sub = modelSubs?.get(queryKey);
|
|
284
|
+
if (sub) {
|
|
285
|
+
sub.socketIds.delete(socketId);
|
|
286
|
+
if (!sub.socketIds.size) {
|
|
287
|
+
modelSubs?.delete(queryKey);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const byModel = socketSubscriptions.get(socketId);
|
|
291
|
+
const set = byModel?.get(modelName);
|
|
292
|
+
if (set) {
|
|
293
|
+
set.delete(queryKey);
|
|
294
|
+
if (!set.size) {
|
|
295
|
+
byModel?.delete(modelName);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (modelSubs && modelSubs.size === 0) {
|
|
299
|
+
tenantSubs?.delete(modelName);
|
|
300
|
+
const tenantStreams = changeStreams.get(tenantId);
|
|
301
|
+
const stream = tenantStreams?.get(modelName);
|
|
302
|
+
if (stream) {
|
|
303
|
+
try {
|
|
304
|
+
stream.close();
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
307
|
+
tenantStreams?.delete(modelName);
|
|
308
|
+
if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (tenantSubs && tenantSubs.size === 0) subscriptions.delete(tenantId);
|
|
312
|
+
if (byModel && byModel.size === 0) socketSubscriptions.delete(socketId);
|
|
313
|
+
};
|
|
314
|
+
const cleanupSocket = (socketId) => {
|
|
315
|
+
const meta = socketMeta.get(socketId);
|
|
316
|
+
if (meta) {
|
|
317
|
+
const byModel = socketSubscriptions.get(socketId);
|
|
318
|
+
if (byModel) {
|
|
319
|
+
for (const [modelName, keys] of byModel.entries()) {
|
|
320
|
+
for (const queryKey of keys.values()) {
|
|
321
|
+
removeSocketSubscription({
|
|
322
|
+
socketId,
|
|
323
|
+
tenantId: meta.tenantId,
|
|
324
|
+
modelName,
|
|
325
|
+
queryKey
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
socketSubscriptions.delete(socketId);
|
|
332
|
+
const cleanupFns = socketCleanup.get(socketId) ?? [];
|
|
333
|
+
socketCleanup.delete(socketId);
|
|
334
|
+
for (const fn of cleanupFns) {
|
|
335
|
+
try {
|
|
336
|
+
fn();
|
|
337
|
+
} catch {
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
sockets.delete(socketId);
|
|
341
|
+
socketMeta.delete(socketId);
|
|
342
|
+
socketWrappers.delete(socketId);
|
|
343
|
+
};
|
|
344
|
+
const handleClientMessage = async ({
|
|
345
|
+
socketId,
|
|
346
|
+
meta,
|
|
347
|
+
message
|
|
348
|
+
}) => {
|
|
349
|
+
const ws = sockets.get(socketId);
|
|
350
|
+
if (!ws) return;
|
|
351
|
+
if (message.type === "event") {
|
|
352
|
+
const wrapper = socketWrappers.get(socketId);
|
|
353
|
+
wrapper?.dispatch(message.event, message.payload);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (!message.modelName || typeof message.modelName !== "string") return;
|
|
357
|
+
if (!message.queryKey || typeof message.queryKey !== "string") return;
|
|
358
|
+
if (message.queryKey.length > QUERY_KEY_MAX_LEN) return;
|
|
359
|
+
if (message.type === "remove_query") {
|
|
360
|
+
removeSocketSubscription({
|
|
361
|
+
socketId,
|
|
362
|
+
tenantId: meta.tenantId,
|
|
363
|
+
modelName: message.modelName,
|
|
364
|
+
queryKey: message.queryKey
|
|
365
|
+
});
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (!message.query || typeof message.query !== "object") return;
|
|
369
|
+
const options = normalizeOptions(message.options);
|
|
370
|
+
if (message.type === "registerQuery") {
|
|
371
|
+
addSocketSubscription({
|
|
372
|
+
socketId,
|
|
373
|
+
tenantId: meta.tenantId,
|
|
374
|
+
modelName: message.modelName,
|
|
375
|
+
queryKey: message.queryKey,
|
|
376
|
+
query: message.query,
|
|
377
|
+
options
|
|
378
|
+
});
|
|
379
|
+
try {
|
|
380
|
+
await ensureChangeStream(meta.tenantId, message.modelName);
|
|
381
|
+
} catch (err) {
|
|
382
|
+
const error = err instanceof Error ? err.message : "Unable to initialize change stream";
|
|
383
|
+
sendWs(ws, { type: "query_payload", modelName: message.modelName, queryKey: message.queryKey, error });
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
await runAndSendQuery({
|
|
389
|
+
tenantId: meta.tenantId,
|
|
390
|
+
targetSocketIds: [socketId],
|
|
391
|
+
modelName: message.modelName,
|
|
392
|
+
queryKey: message.queryKey,
|
|
393
|
+
query: message.query,
|
|
394
|
+
options
|
|
395
|
+
});
|
|
396
|
+
} catch (err) {
|
|
397
|
+
const error = err instanceof Error ? err.message : "Unknown error";
|
|
398
|
+
sendWs(ws, { type: "query_payload", modelName: message.modelName, queryKey: message.queryKey, error });
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const initRts = ({
|
|
402
|
+
server,
|
|
403
|
+
path = "/rts",
|
|
404
|
+
sessionMiddleware
|
|
405
|
+
}) => {
|
|
406
|
+
if (initializedServers.has(server)) return;
|
|
407
|
+
initializedServers.add(server);
|
|
408
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
409
|
+
server.on("upgrade", (req, socket, head) => {
|
|
410
|
+
let url;
|
|
411
|
+
try {
|
|
412
|
+
url = new URL(req.url ?? "", `http://${req.headers.host ?? "localhost"}`);
|
|
413
|
+
} catch {
|
|
414
|
+
badRequest(socket, "Invalid URL");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (url.pathname !== path) return;
|
|
418
|
+
void (async () => {
|
|
419
|
+
try {
|
|
420
|
+
const meta = await parseUpgradeMeta({ req, url, sessionMiddleware });
|
|
421
|
+
req.__rb_rts_meta = meta;
|
|
422
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
423
|
+
wss.emit("connection", ws, req);
|
|
424
|
+
});
|
|
425
|
+
} catch (err) {
|
|
426
|
+
const message = err instanceof Error ? err.message : "RTS upgrade failed";
|
|
427
|
+
if (message.startsWith("Missing rb-tenant-id")) {
|
|
428
|
+
badRequest(socket, message);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
unauthorized(socket, message);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
})().catch(() => {
|
|
435
|
+
badRequest(socket, "RTS upgrade failed");
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
wss.on("connection", (ws, req) => {
|
|
439
|
+
const meta = req.__rb_rts_meta;
|
|
440
|
+
if (!meta) {
|
|
441
|
+
try {
|
|
442
|
+
ws.close();
|
|
443
|
+
} catch {
|
|
444
|
+
}
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const socketId = randomUUID();
|
|
448
|
+
sockets.set(socketId, ws);
|
|
449
|
+
socketMeta.set(socketId, meta);
|
|
450
|
+
const wrapper = new RtsSocket({ id: socketId, ws, meta });
|
|
451
|
+
socketWrappers.set(socketId, wrapper);
|
|
452
|
+
const cleanupFns = [];
|
|
453
|
+
for (const handler of customHandlers) {
|
|
454
|
+
try {
|
|
455
|
+
const cleanup = handler(wrapper);
|
|
456
|
+
if (typeof cleanup === "function") cleanupFns.push(cleanup);
|
|
457
|
+
} catch {
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (cleanupFns.length) socketCleanup.set(socketId, cleanupFns);
|
|
461
|
+
ws.on("message", (raw) => {
|
|
462
|
+
let parsed;
|
|
463
|
+
try {
|
|
464
|
+
parsed = safeJsonParse(raw);
|
|
465
|
+
} catch {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (!parsed || typeof parsed !== "object") return;
|
|
469
|
+
const message = parsed;
|
|
470
|
+
void handleClientMessage({ socketId, meta, message });
|
|
471
|
+
});
|
|
472
|
+
ws.on("close", () => {
|
|
473
|
+
cleanupSocket(socketId);
|
|
474
|
+
});
|
|
475
|
+
ws.on("error", () => {
|
|
476
|
+
cleanupSocket(socketId);
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
};
|
|
480
|
+
const registerRtsHandler = (handler) => {
|
|
481
|
+
customHandlers.push(handler);
|
|
482
|
+
};
|
|
483
|
+
const notifyRtsModelChanged = (tenantId, modelName) => {
|
|
484
|
+
void dispatchSubscriptionsForModel(tenantId, modelName);
|
|
485
|
+
};
|
|
486
|
+
export {
|
|
487
|
+
initRts as i,
|
|
488
|
+
notifyRtsModelChanged as n,
|
|
489
|
+
registerRtsHandler as r
|
|
490
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
|
|
|
18
18
|
import { jsx } from "react/jsx-runtime";
|
|
19
19
|
import { createPath, matchRoutes, parsePath, createStaticRouter, StaticRouterProvider } from "@rpcbase/router";
|
|
20
20
|
import { Resend } from "resend";
|
|
21
|
+
import { i, n, r } from "./index-BXODFGBH.js";
|
|
21
22
|
function getDefaultExportFromCjs(x) {
|
|
22
23
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
23
24
|
}
|
|
@@ -93,9 +94,9 @@ function requireLib() {
|
|
|
93
94
|
}
|
|
94
95
|
return ip;
|
|
95
96
|
});
|
|
96
|
-
for (var
|
|
97
|
-
if (is.ip(forwardedIps[
|
|
98
|
-
return forwardedIps[
|
|
97
|
+
for (var i2 = 0; i2 < forwardedIps.length; i2++) {
|
|
98
|
+
if (is.ip(forwardedIps[i2])) {
|
|
99
|
+
return forwardedIps[i2];
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
return null;
|
|
@@ -206,8 +207,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(proces
|
|
|
206
207
|
if (".js" === ext || ".mjs" === ext || ".cjs" === ext) file = file.slice(0, -1 * ext.length);
|
|
207
208
|
const decodedFile = decodeURIComponent(file);
|
|
208
209
|
if (!dir) dir = ".";
|
|
209
|
-
const
|
|
210
|
-
if (
|
|
210
|
+
const n2 = dir.lastIndexOf("/node_modules");
|
|
211
|
+
if (n2 > -1) return `${dir.slice(n2 + 14).replace(/\//g, ".")}:${decodedFile}`;
|
|
211
212
|
if (dir.startsWith(normalizedBase)) {
|
|
212
213
|
const moduleName = dir.slice(normalizedBase.length + 1).replace(/\//g, ".");
|
|
213
214
|
return moduleName ? `${moduleName}:${decodedFile}` : decodedFile;
|
|
@@ -334,12 +335,12 @@ class UUID {
|
|
|
334
335
|
}
|
|
335
336
|
if (hex) {
|
|
336
337
|
const inner = new Uint8Array(16);
|
|
337
|
-
for (let
|
|
338
|
-
const
|
|
339
|
-
inner[
|
|
340
|
-
inner[
|
|
341
|
-
inner[
|
|
342
|
-
inner[
|
|
338
|
+
for (let i2 = 0; i2 < 16; i2 += 4) {
|
|
339
|
+
const n2 = parseInt(hex.substring(2 * i2, 2 * i2 + 8), 16);
|
|
340
|
+
inner[i2 + 0] = n2 >>> 24;
|
|
341
|
+
inner[i2 + 1] = n2 >>> 16;
|
|
342
|
+
inner[i2 + 2] = n2 >>> 8;
|
|
343
|
+
inner[i2 + 3] = n2;
|
|
343
344
|
}
|
|
344
345
|
return new UUID(inner);
|
|
345
346
|
}
|
|
@@ -347,18 +348,18 @@ class UUID {
|
|
|
347
348
|
}
|
|
348
349
|
toString() {
|
|
349
350
|
let text = "";
|
|
350
|
-
for (let
|
|
351
|
-
text += DIGITS.charAt(this.bytes[
|
|
352
|
-
text += DIGITS.charAt(15 & this.bytes[
|
|
353
|
-
if (3 ===
|
|
351
|
+
for (let i2 = 0; i2 < this.bytes.length; i2++) {
|
|
352
|
+
text += DIGITS.charAt(this.bytes[i2] >>> 4);
|
|
353
|
+
text += DIGITS.charAt(15 & this.bytes[i2]);
|
|
354
|
+
if (3 === i2 || 5 === i2 || 7 === i2 || 9 === i2) text += "-";
|
|
354
355
|
}
|
|
355
356
|
return text;
|
|
356
357
|
}
|
|
357
358
|
toHex() {
|
|
358
359
|
let text = "";
|
|
359
|
-
for (let
|
|
360
|
-
text += DIGITS.charAt(this.bytes[
|
|
361
|
-
text += DIGITS.charAt(15 & this.bytes[
|
|
360
|
+
for (let i2 = 0; i2 < this.bytes.length; i2++) {
|
|
361
|
+
text += DIGITS.charAt(this.bytes[i2] >>> 4);
|
|
362
|
+
text += DIGITS.charAt(15 & this.bytes[i2]);
|
|
362
363
|
}
|
|
363
364
|
return text;
|
|
364
365
|
}
|
|
@@ -366,12 +367,12 @@ class UUID {
|
|
|
366
367
|
return this.toString();
|
|
367
368
|
}
|
|
368
369
|
getVariant() {
|
|
369
|
-
const
|
|
370
|
-
if (
|
|
371
|
-
if (
|
|
372
|
-
if (
|
|
373
|
-
if (
|
|
374
|
-
if (
|
|
370
|
+
const n2 = this.bytes[8] >>> 4;
|
|
371
|
+
if (n2 < 0) throw new Error("unreachable");
|
|
372
|
+
if (n2 <= 7) return this.bytes.every((e) => 0 === e) ? "NIL" : "VAR_0";
|
|
373
|
+
if (n2 <= 11) return "VAR_10";
|
|
374
|
+
if (n2 <= 13) return "VAR_110";
|
|
375
|
+
if (n2 <= 15) return this.bytes.every((e) => 255 === e) ? "MAX" : "VAR_RESERVED";
|
|
375
376
|
else throw new Error("unreachable");
|
|
376
377
|
}
|
|
377
378
|
getVersion() {
|
|
@@ -384,8 +385,8 @@ class UUID {
|
|
|
384
385
|
return 0 === this.compareTo(other);
|
|
385
386
|
}
|
|
386
387
|
compareTo(other) {
|
|
387
|
-
for (let
|
|
388
|
-
const diff = this.bytes[
|
|
388
|
+
for (let i2 = 0; i2 < 16; i2++) {
|
|
389
|
+
const diff = this.bytes[i2] - other.bytes[i2];
|
|
389
390
|
if (0 !== diff) return Math.sign(diff);
|
|
390
391
|
}
|
|
391
392
|
return 0;
|
|
@@ -720,8 +721,8 @@ function removeTrailingSlash(url) {
|
|
|
720
721
|
}
|
|
721
722
|
async function retriable(fn, props) {
|
|
722
723
|
let lastError = null;
|
|
723
|
-
for (let
|
|
724
|
-
if (
|
|
724
|
+
for (let i2 = 0; i2 < props.retryCount + 1; i2++) {
|
|
725
|
+
if (i2 > 0) await new Promise((r2) => setTimeout(r2, props.retryDelay));
|
|
725
726
|
try {
|
|
726
727
|
const res = await fn();
|
|
727
728
|
return res;
|
|
@@ -1423,8 +1424,8 @@ function getFilenameToChunkIdMap(stackParser) {
|
|
|
1423
1424
|
if (result) acc[result[0]] = result[1];
|
|
1424
1425
|
else {
|
|
1425
1426
|
const parsedStack = stackParser(stackKey);
|
|
1426
|
-
for (let
|
|
1427
|
-
const stackFrame = parsedStack[
|
|
1427
|
+
for (let i2 = parsedStack.length - 1; i2 >= 0; i2--) {
|
|
1428
|
+
const stackFrame = parsedStack[i2];
|
|
1428
1429
|
const filename = stackFrame?.filename;
|
|
1429
1430
|
const chunkId = chunkIdMap[stackKey];
|
|
1430
1431
|
if (filename && chunkId) {
|
|
@@ -1632,8 +1633,8 @@ function createStackParser(platform, ...parsers) {
|
|
|
1632
1633
|
return (stack, skipFirstLines = 0) => {
|
|
1633
1634
|
const frames = [];
|
|
1634
1635
|
const lines = stack.split("\n");
|
|
1635
|
-
for (let
|
|
1636
|
-
const line = lines[
|
|
1636
|
+
for (let i2 = skipFirstLines; i2 < lines.length; i2++) {
|
|
1637
|
+
const line = lines[i2];
|
|
1637
1638
|
if (line.length > 1024) continue;
|
|
1638
1639
|
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, "$1") : line;
|
|
1639
1640
|
if (!cleanedLine.match(/\S*Error: /)) {
|
|
@@ -1715,10 +1716,10 @@ function extractExceptionKeysForMessage(err, maxLength = 40) {
|
|
|
1715
1716
|
const keys = Object.keys(err);
|
|
1716
1717
|
keys.sort();
|
|
1717
1718
|
if (!keys.length) return "[object has no keys]";
|
|
1718
|
-
for (let
|
|
1719
|
-
const serialized = keys.slice(0,
|
|
1719
|
+
for (let i2 = keys.length; i2 > 0; i2--) {
|
|
1720
|
+
const serialized = keys.slice(0, i2).join(", ");
|
|
1720
1721
|
if (!(serialized.length > maxLength)) {
|
|
1721
|
-
if (
|
|
1722
|
+
if (i2 === keys.length) return serialized;
|
|
1722
1723
|
return serialized.length <= maxLength ? serialized : `${serialized.slice(0, maxLength)}...`;
|
|
1723
1724
|
}
|
|
1724
1725
|
}
|
|
@@ -1827,8 +1828,8 @@ const MAX_CONTEXTLINES_COLNO = 1e3;
|
|
|
1827
1828
|
const MAX_CONTEXTLINES_LINENO = 1e4;
|
|
1828
1829
|
async function addSourceContext(frames) {
|
|
1829
1830
|
const filesToLines = {};
|
|
1830
|
-
for (let
|
|
1831
|
-
const frame = frames[
|
|
1831
|
+
for (let i2 = frames.length - 1; i2 >= 0; i2--) {
|
|
1832
|
+
const frame = frames[i2];
|
|
1832
1833
|
const filename = frame?.filename;
|
|
1833
1834
|
if (!frame || "string" != typeof filename || "number" != typeof frame.lineno || shouldSkipContextLinesForFile(filename) || shouldSkipContextLinesForFrame(frame)) continue;
|
|
1834
1835
|
const filesToLinesOutput = filesToLines[filename];
|
|
@@ -1844,7 +1845,7 @@ async function addSourceContext(frames) {
|
|
|
1844
1845
|
if (!filesToLineRanges) continue;
|
|
1845
1846
|
filesToLineRanges.sort((a, b) => a - b);
|
|
1846
1847
|
const ranges = makeLineReaderRanges(filesToLineRanges);
|
|
1847
|
-
if (ranges.every((
|
|
1848
|
+
if (ranges.every((r2) => rangeExistsInContentCache(file, r2))) continue;
|
|
1848
1849
|
const cache = emplace(LRU_FILE_CONTENTS_CACHE, file, {});
|
|
1849
1850
|
readlinePromises.push(getContextLinesFromFile(file, ranges, cache));
|
|
1850
1851
|
}
|
|
@@ -1912,8 +1913,8 @@ function addSourceContextToFrames(frames, cache) {
|
|
|
1912
1913
|
function addContextToFrame(lineno, frame, contents) {
|
|
1913
1914
|
if (void 0 === frame.lineno || void 0 === contents) return;
|
|
1914
1915
|
frame.pre_context = [];
|
|
1915
|
-
for (let
|
|
1916
|
-
const line = contents[
|
|
1916
|
+
for (let i2 = makeRangeStart(lineno); i2 < lineno; i2++) {
|
|
1917
|
+
const line = contents[i2];
|
|
1917
1918
|
if (void 0 === line) return void clearLineContext(frame);
|
|
1918
1919
|
frame.pre_context.push(line);
|
|
1919
1920
|
}
|
|
@@ -1921,8 +1922,8 @@ function addContextToFrame(lineno, frame, contents) {
|
|
|
1921
1922
|
frame.context_line = contents[lineno];
|
|
1922
1923
|
const end = makeRangeEnd(lineno);
|
|
1923
1924
|
frame.post_context = [];
|
|
1924
|
-
for (let
|
|
1925
|
-
const line = contents[
|
|
1925
|
+
for (let i2 = lineno + 1; i2 <= end; i2++) {
|
|
1926
|
+
const line = contents[i2];
|
|
1926
1927
|
if (void 0 === line) break;
|
|
1927
1928
|
frame.post_context.push(line);
|
|
1928
1929
|
}
|
|
@@ -1943,29 +1944,29 @@ function shouldSkipContextLinesForFrame(frame) {
|
|
|
1943
1944
|
function rangeExistsInContentCache(file, range) {
|
|
1944
1945
|
const contents = LRU_FILE_CONTENTS_CACHE.get(file);
|
|
1945
1946
|
if (void 0 === contents) return false;
|
|
1946
|
-
for (let
|
|
1947
|
+
for (let i2 = range[0]; i2 <= range[1]; i2++) if (void 0 === contents[i2]) return false;
|
|
1947
1948
|
return true;
|
|
1948
1949
|
}
|
|
1949
1950
|
function makeLineReaderRanges(lines) {
|
|
1950
1951
|
if (!lines.length) return [];
|
|
1951
|
-
let
|
|
1952
|
+
let i2 = 0;
|
|
1952
1953
|
const line = lines[0];
|
|
1953
1954
|
if ("number" != typeof line) return [];
|
|
1954
1955
|
let current = makeContextRange(line);
|
|
1955
1956
|
const out = [];
|
|
1956
1957
|
while (true) {
|
|
1957
|
-
if (
|
|
1958
|
+
if (i2 === lines.length - 1) {
|
|
1958
1959
|
out.push(current);
|
|
1959
1960
|
break;
|
|
1960
1961
|
}
|
|
1961
|
-
const next = lines[
|
|
1962
|
+
const next = lines[i2 + 1];
|
|
1962
1963
|
if ("number" != typeof next) break;
|
|
1963
1964
|
if (next <= current[1]) current[1] = next + DEFAULT_LINES_OF_CONTEXT;
|
|
1964
1965
|
else {
|
|
1965
1966
|
out.push(current);
|
|
1966
1967
|
current = makeContextRange(next);
|
|
1967
1968
|
}
|
|
1968
|
-
|
|
1969
|
+
i2++;
|
|
1969
1970
|
}
|
|
1970
1971
|
return out;
|
|
1971
1972
|
}
|
|
@@ -3378,7 +3379,9 @@ const initServer = async (app, serverEnv) => {
|
|
|
3378
3379
|
if (isProduction$1) {
|
|
3379
3380
|
sessionConfig.cookie.secure = true;
|
|
3380
3381
|
}
|
|
3381
|
-
|
|
3382
|
+
const sessionMiddleware = session(sessionConfig);
|
|
3383
|
+
app.locals.rbSessionMiddleware = sessionMiddleware;
|
|
3384
|
+
app.use(sessionMiddleware);
|
|
3382
3385
|
};
|
|
3383
3386
|
async function hashPassword(password, salt) {
|
|
3384
3387
|
const keyLength = 64;
|
|
@@ -3422,15 +3425,15 @@ const parseEnvInt = (value) => {
|
|
|
3422
3425
|
return parsed;
|
|
3423
3426
|
};
|
|
3424
3427
|
const isPowerOfTwo = (value) => (value & value - 1) === 0;
|
|
3425
|
-
const estimateScryptMemoryBytes = ({ N, r, p }) => {
|
|
3426
|
-
return 128 *
|
|
3428
|
+
const estimateScryptMemoryBytes = ({ N, r: r2, p }) => {
|
|
3429
|
+
return 128 * r2 * (N + p);
|
|
3427
3430
|
};
|
|
3428
3431
|
const validateScryptParams = (params) => {
|
|
3429
|
-
const { N, r, p, keylen, saltBytes, maxmemBytes } = params;
|
|
3432
|
+
const { N, r: r2, p, keylen, saltBytes, maxmemBytes } = params;
|
|
3430
3433
|
if (!Number.isSafeInteger(N) || N < 2 || N > MAX_SCRYPT_N || !isPowerOfTwo(N)) {
|
|
3431
3434
|
return { ok: false, error: "invalid_scrypt_N" };
|
|
3432
3435
|
}
|
|
3433
|
-
if (!Number.isSafeInteger(
|
|
3436
|
+
if (!Number.isSafeInteger(r2) || r2 < 1 || r2 > MAX_SCRYPT_R) {
|
|
3434
3437
|
return { ok: false, error: "invalid_scrypt_r" };
|
|
3435
3438
|
}
|
|
3436
3439
|
if (!Number.isSafeInteger(p) || p < 1 || p > MAX_SCRYPT_P) {
|
|
@@ -3445,7 +3448,7 @@ const validateScryptParams = (params) => {
|
|
|
3445
3448
|
if (!Number.isSafeInteger(maxmemBytes) || maxmemBytes < 16 * 1024 * 1024 || maxmemBytes > MAX_SCRYPT_MAXMEM_BYTES) {
|
|
3446
3449
|
return { ok: false, error: "invalid_scrypt_maxmem" };
|
|
3447
3450
|
}
|
|
3448
|
-
const estimatedMem = estimateScryptMemoryBytes({ N, r, p });
|
|
3451
|
+
const estimatedMem = estimateScryptMemoryBytes({ N, r: r2, p });
|
|
3449
3452
|
if (estimatedMem > maxmemBytes) {
|
|
3450
3453
|
return { ok: false, error: "scrypt_params_exceed_maxmem" };
|
|
3451
3454
|
}
|
|
@@ -3480,9 +3483,9 @@ const getCurrentScryptParams = (opts) => {
|
|
|
3480
3483
|
return params;
|
|
3481
3484
|
};
|
|
3482
3485
|
const scryptAsync = async (password, salt, params) => {
|
|
3483
|
-
const { N, r, p, keylen, maxmemBytes } = params;
|
|
3486
|
+
const { N, r: r2, p, keylen, maxmemBytes } = params;
|
|
3484
3487
|
return await new Promise((resolve, reject) => {
|
|
3485
|
-
crypto.scrypt(password, salt, keylen, { N, r, p, maxmem: maxmemBytes }, (err, derivedKey) => {
|
|
3488
|
+
crypto.scrypt(password, salt, keylen, { N, r: r2, p, maxmem: maxmemBytes }, (err, derivedKey) => {
|
|
3486
3489
|
if (err) {
|
|
3487
3490
|
reject(err);
|
|
3488
3491
|
return;
|
|
@@ -3529,10 +3532,10 @@ const parseStoredScryptHash = (stored) => {
|
|
|
3529
3532
|
params.set(key, value);
|
|
3530
3533
|
}
|
|
3531
3534
|
const N = params.get("N");
|
|
3532
|
-
const
|
|
3535
|
+
const r2 = params.get("r");
|
|
3533
3536
|
const p = params.get("p");
|
|
3534
3537
|
const keylen = params.get("keylen");
|
|
3535
|
-
if (N === void 0 ||
|
|
3538
|
+
if (N === void 0 || r2 === void 0 || p === void 0 || keylen === void 0) return null;
|
|
3536
3539
|
if (params.size !== 4) return null;
|
|
3537
3540
|
const salt = parseB64(saltB64);
|
|
3538
3541
|
const dk = parseB64(dkB64);
|
|
@@ -3543,31 +3546,31 @@ const parseStoredScryptHash = (stored) => {
|
|
|
3543
3546
|
const currentMaxmemBytes = getCurrentMaxmemBytes();
|
|
3544
3547
|
const validated = validateScryptParams({
|
|
3545
3548
|
N,
|
|
3546
|
-
r,
|
|
3549
|
+
r: r2,
|
|
3547
3550
|
p,
|
|
3548
3551
|
keylen,
|
|
3549
3552
|
saltBytes: salt.length,
|
|
3550
3553
|
maxmemBytes: currentMaxmemBytes
|
|
3551
3554
|
});
|
|
3552
3555
|
if (!validated.ok) return null;
|
|
3553
|
-
return { N, r, p, keylen, salt, dk };
|
|
3556
|
+
return { N, r: r2, p, keylen, salt, dk };
|
|
3554
3557
|
};
|
|
3555
3558
|
async function hashPasswordForStorage(password, opts) {
|
|
3556
|
-
const { N, r, p, keylen, saltBytes, maxmemBytes } = getCurrentScryptParams(opts);
|
|
3559
|
+
const { N, r: r2, p, keylen, saltBytes, maxmemBytes } = getCurrentScryptParams(opts);
|
|
3557
3560
|
const salt = crypto.randomBytes(saltBytes);
|
|
3558
|
-
const dk = await scryptAsync(password, salt, { N, r, p, keylen, maxmemBytes });
|
|
3561
|
+
const dk = await scryptAsync(password, salt, { N, r: r2, p, keylen, maxmemBytes });
|
|
3559
3562
|
const saltB64 = salt.toString("base64");
|
|
3560
3563
|
const dkB64 = dk.toString("base64");
|
|
3561
|
-
return `$scrypt$N=${N},r=${
|
|
3564
|
+
return `$scrypt$N=${N},r=${r2},p=${p},keylen=${keylen}$${saltB64}$${dkB64}`;
|
|
3562
3565
|
}
|
|
3563
3566
|
async function verifyPasswordFromStorage(password, stored) {
|
|
3564
3567
|
const parsed = parseStoredScryptHash(stored);
|
|
3565
3568
|
if (!parsed) return false;
|
|
3566
|
-
const { N, r, p, keylen, salt, dk } = parsed;
|
|
3569
|
+
const { N, r: r2, p, keylen, salt, dk } = parsed;
|
|
3567
3570
|
const maxmemBytes = getCurrentMaxmemBytes();
|
|
3568
3571
|
let derivedKey;
|
|
3569
3572
|
try {
|
|
3570
|
-
derivedKey = await scryptAsync(password, salt, { N, r, p, keylen, maxmemBytes });
|
|
3573
|
+
derivedKey = await scryptAsync(password, salt, { N, r: r2, p, keylen, maxmemBytes });
|
|
3571
3574
|
} catch {
|
|
3572
3575
|
return false;
|
|
3573
3576
|
}
|
|
@@ -3590,7 +3593,7 @@ function createLocation(current, to, state = null, key) {
|
|
|
3590
3593
|
return location;
|
|
3591
3594
|
}
|
|
3592
3595
|
function getShortCircuitMatches(routes) {
|
|
3593
|
-
const route = routes.length === 1 ? routes[0] : routes.find((
|
|
3596
|
+
const route = routes.length === 1 ? routes[0] : routes.find((r2) => r2.index || !r2.path || r2.path === "/") || {
|
|
3594
3597
|
id: "__shim-error-route__"
|
|
3595
3598
|
};
|
|
3596
3599
|
return {
|
|
@@ -4095,7 +4098,10 @@ export {
|
|
|
4095
4098
|
getDerivedKey,
|
|
4096
4099
|
hashPassword,
|
|
4097
4100
|
hashPasswordForStorage,
|
|
4101
|
+
i as initRts,
|
|
4098
4102
|
initServer,
|
|
4103
|
+
n as notifyRtsModelChanged,
|
|
4104
|
+
r as registerRtsHandler,
|
|
4099
4105
|
sendEmail,
|
|
4100
4106
|
ssrMiddleware,
|
|
4101
4107
|
verifyPasswordFromStorage
|
package/dist/initServer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initServer.d.ts","sourceRoot":"","sources":["../src/initServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAuBrC,KAAK,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AA8EtD,eAAO,MAAM,UAAU,GAAU,KAAK,WAAW,EAAE,WAAW,SAAS,
|
|
1
|
+
{"version":3,"file":"initServer.d.ts","sourceRoot":"","sources":["../src/initServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAuBrC,KAAK,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AA8EtD,eAAO,MAAM,UAAU,GAAU,KAAK,WAAW,EAAE,WAAW,SAAS,kBA6DtE,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Server as HttpServer } from 'node:http';
|
|
2
|
+
import { RequestHandler } from 'express';
|
|
3
|
+
import { WebSocket } from 'ws';
|
|
4
|
+
type SocketMeta = {
|
|
5
|
+
tenantId: string;
|
|
6
|
+
userId: string;
|
|
7
|
+
};
|
|
8
|
+
type HandlerFn = (socket: RtsSocket) => void | (() => void);
|
|
9
|
+
declare class RtsSocket {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly tenantId: string;
|
|
12
|
+
readonly userId: string;
|
|
13
|
+
private readonly ws;
|
|
14
|
+
private readonly handlers;
|
|
15
|
+
constructor({ id, ws, meta, }: {
|
|
16
|
+
id: string;
|
|
17
|
+
ws: WebSocket;
|
|
18
|
+
meta: SocketMeta;
|
|
19
|
+
});
|
|
20
|
+
on(event: string, handler: (payload: unknown) => void): () => void;
|
|
21
|
+
off(event: string, handler: (payload: unknown) => void): void;
|
|
22
|
+
emit(event: string, payload?: unknown): void;
|
|
23
|
+
close(): void;
|
|
24
|
+
dispatch(event: string, payload: unknown): void;
|
|
25
|
+
}
|
|
26
|
+
export declare const initRts: ({ server, path, sessionMiddleware, }: {
|
|
27
|
+
server: HttpServer;
|
|
28
|
+
path?: string;
|
|
29
|
+
sessionMiddleware?: RequestHandler;
|
|
30
|
+
}) => void;
|
|
31
|
+
export declare const registerRtsHandler: (handler: HandlerFn) => void;
|
|
32
|
+
export declare const notifyRtsModelChanged: (tenantId: string, modelName: string) => void;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rts/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAG7C,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,IAAI,CAAA;AAqBlE,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAoBD,KAAK,SAAS,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;AAoB3D,cAAM,SAAS;IACb,SAAgB,EAAE,EAAE,MAAM,CAAA;IAC1B,SAAgB,QAAQ,EAAE,MAAM,CAAA;IAChC,SAAgB,MAAM,EAAE,MAAM,CAAA;IAE9B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqD;gBAE3D,EACjB,EAAE,EACF,EAAE,EACF,IAAI,GACL,EAAE;QACD,EAAE,EAAE,MAAM,CAAA;QACV,EAAE,EAAE,SAAS,CAAA;QACb,IAAI,EAAE,UAAU,CAAA;KACjB;IAOM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAO7D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,KAAK,IAAI,IAAI;IAQb,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;CAOvD;AA4aD,eAAO,MAAM,OAAO,GAAI,sCAIrB;IACD,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB,CAAC,EAAE,cAAc,CAAA;CACnC,KAAG,IAyFH,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,SAAS,KAAG,IAEvD,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,IAE3E,CAAA"}
|
package/dist/rts.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rts.d.ts","sourceRoot":"","sources":["../src/rts.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
|
package/dist/rts.js
ADDED
package/package.json
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpcbase/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.465.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
7
7
|
],
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./rts": {
|
|
17
|
+
"types": "./dist/rts.d.ts",
|
|
18
|
+
"import": "./dist/rts.js",
|
|
19
|
+
"default": "./dist/rts.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
10
22
|
"scripts": {
|
|
11
23
|
"build": "wireit",
|
|
12
24
|
"test": "wireit",
|
|
@@ -64,9 +76,11 @@
|
|
|
64
76
|
"express-session": "1.18.2",
|
|
65
77
|
"http-proxy-middleware": "3.0.5",
|
|
66
78
|
"redis": "5.10.0",
|
|
67
|
-
"resend": "6.5.2"
|
|
79
|
+
"resend": "6.5.2",
|
|
80
|
+
"ws": "8.18.0"
|
|
68
81
|
},
|
|
69
82
|
"devDependencies": {
|
|
83
|
+
"@types/ws": "8.18.1",
|
|
70
84
|
"request-ip": "3.3.0"
|
|
71
85
|
}
|
|
72
86
|
}
|