lakesync 0.1.5 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/adapter.d.ts +199 -19
  2. package/dist/adapter.js +19 -3
  3. package/dist/analyst.js +2 -2
  4. package/dist/{base-poller-CBvhdvcj.d.ts → base-poller-Bj9kX9dv.d.ts} +76 -19
  5. package/dist/catalogue.d.ts +1 -1
  6. package/dist/catalogue.js +3 -3
  7. package/dist/chunk-DGUM43GV.js +11 -0
  8. package/dist/{chunk-PWGQ3PXE.js → chunk-JI4C4R5H.js} +280 -140
  9. package/dist/chunk-JI4C4R5H.js.map +1 -0
  10. package/dist/{chunk-L4ZL5JA7.js → chunk-KVSWLIJR.js} +2 -2
  11. package/dist/{chunk-7UBS6MFH.js → chunk-LDFFCG2K.js} +377 -247
  12. package/dist/chunk-LDFFCG2K.js.map +1 -0
  13. package/dist/{chunk-Z7FGLEQU.js → chunk-LPWXOYNS.js} +376 -287
  14. package/dist/chunk-LPWXOYNS.js.map +1 -0
  15. package/dist/{chunk-SZSGSTVZ.js → chunk-PYRS74YP.js} +15 -4
  16. package/dist/{chunk-SZSGSTVZ.js.map → chunk-PYRS74YP.js.map} +1 -1
  17. package/dist/{chunk-TVLTXHW6.js → chunk-QNITY4F6.js} +30 -7
  18. package/dist/{chunk-TVLTXHW6.js.map → chunk-QNITY4F6.js.map} +1 -1
  19. package/dist/{chunk-46CKACNC.js → chunk-SSICS5KI.js} +2 -2
  20. package/dist/{chunk-B3QEUG6E.js → chunk-TMLG32QV.js} +2 -2
  21. package/dist/client.d.ts +164 -13
  22. package/dist/client.js +310 -163
  23. package/dist/client.js.map +1 -1
  24. package/dist/compactor.d.ts +1 -1
  25. package/dist/compactor.js +4 -4
  26. package/dist/connector-jira.d.ts +2 -2
  27. package/dist/connector-jira.js +3 -3
  28. package/dist/connector-salesforce.d.ts +2 -2
  29. package/dist/connector-salesforce.js +3 -3
  30. package/dist/{coordinator-DN8D8C7W.d.ts → coordinator-NXy6tA0h.d.ts} +23 -16
  31. package/dist/{db-types-B6_JKQWK.d.ts → db-types-CfLMUBfW.d.ts} +1 -1
  32. package/dist/gateway-server.d.ts +158 -64
  33. package/dist/gateway-server.js +482 -4003
  34. package/dist/gateway-server.js.map +1 -1
  35. package/dist/gateway.d.ts +61 -104
  36. package/dist/gateway.js +12 -6
  37. package/dist/index.d.ts +45 -10
  38. package/dist/index.js +14 -2
  39. package/dist/parquet.d.ts +1 -1
  40. package/dist/parquet.js +3 -3
  41. package/dist/proto.d.ts +1 -1
  42. package/dist/proto.js +3 -3
  43. package/dist/react.d.ts +47 -10
  44. package/dist/react.js +88 -40
  45. package/dist/react.js.map +1 -1
  46. package/dist/{registry-BN_9spxE.d.ts → registry-BcspAtZI.d.ts} +19 -4
  47. package/dist/{gateway-CvO7Xy3T.d.ts → request-handler-pUvL7ozF.d.ts} +139 -10
  48. package/dist/{resolver-BZURzdlL.d.ts → resolver-CXxmC0jR.d.ts} +1 -1
  49. package/dist/{src-RR7I76OL.js → src-B6NLV3FP.js} +4 -4
  50. package/dist/{src-SLVE5567.js → src-ROW4XLO7.js} +15 -3
  51. package/dist/{src-V2CTPR7V.js → src-ZRHKG42A.js} +4 -4
  52. package/dist/{types-GGBfZBKQ.d.ts → types-BdGBv2ba.d.ts} +23 -2
  53. package/dist/{types-D-E0VrfS.d.ts → types-BrcD1oJg.d.ts} +26 -19
  54. package/package.json +1 -1
  55. package/dist/chunk-7D4SUZUM.js +0 -38
  56. package/dist/chunk-7UBS6MFH.js.map +0 -1
  57. package/dist/chunk-PWGQ3PXE.js.map +0 -1
  58. package/dist/chunk-Z7FGLEQU.js.map +0 -1
  59. /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
  60. /package/dist/{chunk-L4ZL5JA7.js.map → chunk-KVSWLIJR.js.map} +0 -0
  61. /package/dist/{chunk-46CKACNC.js.map → chunk-SSICS5KI.js.map} +0 -0
  62. /package/dist/{chunk-B3QEUG6E.js.map → chunk-TMLG32QV.js.map} +0 -0
  63. /package/dist/{src-RR7I76OL.js.map → src-B6NLV3FP.js.map} +0 -0
  64. /package/dist/{src-SLVE5567.js.map → src-ROW4XLO7.js.map} +0 -0
  65. /package/dist/{src-V2CTPR7V.js.map → src-ZRHKG42A.js.map} +0 -0
@@ -15,12 +15,12 @@ import {
15
15
  handleSaveSchema,
16
16
  handleSaveSyncRules,
17
17
  handleUnregisterConnector
18
- } from "./chunk-PWGQ3PXE.js";
18
+ } from "./chunk-JI4C4R5H.js";
19
19
  import {
20
20
  createDatabaseAdapter,
21
21
  createQueryFn
22
- } from "./chunk-Z7FGLEQU.js";
23
- import "./chunk-B3QEUG6E.js";
22
+ } from "./chunk-LPWXOYNS.js";
23
+ import "./chunk-TMLG32QV.js";
24
24
  import {
25
25
  TAG_SYNC_PULL,
26
26
  TAG_SYNC_PUSH,
@@ -28,8 +28,8 @@ import {
28
28
  decodeSyncPush,
29
29
  encodeBroadcastFrame,
30
30
  encodeSyncResponse
31
- } from "./chunk-L4ZL5JA7.js";
32
- import "./chunk-46CKACNC.js";
31
+ } from "./chunk-KVSWLIJR.js";
32
+ import "./chunk-SSICS5KI.js";
33
33
  import {
34
34
  AuthError,
35
35
  HLC,
@@ -39,3613 +39,52 @@ import {
39
39
  filterDeltas,
40
40
  isActionHandler,
41
41
  verifyToken
42
- } from "./chunk-7UBS6MFH.js";
42
+ } from "./chunk-LDFFCG2K.js";
43
43
  import {
44
- __commonJS,
45
- __require,
46
- __toESM
47
- } from "./chunk-7D4SUZUM.js";
44
+ __require
45
+ } from "./chunk-DGUM43GV.js";
48
46
 
49
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/stream.js
50
- var require_stream = __commonJS({
51
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/stream.js"(exports, module) {
52
- "use strict";
53
- var { Duplex } = __require("stream");
54
- function emitClose(stream) {
55
- stream.emit("close");
56
- }
57
- function duplexOnEnd() {
58
- if (!this.destroyed && this._writableState.finished) {
59
- this.destroy();
60
- }
61
- }
62
- function duplexOnError(err) {
63
- this.removeListener("error", duplexOnError);
64
- this.destroy();
65
- if (this.listenerCount("error") === 0) {
66
- this.emit("error", err);
67
- }
68
- }
69
- function createWebSocketStream2(ws, options) {
70
- let terminateOnDestroy = true;
71
- const duplex = new Duplex({
72
- ...options,
73
- autoDestroy: false,
74
- emitClose: false,
75
- objectMode: false,
76
- writableObjectMode: false
77
- });
78
- ws.on("message", function message(msg, isBinary) {
79
- const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
80
- if (!duplex.push(data)) ws.pause();
81
- });
82
- ws.once("error", function error(err) {
83
- if (duplex.destroyed) return;
84
- terminateOnDestroy = false;
85
- duplex.destroy(err);
86
- });
87
- ws.once("close", function close() {
88
- if (duplex.destroyed) return;
89
- duplex.push(null);
90
- });
91
- duplex._destroy = function(err, callback) {
92
- if (ws.readyState === ws.CLOSED) {
93
- callback(err);
94
- process.nextTick(emitClose, duplex);
95
- return;
96
- }
97
- let called = false;
98
- ws.once("error", function error(err2) {
99
- called = true;
100
- callback(err2);
101
- });
102
- ws.once("close", function close() {
103
- if (!called) callback(err);
104
- process.nextTick(emitClose, duplex);
105
- });
106
- if (terminateOnDestroy) ws.terminate();
107
- };
108
- duplex._final = function(callback) {
109
- if (ws.readyState === ws.CONNECTING) {
110
- ws.once("open", function open() {
111
- duplex._final(callback);
112
- });
113
- return;
114
- }
115
- if (ws._socket === null) return;
116
- if (ws._socket._writableState.finished) {
117
- callback();
118
- if (duplex._readableState.endEmitted) duplex.destroy();
119
- } else {
120
- ws._socket.once("finish", function finish() {
121
- callback();
122
- });
123
- ws.close();
124
- }
125
- };
126
- duplex._read = function() {
127
- if (ws.isPaused) ws.resume();
128
- };
129
- duplex._write = function(chunk, encoding, callback) {
130
- if (ws.readyState === ws.CONNECTING) {
131
- ws.once("open", function open() {
132
- duplex._write(chunk, encoding, callback);
133
- });
134
- return;
135
- }
136
- ws.send(chunk, callback);
137
- };
138
- duplex.on("end", duplexOnEnd);
139
- duplex.on("error", duplexOnError);
140
- return duplex;
141
- }
142
- module.exports = createWebSocketStream2;
143
- }
144
- });
145
-
146
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/constants.js
147
- var require_constants = __commonJS({
148
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/constants.js"(exports, module) {
149
- "use strict";
150
- var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
151
- var hasBlob = typeof Blob !== "undefined";
152
- if (hasBlob) BINARY_TYPES.push("blob");
153
- module.exports = {
154
- BINARY_TYPES,
155
- EMPTY_BUFFER: Buffer.alloc(0),
156
- GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
157
- hasBlob,
158
- kForOnEventAttribute: /* @__PURE__ */ Symbol("kIsForOnEventAttribute"),
159
- kListener: /* @__PURE__ */ Symbol("kListener"),
160
- kStatusCode: /* @__PURE__ */ Symbol("status-code"),
161
- kWebSocket: /* @__PURE__ */ Symbol("websocket"),
162
- NOOP: () => {
163
- }
164
- };
165
- }
166
- });
167
-
168
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/buffer-util.js
169
- var require_buffer_util = __commonJS({
170
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/buffer-util.js"(exports, module) {
171
- "use strict";
172
- var { EMPTY_BUFFER } = require_constants();
173
- var FastBuffer = Buffer[Symbol.species];
174
- function concat(list, totalLength) {
175
- if (list.length === 0) return EMPTY_BUFFER;
176
- if (list.length === 1) return list[0];
177
- const target = Buffer.allocUnsafe(totalLength);
178
- let offset = 0;
179
- for (let i = 0; i < list.length; i++) {
180
- const buf = list[i];
181
- target.set(buf, offset);
182
- offset += buf.length;
183
- }
184
- if (offset < totalLength) {
185
- return new FastBuffer(target.buffer, target.byteOffset, offset);
186
- }
187
- return target;
188
- }
189
- function _mask(source, mask, output, offset, length) {
190
- for (let i = 0; i < length; i++) {
191
- output[offset + i] = source[i] ^ mask[i & 3];
192
- }
193
- }
194
- function _unmask(buffer, mask) {
195
- for (let i = 0; i < buffer.length; i++) {
196
- buffer[i] ^= mask[i & 3];
197
- }
198
- }
199
- function toArrayBuffer(buf) {
200
- if (buf.length === buf.buffer.byteLength) {
201
- return buf.buffer;
202
- }
203
- return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
204
- }
205
- function toBuffer(data) {
206
- toBuffer.readOnly = true;
207
- if (Buffer.isBuffer(data)) return data;
208
- let buf;
209
- if (data instanceof ArrayBuffer) {
210
- buf = new FastBuffer(data);
211
- } else if (ArrayBuffer.isView(data)) {
212
- buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
213
- } else {
214
- buf = Buffer.from(data);
215
- toBuffer.readOnly = false;
216
- }
217
- return buf;
218
- }
219
- module.exports = {
220
- concat,
221
- mask: _mask,
222
- toArrayBuffer,
223
- toBuffer,
224
- unmask: _unmask
225
- };
226
- if (!process.env.WS_NO_BUFFER_UTIL) {
227
- try {
228
- const bufferUtil = __require("bufferutil");
229
- module.exports.mask = function(source, mask, output, offset, length) {
230
- if (length < 48) _mask(source, mask, output, offset, length);
231
- else bufferUtil.mask(source, mask, output, offset, length);
232
- };
233
- module.exports.unmask = function(buffer, mask) {
234
- if (buffer.length < 32) _unmask(buffer, mask);
235
- else bufferUtil.unmask(buffer, mask);
236
- };
237
- } catch (e) {
238
- }
239
- }
240
- }
241
- });
242
-
243
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/limiter.js
244
- var require_limiter = __commonJS({
245
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/limiter.js"(exports, module) {
246
- "use strict";
247
- var kDone = /* @__PURE__ */ Symbol("kDone");
248
- var kRun = /* @__PURE__ */ Symbol("kRun");
249
- var Limiter = class {
250
- /**
251
- * Creates a new `Limiter`.
252
- *
253
- * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
254
- * to run concurrently
255
- */
256
- constructor(concurrency) {
257
- this[kDone] = () => {
258
- this.pending--;
259
- this[kRun]();
260
- };
261
- this.concurrency = concurrency || Infinity;
262
- this.jobs = [];
263
- this.pending = 0;
264
- }
265
- /**
266
- * Adds a job to the queue.
267
- *
268
- * @param {Function} job The job to run
269
- * @public
270
- */
271
- add(job) {
272
- this.jobs.push(job);
273
- this[kRun]();
274
- }
275
- /**
276
- * Removes a job from the queue and runs it if possible.
277
- *
278
- * @private
279
- */
280
- [kRun]() {
281
- if (this.pending === this.concurrency) return;
282
- if (this.jobs.length) {
283
- const job = this.jobs.shift();
284
- this.pending++;
285
- job(this[kDone]);
286
- }
287
- }
288
- };
289
- module.exports = Limiter;
290
- }
291
- });
292
-
293
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/permessage-deflate.js
294
- var require_permessage_deflate = __commonJS({
295
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/permessage-deflate.js"(exports, module) {
296
- "use strict";
297
- var zlib = __require("zlib");
298
- var bufferUtil = require_buffer_util();
299
- var Limiter = require_limiter();
300
- var { kStatusCode } = require_constants();
301
- var FastBuffer = Buffer[Symbol.species];
302
- var TRAILER = Buffer.from([0, 0, 255, 255]);
303
- var kPerMessageDeflate = /* @__PURE__ */ Symbol("permessage-deflate");
304
- var kTotalLength = /* @__PURE__ */ Symbol("total-length");
305
- var kCallback = /* @__PURE__ */ Symbol("callback");
306
- var kBuffers = /* @__PURE__ */ Symbol("buffers");
307
- var kError = /* @__PURE__ */ Symbol("error");
308
- var zlibLimiter;
309
- var PerMessageDeflate = class {
310
- /**
311
- * Creates a PerMessageDeflate instance.
312
- *
313
- * @param {Object} [options] Configuration options
314
- * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
315
- * for, or request, a custom client window size
316
- * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
317
- * acknowledge disabling of client context takeover
318
- * @param {Number} [options.concurrencyLimit=10] The number of concurrent
319
- * calls to zlib
320
- * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
321
- * use of a custom server window size
322
- * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
323
- * disabling of server context takeover
324
- * @param {Number} [options.threshold=1024] Size (in bytes) below which
325
- * messages should not be compressed if context takeover is disabled
326
- * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
327
- * deflate
328
- * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
329
- * inflate
330
- * @param {Boolean} [isServer=false] Create the instance in either server or
331
- * client mode
332
- * @param {Number} [maxPayload=0] The maximum allowed message length
333
- */
334
- constructor(options, isServer, maxPayload) {
335
- this._maxPayload = maxPayload | 0;
336
- this._options = options || {};
337
- this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
338
- this._isServer = !!isServer;
339
- this._deflate = null;
340
- this._inflate = null;
341
- this.params = null;
342
- if (!zlibLimiter) {
343
- const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10;
344
- zlibLimiter = new Limiter(concurrency);
345
- }
346
- }
347
- /**
348
- * @type {String}
349
- */
350
- static get extensionName() {
351
- return "permessage-deflate";
352
- }
353
- /**
354
- * Create an extension negotiation offer.
355
- *
356
- * @return {Object} Extension parameters
357
- * @public
358
- */
359
- offer() {
360
- const params = {};
361
- if (this._options.serverNoContextTakeover) {
362
- params.server_no_context_takeover = true;
363
- }
364
- if (this._options.clientNoContextTakeover) {
365
- params.client_no_context_takeover = true;
366
- }
367
- if (this._options.serverMaxWindowBits) {
368
- params.server_max_window_bits = this._options.serverMaxWindowBits;
369
- }
370
- if (this._options.clientMaxWindowBits) {
371
- params.client_max_window_bits = this._options.clientMaxWindowBits;
372
- } else if (this._options.clientMaxWindowBits == null) {
373
- params.client_max_window_bits = true;
374
- }
375
- return params;
376
- }
377
- /**
378
- * Accept an extension negotiation offer/response.
379
- *
380
- * @param {Array} configurations The extension negotiation offers/reponse
381
- * @return {Object} Accepted configuration
382
- * @public
383
- */
384
- accept(configurations) {
385
- configurations = this.normalizeParams(configurations);
386
- this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations);
387
- return this.params;
388
- }
389
- /**
390
- * Releases all resources used by the extension.
391
- *
392
- * @public
393
- */
394
- cleanup() {
395
- if (this._inflate) {
396
- this._inflate.close();
397
- this._inflate = null;
398
- }
399
- if (this._deflate) {
400
- const callback = this._deflate[kCallback];
401
- this._deflate.close();
402
- this._deflate = null;
403
- if (callback) {
404
- callback(
405
- new Error(
406
- "The deflate stream was closed while data was being processed"
407
- )
408
- );
409
- }
410
- }
411
- }
412
- /**
413
- * Accept an extension negotiation offer.
414
- *
415
- * @param {Array} offers The extension negotiation offers
416
- * @return {Object} Accepted configuration
417
- * @private
418
- */
419
- acceptAsServer(offers) {
420
- const opts = this._options;
421
- const accepted = offers.find((params) => {
422
- if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
423
- return false;
424
- }
425
- return true;
426
- });
427
- if (!accepted) {
428
- throw new Error("None of the extension offers can be accepted");
429
- }
430
- if (opts.serverNoContextTakeover) {
431
- accepted.server_no_context_takeover = true;
432
- }
433
- if (opts.clientNoContextTakeover) {
434
- accepted.client_no_context_takeover = true;
435
- }
436
- if (typeof opts.serverMaxWindowBits === "number") {
437
- accepted.server_max_window_bits = opts.serverMaxWindowBits;
438
- }
439
- if (typeof opts.clientMaxWindowBits === "number") {
440
- accepted.client_max_window_bits = opts.clientMaxWindowBits;
441
- } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) {
442
- delete accepted.client_max_window_bits;
443
- }
444
- return accepted;
445
- }
446
- /**
447
- * Accept the extension negotiation response.
448
- *
449
- * @param {Array} response The extension negotiation response
450
- * @return {Object} Accepted configuration
451
- * @private
452
- */
453
- acceptAsClient(response) {
454
- const params = response[0];
455
- if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) {
456
- throw new Error('Unexpected parameter "client_no_context_takeover"');
457
- }
458
- if (!params.client_max_window_bits) {
459
- if (typeof this._options.clientMaxWindowBits === "number") {
460
- params.client_max_window_bits = this._options.clientMaxWindowBits;
461
- }
462
- } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) {
463
- throw new Error(
464
- 'Unexpected or invalid parameter "client_max_window_bits"'
465
- );
466
- }
467
- return params;
468
- }
469
- /**
470
- * Normalize parameters.
471
- *
472
- * @param {Array} configurations The extension negotiation offers/reponse
473
- * @return {Array} The offers/response with normalized parameters
474
- * @private
475
- */
476
- normalizeParams(configurations) {
477
- configurations.forEach((params) => {
478
- Object.keys(params).forEach((key) => {
479
- let value = params[key];
480
- if (value.length > 1) {
481
- throw new Error(`Parameter "${key}" must have only a single value`);
482
- }
483
- value = value[0];
484
- if (key === "client_max_window_bits") {
485
- if (value !== true) {
486
- const num = +value;
487
- if (!Number.isInteger(num) || num < 8 || num > 15) {
488
- throw new TypeError(
489
- `Invalid value for parameter "${key}": ${value}`
490
- );
491
- }
492
- value = num;
493
- } else if (!this._isServer) {
494
- throw new TypeError(
495
- `Invalid value for parameter "${key}": ${value}`
496
- );
497
- }
498
- } else if (key === "server_max_window_bits") {
499
- const num = +value;
500
- if (!Number.isInteger(num) || num < 8 || num > 15) {
501
- throw new TypeError(
502
- `Invalid value for parameter "${key}": ${value}`
503
- );
504
- }
505
- value = num;
506
- } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
507
- if (value !== true) {
508
- throw new TypeError(
509
- `Invalid value for parameter "${key}": ${value}`
510
- );
511
- }
512
- } else {
513
- throw new Error(`Unknown parameter "${key}"`);
514
- }
515
- params[key] = value;
516
- });
517
- });
518
- return configurations;
519
- }
520
- /**
521
- * Decompress data. Concurrency limited.
522
- *
523
- * @param {Buffer} data Compressed data
524
- * @param {Boolean} fin Specifies whether or not this is the last fragment
525
- * @param {Function} callback Callback
526
- * @public
527
- */
528
- decompress(data, fin, callback) {
529
- zlibLimiter.add((done) => {
530
- this._decompress(data, fin, (err, result) => {
531
- done();
532
- callback(err, result);
533
- });
534
- });
535
- }
536
- /**
537
- * Compress data. Concurrency limited.
538
- *
539
- * @param {(Buffer|String)} data Data to compress
540
- * @param {Boolean} fin Specifies whether or not this is the last fragment
541
- * @param {Function} callback Callback
542
- * @public
543
- */
544
- compress(data, fin, callback) {
545
- zlibLimiter.add((done) => {
546
- this._compress(data, fin, (err, result) => {
547
- done();
548
- callback(err, result);
549
- });
550
- });
551
- }
552
- /**
553
- * Decompress data.
554
- *
555
- * @param {Buffer} data Compressed data
556
- * @param {Boolean} fin Specifies whether or not this is the last fragment
557
- * @param {Function} callback Callback
558
- * @private
559
- */
560
- _decompress(data, fin, callback) {
561
- const endpoint = this._isServer ? "client" : "server";
562
- if (!this._inflate) {
563
- const key = `${endpoint}_max_window_bits`;
564
- const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
565
- this._inflate = zlib.createInflateRaw({
566
- ...this._options.zlibInflateOptions,
567
- windowBits
568
- });
569
- this._inflate[kPerMessageDeflate] = this;
570
- this._inflate[kTotalLength] = 0;
571
- this._inflate[kBuffers] = [];
572
- this._inflate.on("error", inflateOnError);
573
- this._inflate.on("data", inflateOnData);
574
- }
575
- this._inflate[kCallback] = callback;
576
- this._inflate.write(data);
577
- if (fin) this._inflate.write(TRAILER);
578
- this._inflate.flush(() => {
579
- const err = this._inflate[kError];
580
- if (err) {
581
- this._inflate.close();
582
- this._inflate = null;
583
- callback(err);
584
- return;
585
- }
586
- const data2 = bufferUtil.concat(
587
- this._inflate[kBuffers],
588
- this._inflate[kTotalLength]
589
- );
590
- if (this._inflate._readableState.endEmitted) {
591
- this._inflate.close();
592
- this._inflate = null;
593
- } else {
594
- this._inflate[kTotalLength] = 0;
595
- this._inflate[kBuffers] = [];
596
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
597
- this._inflate.reset();
598
- }
599
- }
600
- callback(null, data2);
601
- });
602
- }
603
- /**
604
- * Compress data.
605
- *
606
- * @param {(Buffer|String)} data Data to compress
607
- * @param {Boolean} fin Specifies whether or not this is the last fragment
608
- * @param {Function} callback Callback
609
- * @private
610
- */
611
- _compress(data, fin, callback) {
612
- const endpoint = this._isServer ? "server" : "client";
613
- if (!this._deflate) {
614
- const key = `${endpoint}_max_window_bits`;
615
- const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
616
- this._deflate = zlib.createDeflateRaw({
617
- ...this._options.zlibDeflateOptions,
618
- windowBits
619
- });
620
- this._deflate[kTotalLength] = 0;
621
- this._deflate[kBuffers] = [];
622
- this._deflate.on("data", deflateOnData);
623
- }
624
- this._deflate[kCallback] = callback;
625
- this._deflate.write(data);
626
- this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
627
- if (!this._deflate) {
628
- return;
629
- }
630
- let data2 = bufferUtil.concat(
631
- this._deflate[kBuffers],
632
- this._deflate[kTotalLength]
633
- );
634
- if (fin) {
635
- data2 = new FastBuffer(data2.buffer, data2.byteOffset, data2.length - 4);
636
- }
637
- this._deflate[kCallback] = null;
638
- this._deflate[kTotalLength] = 0;
639
- this._deflate[kBuffers] = [];
640
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
641
- this._deflate.reset();
642
- }
643
- callback(null, data2);
644
- });
645
- }
646
- };
647
- module.exports = PerMessageDeflate;
648
- function deflateOnData(chunk) {
649
- this[kBuffers].push(chunk);
650
- this[kTotalLength] += chunk.length;
651
- }
652
- function inflateOnData(chunk) {
653
- this[kTotalLength] += chunk.length;
654
- if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) {
655
- this[kBuffers].push(chunk);
656
- return;
657
- }
658
- this[kError] = new RangeError("Max payload size exceeded");
659
- this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH";
660
- this[kError][kStatusCode] = 1009;
661
- this.removeListener("data", inflateOnData);
662
- this.reset();
663
- }
664
- function inflateOnError(err) {
665
- this[kPerMessageDeflate]._inflate = null;
666
- err[kStatusCode] = 1007;
667
- this[kCallback](err);
668
- }
669
- }
670
- });
671
-
672
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/validation.js
673
- var require_validation = __commonJS({
674
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/validation.js"(exports, module) {
675
- "use strict";
676
- var { isUtf8 } = __require("buffer");
677
- var { hasBlob } = require_constants();
678
- var tokenChars = [
679
- 0,
680
- 0,
681
- 0,
682
- 0,
683
- 0,
684
- 0,
685
- 0,
686
- 0,
687
- 0,
688
- 0,
689
- 0,
690
- 0,
691
- 0,
692
- 0,
693
- 0,
694
- 0,
695
- // 0 - 15
696
- 0,
697
- 0,
698
- 0,
699
- 0,
700
- 0,
701
- 0,
702
- 0,
703
- 0,
704
- 0,
705
- 0,
706
- 0,
707
- 0,
708
- 0,
709
- 0,
710
- 0,
711
- 0,
712
- // 16 - 31
713
- 0,
714
- 1,
715
- 0,
716
- 1,
717
- 1,
718
- 1,
719
- 1,
720
- 1,
721
- 0,
722
- 0,
723
- 1,
724
- 1,
725
- 0,
726
- 1,
727
- 1,
728
- 0,
729
- // 32 - 47
730
- 1,
731
- 1,
732
- 1,
733
- 1,
734
- 1,
735
- 1,
736
- 1,
737
- 1,
738
- 1,
739
- 1,
740
- 0,
741
- 0,
742
- 0,
743
- 0,
744
- 0,
745
- 0,
746
- // 48 - 63
747
- 0,
748
- 1,
749
- 1,
750
- 1,
751
- 1,
752
- 1,
753
- 1,
754
- 1,
755
- 1,
756
- 1,
757
- 1,
758
- 1,
759
- 1,
760
- 1,
761
- 1,
762
- 1,
763
- // 64 - 79
764
- 1,
765
- 1,
766
- 1,
767
- 1,
768
- 1,
769
- 1,
770
- 1,
771
- 1,
772
- 1,
773
- 1,
774
- 1,
775
- 0,
776
- 0,
777
- 0,
778
- 1,
779
- 1,
780
- // 80 - 95
781
- 1,
782
- 1,
783
- 1,
784
- 1,
785
- 1,
786
- 1,
787
- 1,
788
- 1,
789
- 1,
790
- 1,
791
- 1,
792
- 1,
793
- 1,
794
- 1,
795
- 1,
796
- 1,
797
- // 96 - 111
798
- 1,
799
- 1,
800
- 1,
801
- 1,
802
- 1,
803
- 1,
804
- 1,
805
- 1,
806
- 1,
807
- 1,
808
- 1,
809
- 0,
810
- 1,
811
- 0,
812
- 1,
813
- 0
814
- // 112 - 127
815
- ];
816
- function isValidStatusCode(code) {
817
- return code >= 1e3 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3e3 && code <= 4999;
818
- }
819
- function _isValidUTF8(buf) {
820
- const len = buf.length;
821
- let i = 0;
822
- while (i < len) {
823
- if ((buf[i] & 128) === 0) {
824
- i++;
825
- } else if ((buf[i] & 224) === 192) {
826
- if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) {
827
- return false;
828
- }
829
- i += 2;
830
- } else if ((buf[i] & 240) === 224) {
831
- if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || // Overlong
832
- buf[i] === 237 && (buf[i + 1] & 224) === 160) {
833
- return false;
834
- }
835
- i += 3;
836
- } else if ((buf[i] & 248) === 240) {
837
- if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || // Overlong
838
- buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) {
839
- return false;
840
- }
841
- i += 4;
842
- } else {
843
- return false;
844
- }
845
- }
846
- return true;
847
- }
848
- function isBlob(value) {
849
- return hasBlob && typeof value === "object" && typeof value.arrayBuffer === "function" && typeof value.type === "string" && typeof value.stream === "function" && (value[Symbol.toStringTag] === "Blob" || value[Symbol.toStringTag] === "File");
850
- }
851
- module.exports = {
852
- isBlob,
853
- isValidStatusCode,
854
- isValidUTF8: _isValidUTF8,
855
- tokenChars
856
- };
857
- if (isUtf8) {
858
- module.exports.isValidUTF8 = function(buf) {
859
- return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
860
- };
861
- } else if (!process.env.WS_NO_UTF_8_VALIDATE) {
862
- try {
863
- const isValidUTF8 = __require("utf-8-validate");
864
- module.exports.isValidUTF8 = function(buf) {
865
- return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
866
- };
867
- } catch (e) {
868
- }
869
- }
870
- }
871
- });
872
-
873
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/receiver.js
874
- var require_receiver = __commonJS({
875
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/receiver.js"(exports, module) {
876
- "use strict";
877
- var { Writable } = __require("stream");
878
- var PerMessageDeflate = require_permessage_deflate();
879
- var {
880
- BINARY_TYPES,
881
- EMPTY_BUFFER,
882
- kStatusCode,
883
- kWebSocket
884
- } = require_constants();
885
- var { concat, toArrayBuffer, unmask } = require_buffer_util();
886
- var { isValidStatusCode, isValidUTF8 } = require_validation();
887
- var FastBuffer = Buffer[Symbol.species];
888
- var GET_INFO = 0;
889
- var GET_PAYLOAD_LENGTH_16 = 1;
890
- var GET_PAYLOAD_LENGTH_64 = 2;
891
- var GET_MASK = 3;
892
- var GET_DATA = 4;
893
- var INFLATING = 5;
894
- var DEFER_EVENT = 6;
895
- var Receiver2 = class extends Writable {
896
- /**
897
- * Creates a Receiver instance.
898
- *
899
- * @param {Object} [options] Options object
900
- * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
901
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
902
- * multiple times in the same tick
903
- * @param {String} [options.binaryType=nodebuffer] The type for binary data
904
- * @param {Object} [options.extensions] An object containing the negotiated
905
- * extensions
906
- * @param {Boolean} [options.isServer=false] Specifies whether to operate in
907
- * client or server mode
908
- * @param {Number} [options.maxPayload=0] The maximum allowed message length
909
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
910
- * not to skip UTF-8 validation for text and close messages
911
- */
912
- constructor(options = {}) {
913
- super();
914
- this._allowSynchronousEvents = options.allowSynchronousEvents !== void 0 ? options.allowSynchronousEvents : true;
915
- this._binaryType = options.binaryType || BINARY_TYPES[0];
916
- this._extensions = options.extensions || {};
917
- this._isServer = !!options.isServer;
918
- this._maxPayload = options.maxPayload | 0;
919
- this._skipUTF8Validation = !!options.skipUTF8Validation;
920
- this[kWebSocket] = void 0;
921
- this._bufferedBytes = 0;
922
- this._buffers = [];
923
- this._compressed = false;
924
- this._payloadLength = 0;
925
- this._mask = void 0;
926
- this._fragmented = 0;
927
- this._masked = false;
928
- this._fin = false;
929
- this._opcode = 0;
930
- this._totalPayloadLength = 0;
931
- this._messageLength = 0;
932
- this._fragments = [];
933
- this._errored = false;
934
- this._loop = false;
935
- this._state = GET_INFO;
936
- }
937
- /**
938
- * Implements `Writable.prototype._write()`.
939
- *
940
- * @param {Buffer} chunk The chunk of data to write
941
- * @param {String} encoding The character encoding of `chunk`
942
- * @param {Function} cb Callback
943
- * @private
944
- */
945
- _write(chunk, encoding, cb) {
946
- if (this._opcode === 8 && this._state == GET_INFO) return cb();
947
- this._bufferedBytes += chunk.length;
948
- this._buffers.push(chunk);
949
- this.startLoop(cb);
950
- }
951
- /**
952
- * Consumes `n` bytes from the buffered data.
953
- *
954
- * @param {Number} n The number of bytes to consume
955
- * @return {Buffer} The consumed bytes
956
- * @private
957
- */
958
- consume(n) {
959
- this._bufferedBytes -= n;
960
- if (n === this._buffers[0].length) return this._buffers.shift();
961
- if (n < this._buffers[0].length) {
962
- const buf = this._buffers[0];
963
- this._buffers[0] = new FastBuffer(
964
- buf.buffer,
965
- buf.byteOffset + n,
966
- buf.length - n
967
- );
968
- return new FastBuffer(buf.buffer, buf.byteOffset, n);
969
- }
970
- const dst = Buffer.allocUnsafe(n);
971
- do {
972
- const buf = this._buffers[0];
973
- const offset = dst.length - n;
974
- if (n >= buf.length) {
975
- dst.set(this._buffers.shift(), offset);
976
- } else {
977
- dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
978
- this._buffers[0] = new FastBuffer(
979
- buf.buffer,
980
- buf.byteOffset + n,
981
- buf.length - n
982
- );
983
- }
984
- n -= buf.length;
985
- } while (n > 0);
986
- return dst;
987
- }
988
- /**
989
- * Starts the parsing loop.
990
- *
991
- * @param {Function} cb Callback
992
- * @private
993
- */
994
- startLoop(cb) {
995
- this._loop = true;
996
- do {
997
- switch (this._state) {
998
- case GET_INFO:
999
- this.getInfo(cb);
1000
- break;
1001
- case GET_PAYLOAD_LENGTH_16:
1002
- this.getPayloadLength16(cb);
1003
- break;
1004
- case GET_PAYLOAD_LENGTH_64:
1005
- this.getPayloadLength64(cb);
1006
- break;
1007
- case GET_MASK:
1008
- this.getMask();
1009
- break;
1010
- case GET_DATA:
1011
- this.getData(cb);
1012
- break;
1013
- case INFLATING:
1014
- case DEFER_EVENT:
1015
- this._loop = false;
1016
- return;
1017
- }
1018
- } while (this._loop);
1019
- if (!this._errored) cb();
1020
- }
1021
- /**
1022
- * Reads the first two bytes of a frame.
1023
- *
1024
- * @param {Function} cb Callback
1025
- * @private
1026
- */
1027
- getInfo(cb) {
1028
- if (this._bufferedBytes < 2) {
1029
- this._loop = false;
1030
- return;
1031
- }
1032
- const buf = this.consume(2);
1033
- if ((buf[0] & 48) !== 0) {
1034
- const error = this.createError(
1035
- RangeError,
1036
- "RSV2 and RSV3 must be clear",
1037
- true,
1038
- 1002,
1039
- "WS_ERR_UNEXPECTED_RSV_2_3"
1040
- );
1041
- cb(error);
1042
- return;
1043
- }
1044
- const compressed = (buf[0] & 64) === 64;
1045
- if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
1046
- const error = this.createError(
1047
- RangeError,
1048
- "RSV1 must be clear",
1049
- true,
1050
- 1002,
1051
- "WS_ERR_UNEXPECTED_RSV_1"
1052
- );
1053
- cb(error);
1054
- return;
1055
- }
1056
- this._fin = (buf[0] & 128) === 128;
1057
- this._opcode = buf[0] & 15;
1058
- this._payloadLength = buf[1] & 127;
1059
- if (this._opcode === 0) {
1060
- if (compressed) {
1061
- const error = this.createError(
1062
- RangeError,
1063
- "RSV1 must be clear",
1064
- true,
1065
- 1002,
1066
- "WS_ERR_UNEXPECTED_RSV_1"
1067
- );
1068
- cb(error);
1069
- return;
1070
- }
1071
- if (!this._fragmented) {
1072
- const error = this.createError(
1073
- RangeError,
1074
- "invalid opcode 0",
1075
- true,
1076
- 1002,
1077
- "WS_ERR_INVALID_OPCODE"
1078
- );
1079
- cb(error);
1080
- return;
1081
- }
1082
- this._opcode = this._fragmented;
1083
- } else if (this._opcode === 1 || this._opcode === 2) {
1084
- if (this._fragmented) {
1085
- const error = this.createError(
1086
- RangeError,
1087
- `invalid opcode ${this._opcode}`,
1088
- true,
1089
- 1002,
1090
- "WS_ERR_INVALID_OPCODE"
1091
- );
1092
- cb(error);
1093
- return;
1094
- }
1095
- this._compressed = compressed;
1096
- } else if (this._opcode > 7 && this._opcode < 11) {
1097
- if (!this._fin) {
1098
- const error = this.createError(
1099
- RangeError,
1100
- "FIN must be set",
1101
- true,
1102
- 1002,
1103
- "WS_ERR_EXPECTED_FIN"
1104
- );
1105
- cb(error);
1106
- return;
1107
- }
1108
- if (compressed) {
1109
- const error = this.createError(
1110
- RangeError,
1111
- "RSV1 must be clear",
1112
- true,
1113
- 1002,
1114
- "WS_ERR_UNEXPECTED_RSV_1"
1115
- );
1116
- cb(error);
1117
- return;
1118
- }
1119
- if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) {
1120
- const error = this.createError(
1121
- RangeError,
1122
- `invalid payload length ${this._payloadLength}`,
1123
- true,
1124
- 1002,
1125
- "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"
1126
- );
1127
- cb(error);
1128
- return;
1129
- }
1130
- } else {
1131
- const error = this.createError(
1132
- RangeError,
1133
- `invalid opcode ${this._opcode}`,
1134
- true,
1135
- 1002,
1136
- "WS_ERR_INVALID_OPCODE"
1137
- );
1138
- cb(error);
1139
- return;
1140
- }
1141
- if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
1142
- this._masked = (buf[1] & 128) === 128;
1143
- if (this._isServer) {
1144
- if (!this._masked) {
1145
- const error = this.createError(
1146
- RangeError,
1147
- "MASK must be set",
1148
- true,
1149
- 1002,
1150
- "WS_ERR_EXPECTED_MASK"
1151
- );
1152
- cb(error);
1153
- return;
1154
- }
1155
- } else if (this._masked) {
1156
- const error = this.createError(
1157
- RangeError,
1158
- "MASK must be clear",
1159
- true,
1160
- 1002,
1161
- "WS_ERR_UNEXPECTED_MASK"
1162
- );
1163
- cb(error);
1164
- return;
1165
- }
1166
- if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
1167
- else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
1168
- else this.haveLength(cb);
1169
- }
1170
- /**
1171
- * Gets extended payload length (7+16).
1172
- *
1173
- * @param {Function} cb Callback
1174
- * @private
1175
- */
1176
- getPayloadLength16(cb) {
1177
- if (this._bufferedBytes < 2) {
1178
- this._loop = false;
1179
- return;
1180
- }
1181
- this._payloadLength = this.consume(2).readUInt16BE(0);
1182
- this.haveLength(cb);
1183
- }
1184
- /**
1185
- * Gets extended payload length (7+64).
1186
- *
1187
- * @param {Function} cb Callback
1188
- * @private
1189
- */
1190
- getPayloadLength64(cb) {
1191
- if (this._bufferedBytes < 8) {
1192
- this._loop = false;
1193
- return;
1194
- }
1195
- const buf = this.consume(8);
1196
- const num = buf.readUInt32BE(0);
1197
- if (num > Math.pow(2, 53 - 32) - 1) {
1198
- const error = this.createError(
1199
- RangeError,
1200
- "Unsupported WebSocket frame: payload length > 2^53 - 1",
1201
- false,
1202
- 1009,
1203
- "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"
1204
- );
1205
- cb(error);
1206
- return;
1207
- }
1208
- this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
1209
- this.haveLength(cb);
1210
- }
1211
- /**
1212
- * Payload length has been read.
1213
- *
1214
- * @param {Function} cb Callback
1215
- * @private
1216
- */
1217
- haveLength(cb) {
1218
- if (this._payloadLength && this._opcode < 8) {
1219
- this._totalPayloadLength += this._payloadLength;
1220
- if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
1221
- const error = this.createError(
1222
- RangeError,
1223
- "Max payload size exceeded",
1224
- false,
1225
- 1009,
1226
- "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
1227
- );
1228
- cb(error);
1229
- return;
1230
- }
1231
- }
1232
- if (this._masked) this._state = GET_MASK;
1233
- else this._state = GET_DATA;
1234
- }
1235
- /**
1236
- * Reads mask bytes.
1237
- *
1238
- * @private
1239
- */
1240
- getMask() {
1241
- if (this._bufferedBytes < 4) {
1242
- this._loop = false;
1243
- return;
1244
- }
1245
- this._mask = this.consume(4);
1246
- this._state = GET_DATA;
1247
- }
1248
- /**
1249
- * Reads data bytes.
1250
- *
1251
- * @param {Function} cb Callback
1252
- * @private
1253
- */
1254
- getData(cb) {
1255
- let data = EMPTY_BUFFER;
1256
- if (this._payloadLength) {
1257
- if (this._bufferedBytes < this._payloadLength) {
1258
- this._loop = false;
1259
- return;
1260
- }
1261
- data = this.consume(this._payloadLength);
1262
- if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) {
1263
- unmask(data, this._mask);
1264
- }
1265
- }
1266
- if (this._opcode > 7) {
1267
- this.controlMessage(data, cb);
1268
- return;
1269
- }
1270
- if (this._compressed) {
1271
- this._state = INFLATING;
1272
- this.decompress(data, cb);
1273
- return;
1274
- }
1275
- if (data.length) {
1276
- this._messageLength = this._totalPayloadLength;
1277
- this._fragments.push(data);
1278
- }
1279
- this.dataMessage(cb);
1280
- }
1281
- /**
1282
- * Decompresses data.
1283
- *
1284
- * @param {Buffer} data Compressed data
1285
- * @param {Function} cb Callback
1286
- * @private
1287
- */
1288
- decompress(data, cb) {
1289
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
1290
- perMessageDeflate.decompress(data, this._fin, (err, buf) => {
1291
- if (err) return cb(err);
1292
- if (buf.length) {
1293
- this._messageLength += buf.length;
1294
- if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
1295
- const error = this.createError(
1296
- RangeError,
1297
- "Max payload size exceeded",
1298
- false,
1299
- 1009,
1300
- "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
1301
- );
1302
- cb(error);
1303
- return;
1304
- }
1305
- this._fragments.push(buf);
1306
- }
1307
- this.dataMessage(cb);
1308
- if (this._state === GET_INFO) this.startLoop(cb);
1309
- });
1310
- }
1311
- /**
1312
- * Handles a data message.
1313
- *
1314
- * @param {Function} cb Callback
1315
- * @private
1316
- */
1317
- dataMessage(cb) {
1318
- if (!this._fin) {
1319
- this._state = GET_INFO;
1320
- return;
1321
- }
1322
- const messageLength = this._messageLength;
1323
- const fragments = this._fragments;
1324
- this._totalPayloadLength = 0;
1325
- this._messageLength = 0;
1326
- this._fragmented = 0;
1327
- this._fragments = [];
1328
- if (this._opcode === 2) {
1329
- let data;
1330
- if (this._binaryType === "nodebuffer") {
1331
- data = concat(fragments, messageLength);
1332
- } else if (this._binaryType === "arraybuffer") {
1333
- data = toArrayBuffer(concat(fragments, messageLength));
1334
- } else if (this._binaryType === "blob") {
1335
- data = new Blob(fragments);
1336
- } else {
1337
- data = fragments;
1338
- }
1339
- if (this._allowSynchronousEvents) {
1340
- this.emit("message", data, true);
1341
- this._state = GET_INFO;
1342
- } else {
1343
- this._state = DEFER_EVENT;
1344
- setImmediate(() => {
1345
- this.emit("message", data, true);
1346
- this._state = GET_INFO;
1347
- this.startLoop(cb);
1348
- });
1349
- }
1350
- } else {
1351
- const buf = concat(fragments, messageLength);
1352
- if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1353
- const error = this.createError(
1354
- Error,
1355
- "invalid UTF-8 sequence",
1356
- true,
1357
- 1007,
1358
- "WS_ERR_INVALID_UTF8"
1359
- );
1360
- cb(error);
1361
- return;
1362
- }
1363
- if (this._state === INFLATING || this._allowSynchronousEvents) {
1364
- this.emit("message", buf, false);
1365
- this._state = GET_INFO;
1366
- } else {
1367
- this._state = DEFER_EVENT;
1368
- setImmediate(() => {
1369
- this.emit("message", buf, false);
1370
- this._state = GET_INFO;
1371
- this.startLoop(cb);
1372
- });
1373
- }
1374
- }
1375
- }
1376
- /**
1377
- * Handles a control message.
1378
- *
1379
- * @param {Buffer} data Data to handle
1380
- * @return {(Error|RangeError|undefined)} A possible error
1381
- * @private
1382
- */
1383
- controlMessage(data, cb) {
1384
- if (this._opcode === 8) {
1385
- if (data.length === 0) {
1386
- this._loop = false;
1387
- this.emit("conclude", 1005, EMPTY_BUFFER);
1388
- this.end();
1389
- } else {
1390
- const code = data.readUInt16BE(0);
1391
- if (!isValidStatusCode(code)) {
1392
- const error = this.createError(
1393
- RangeError,
1394
- `invalid status code ${code}`,
1395
- true,
1396
- 1002,
1397
- "WS_ERR_INVALID_CLOSE_CODE"
1398
- );
1399
- cb(error);
1400
- return;
1401
- }
1402
- const buf = new FastBuffer(
1403
- data.buffer,
1404
- data.byteOffset + 2,
1405
- data.length - 2
1406
- );
1407
- if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1408
- const error = this.createError(
1409
- Error,
1410
- "invalid UTF-8 sequence",
1411
- true,
1412
- 1007,
1413
- "WS_ERR_INVALID_UTF8"
1414
- );
1415
- cb(error);
1416
- return;
1417
- }
1418
- this._loop = false;
1419
- this.emit("conclude", code, buf);
1420
- this.end();
1421
- }
1422
- this._state = GET_INFO;
1423
- return;
1424
- }
1425
- if (this._allowSynchronousEvents) {
1426
- this.emit(this._opcode === 9 ? "ping" : "pong", data);
1427
- this._state = GET_INFO;
1428
- } else {
1429
- this._state = DEFER_EVENT;
1430
- setImmediate(() => {
1431
- this.emit(this._opcode === 9 ? "ping" : "pong", data);
1432
- this._state = GET_INFO;
1433
- this.startLoop(cb);
1434
- });
1435
- }
1436
- }
1437
- /**
1438
- * Builds an error object.
1439
- *
1440
- * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
1441
- * @param {String} message The error message
1442
- * @param {Boolean} prefix Specifies whether or not to add a default prefix to
1443
- * `message`
1444
- * @param {Number} statusCode The status code
1445
- * @param {String} errorCode The exposed error code
1446
- * @return {(Error|RangeError)} The error
1447
- * @private
1448
- */
1449
- createError(ErrorCtor, message, prefix, statusCode, errorCode) {
1450
- this._loop = false;
1451
- this._errored = true;
1452
- const err = new ErrorCtor(
1453
- prefix ? `Invalid WebSocket frame: ${message}` : message
1454
- );
1455
- Error.captureStackTrace(err, this.createError);
1456
- err.code = errorCode;
1457
- err[kStatusCode] = statusCode;
1458
- return err;
1459
- }
1460
- };
1461
- module.exports = Receiver2;
1462
- }
1463
- });
1464
-
1465
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/sender.js
1466
- var require_sender = __commonJS({
1467
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/sender.js"(exports, module) {
1468
- "use strict";
1469
- var { Duplex } = __require("stream");
1470
- var { randomFillSync } = __require("crypto");
1471
- var PerMessageDeflate = require_permessage_deflate();
1472
- var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
1473
- var { isBlob, isValidStatusCode } = require_validation();
1474
- var { mask: applyMask, toBuffer } = require_buffer_util();
1475
- var kByteLength = /* @__PURE__ */ Symbol("kByteLength");
1476
- var maskBuffer = Buffer.alloc(4);
1477
- var RANDOM_POOL_SIZE = 8 * 1024;
1478
- var randomPool;
1479
- var randomPoolPointer = RANDOM_POOL_SIZE;
1480
- var DEFAULT = 0;
1481
- var DEFLATING = 1;
1482
- var GET_BLOB_DATA = 2;
1483
- var Sender2 = class _Sender {
1484
- /**
1485
- * Creates a Sender instance.
1486
- *
1487
- * @param {Duplex} socket The connection socket
1488
- * @param {Object} [extensions] An object containing the negotiated extensions
1489
- * @param {Function} [generateMask] The function used to generate the masking
1490
- * key
1491
- */
1492
- constructor(socket, extensions, generateMask) {
1493
- this._extensions = extensions || {};
1494
- if (generateMask) {
1495
- this._generateMask = generateMask;
1496
- this._maskBuffer = Buffer.alloc(4);
1497
- }
1498
- this._socket = socket;
1499
- this._firstFragment = true;
1500
- this._compress = false;
1501
- this._bufferedBytes = 0;
1502
- this._queue = [];
1503
- this._state = DEFAULT;
1504
- this.onerror = NOOP;
1505
- this[kWebSocket] = void 0;
1506
- }
1507
- /**
1508
- * Frames a piece of data according to the HyBi WebSocket protocol.
1509
- *
1510
- * @param {(Buffer|String)} data The data to frame
1511
- * @param {Object} options Options object
1512
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1513
- * FIN bit
1514
- * @param {Function} [options.generateMask] The function used to generate the
1515
- * masking key
1516
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1517
- * `data`
1518
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1519
- * key
1520
- * @param {Number} options.opcode The opcode
1521
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1522
- * modified
1523
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1524
- * RSV1 bit
1525
- * @return {(Buffer|String)[]} The framed data
1526
- * @public
1527
- */
1528
- static frame(data, options) {
1529
- let mask;
1530
- let merge = false;
1531
- let offset = 2;
1532
- let skipMasking = false;
1533
- if (options.mask) {
1534
- mask = options.maskBuffer || maskBuffer;
1535
- if (options.generateMask) {
1536
- options.generateMask(mask);
1537
- } else {
1538
- if (randomPoolPointer === RANDOM_POOL_SIZE) {
1539
- if (randomPool === void 0) {
1540
- randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
1541
- }
1542
- randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
1543
- randomPoolPointer = 0;
1544
- }
1545
- mask[0] = randomPool[randomPoolPointer++];
1546
- mask[1] = randomPool[randomPoolPointer++];
1547
- mask[2] = randomPool[randomPoolPointer++];
1548
- mask[3] = randomPool[randomPoolPointer++];
1549
- }
1550
- skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
1551
- offset = 6;
1552
- }
1553
- let dataLength;
1554
- if (typeof data === "string") {
1555
- if ((!options.mask || skipMasking) && options[kByteLength] !== void 0) {
1556
- dataLength = options[kByteLength];
1557
- } else {
1558
- data = Buffer.from(data);
1559
- dataLength = data.length;
1560
- }
1561
- } else {
1562
- dataLength = data.length;
1563
- merge = options.mask && options.readOnly && !skipMasking;
1564
- }
1565
- let payloadLength = dataLength;
1566
- if (dataLength >= 65536) {
1567
- offset += 8;
1568
- payloadLength = 127;
1569
- } else if (dataLength > 125) {
1570
- offset += 2;
1571
- payloadLength = 126;
1572
- }
1573
- const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
1574
- target[0] = options.fin ? options.opcode | 128 : options.opcode;
1575
- if (options.rsv1) target[0] |= 64;
1576
- target[1] = payloadLength;
1577
- if (payloadLength === 126) {
1578
- target.writeUInt16BE(dataLength, 2);
1579
- } else if (payloadLength === 127) {
1580
- target[2] = target[3] = 0;
1581
- target.writeUIntBE(dataLength, 4, 6);
1582
- }
1583
- if (!options.mask) return [target, data];
1584
- target[1] |= 128;
1585
- target[offset - 4] = mask[0];
1586
- target[offset - 3] = mask[1];
1587
- target[offset - 2] = mask[2];
1588
- target[offset - 1] = mask[3];
1589
- if (skipMasking) return [target, data];
1590
- if (merge) {
1591
- applyMask(data, mask, target, offset, dataLength);
1592
- return [target];
1593
- }
1594
- applyMask(data, mask, data, 0, dataLength);
1595
- return [target, data];
1596
- }
1597
- /**
1598
- * Sends a close message to the other peer.
1599
- *
1600
- * @param {Number} [code] The status code component of the body
1601
- * @param {(String|Buffer)} [data] The message component of the body
1602
- * @param {Boolean} [mask=false] Specifies whether or not to mask the message
1603
- * @param {Function} [cb] Callback
1604
- * @public
1605
- */
1606
- close(code, data, mask, cb) {
1607
- let buf;
1608
- if (code === void 0) {
1609
- buf = EMPTY_BUFFER;
1610
- } else if (typeof code !== "number" || !isValidStatusCode(code)) {
1611
- throw new TypeError("First argument must be a valid error code number");
1612
- } else if (data === void 0 || !data.length) {
1613
- buf = Buffer.allocUnsafe(2);
1614
- buf.writeUInt16BE(code, 0);
1615
- } else {
1616
- const length = Buffer.byteLength(data);
1617
- if (length > 123) {
1618
- throw new RangeError("The message must not be greater than 123 bytes");
1619
- }
1620
- buf = Buffer.allocUnsafe(2 + length);
1621
- buf.writeUInt16BE(code, 0);
1622
- if (typeof data === "string") {
1623
- buf.write(data, 2);
1624
- } else {
1625
- buf.set(data, 2);
1626
- }
1627
- }
1628
- const options = {
1629
- [kByteLength]: buf.length,
1630
- fin: true,
1631
- generateMask: this._generateMask,
1632
- mask,
1633
- maskBuffer: this._maskBuffer,
1634
- opcode: 8,
1635
- readOnly: false,
1636
- rsv1: false
1637
- };
1638
- if (this._state !== DEFAULT) {
1639
- this.enqueue([this.dispatch, buf, false, options, cb]);
1640
- } else {
1641
- this.sendFrame(_Sender.frame(buf, options), cb);
1642
- }
1643
- }
1644
- /**
1645
- * Sends a ping message to the other peer.
1646
- *
1647
- * @param {*} data The message to send
1648
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1649
- * @param {Function} [cb] Callback
1650
- * @public
1651
- */
1652
- ping(data, mask, cb) {
1653
- let byteLength;
1654
- let readOnly;
1655
- if (typeof data === "string") {
1656
- byteLength = Buffer.byteLength(data);
1657
- readOnly = false;
1658
- } else if (isBlob(data)) {
1659
- byteLength = data.size;
1660
- readOnly = false;
1661
- } else {
1662
- data = toBuffer(data);
1663
- byteLength = data.length;
1664
- readOnly = toBuffer.readOnly;
1665
- }
1666
- if (byteLength > 125) {
1667
- throw new RangeError("The data size must not be greater than 125 bytes");
1668
- }
1669
- const options = {
1670
- [kByteLength]: byteLength,
1671
- fin: true,
1672
- generateMask: this._generateMask,
1673
- mask,
1674
- maskBuffer: this._maskBuffer,
1675
- opcode: 9,
1676
- readOnly,
1677
- rsv1: false
1678
- };
1679
- if (isBlob(data)) {
1680
- if (this._state !== DEFAULT) {
1681
- this.enqueue([this.getBlobData, data, false, options, cb]);
1682
- } else {
1683
- this.getBlobData(data, false, options, cb);
1684
- }
1685
- } else if (this._state !== DEFAULT) {
1686
- this.enqueue([this.dispatch, data, false, options, cb]);
1687
- } else {
1688
- this.sendFrame(_Sender.frame(data, options), cb);
1689
- }
1690
- }
1691
- /**
1692
- * Sends a pong message to the other peer.
1693
- *
1694
- * @param {*} data The message to send
1695
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1696
- * @param {Function} [cb] Callback
1697
- * @public
1698
- */
1699
- pong(data, mask, cb) {
1700
- let byteLength;
1701
- let readOnly;
1702
- if (typeof data === "string") {
1703
- byteLength = Buffer.byteLength(data);
1704
- readOnly = false;
1705
- } else if (isBlob(data)) {
1706
- byteLength = data.size;
1707
- readOnly = false;
1708
- } else {
1709
- data = toBuffer(data);
1710
- byteLength = data.length;
1711
- readOnly = toBuffer.readOnly;
1712
- }
1713
- if (byteLength > 125) {
1714
- throw new RangeError("The data size must not be greater than 125 bytes");
1715
- }
1716
- const options = {
1717
- [kByteLength]: byteLength,
1718
- fin: true,
1719
- generateMask: this._generateMask,
1720
- mask,
1721
- maskBuffer: this._maskBuffer,
1722
- opcode: 10,
1723
- readOnly,
1724
- rsv1: false
1725
- };
1726
- if (isBlob(data)) {
1727
- if (this._state !== DEFAULT) {
1728
- this.enqueue([this.getBlobData, data, false, options, cb]);
1729
- } else {
1730
- this.getBlobData(data, false, options, cb);
1731
- }
1732
- } else if (this._state !== DEFAULT) {
1733
- this.enqueue([this.dispatch, data, false, options, cb]);
1734
- } else {
1735
- this.sendFrame(_Sender.frame(data, options), cb);
1736
- }
1737
- }
1738
- /**
1739
- * Sends a data message to the other peer.
1740
- *
1741
- * @param {*} data The message to send
1742
- * @param {Object} options Options object
1743
- * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
1744
- * or text
1745
- * @param {Boolean} [options.compress=false] Specifies whether or not to
1746
- * compress `data`
1747
- * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
1748
- * last one
1749
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1750
- * `data`
1751
- * @param {Function} [cb] Callback
1752
- * @public
1753
- */
1754
- send(data, options, cb) {
1755
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
1756
- let opcode = options.binary ? 2 : 1;
1757
- let rsv1 = options.compress;
1758
- let byteLength;
1759
- let readOnly;
1760
- if (typeof data === "string") {
1761
- byteLength = Buffer.byteLength(data);
1762
- readOnly = false;
1763
- } else if (isBlob(data)) {
1764
- byteLength = data.size;
1765
- readOnly = false;
1766
- } else {
1767
- data = toBuffer(data);
1768
- byteLength = data.length;
1769
- readOnly = toBuffer.readOnly;
1770
- }
1771
- if (this._firstFragment) {
1772
- this._firstFragment = false;
1773
- if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) {
1774
- rsv1 = byteLength >= perMessageDeflate._threshold;
1775
- }
1776
- this._compress = rsv1;
1777
- } else {
1778
- rsv1 = false;
1779
- opcode = 0;
1780
- }
1781
- if (options.fin) this._firstFragment = true;
1782
- const opts = {
1783
- [kByteLength]: byteLength,
1784
- fin: options.fin,
1785
- generateMask: this._generateMask,
1786
- mask: options.mask,
1787
- maskBuffer: this._maskBuffer,
1788
- opcode,
1789
- readOnly,
1790
- rsv1
1791
- };
1792
- if (isBlob(data)) {
1793
- if (this._state !== DEFAULT) {
1794
- this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
1795
- } else {
1796
- this.getBlobData(data, this._compress, opts, cb);
1797
- }
1798
- } else if (this._state !== DEFAULT) {
1799
- this.enqueue([this.dispatch, data, this._compress, opts, cb]);
1800
- } else {
1801
- this.dispatch(data, this._compress, opts, cb);
1802
- }
1803
- }
1804
- /**
1805
- * Gets the contents of a blob as binary data.
1806
- *
1807
- * @param {Blob} blob The blob
1808
- * @param {Boolean} [compress=false] Specifies whether or not to compress
1809
- * the data
1810
- * @param {Object} options Options object
1811
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1812
- * FIN bit
1813
- * @param {Function} [options.generateMask] The function used to generate the
1814
- * masking key
1815
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1816
- * `data`
1817
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1818
- * key
1819
- * @param {Number} options.opcode The opcode
1820
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1821
- * modified
1822
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1823
- * RSV1 bit
1824
- * @param {Function} [cb] Callback
1825
- * @private
1826
- */
1827
- getBlobData(blob, compress, options, cb) {
1828
- this._bufferedBytes += options[kByteLength];
1829
- this._state = GET_BLOB_DATA;
1830
- blob.arrayBuffer().then((arrayBuffer) => {
1831
- if (this._socket.destroyed) {
1832
- const err = new Error(
1833
- "The socket was closed while the blob was being read"
1834
- );
1835
- process.nextTick(callCallbacks, this, err, cb);
1836
- return;
1837
- }
1838
- this._bufferedBytes -= options[kByteLength];
1839
- const data = toBuffer(arrayBuffer);
1840
- if (!compress) {
1841
- this._state = DEFAULT;
1842
- this.sendFrame(_Sender.frame(data, options), cb);
1843
- this.dequeue();
1844
- } else {
1845
- this.dispatch(data, compress, options, cb);
1846
- }
1847
- }).catch((err) => {
1848
- process.nextTick(onError, this, err, cb);
1849
- });
1850
- }
1851
- /**
1852
- * Dispatches a message.
1853
- *
1854
- * @param {(Buffer|String)} data The message to send
1855
- * @param {Boolean} [compress=false] Specifies whether or not to compress
1856
- * `data`
1857
- * @param {Object} options Options object
1858
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1859
- * FIN bit
1860
- * @param {Function} [options.generateMask] The function used to generate the
1861
- * masking key
1862
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1863
- * `data`
1864
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1865
- * key
1866
- * @param {Number} options.opcode The opcode
1867
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1868
- * modified
1869
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1870
- * RSV1 bit
1871
- * @param {Function} [cb] Callback
1872
- * @private
1873
- */
1874
- dispatch(data, compress, options, cb) {
1875
- if (!compress) {
1876
- this.sendFrame(_Sender.frame(data, options), cb);
1877
- return;
1878
- }
1879
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
1880
- this._bufferedBytes += options[kByteLength];
1881
- this._state = DEFLATING;
1882
- perMessageDeflate.compress(data, options.fin, (_, buf) => {
1883
- if (this._socket.destroyed) {
1884
- const err = new Error(
1885
- "The socket was closed while data was being compressed"
1886
- );
1887
- callCallbacks(this, err, cb);
1888
- return;
1889
- }
1890
- this._bufferedBytes -= options[kByteLength];
1891
- this._state = DEFAULT;
1892
- options.readOnly = false;
1893
- this.sendFrame(_Sender.frame(buf, options), cb);
1894
- this.dequeue();
1895
- });
1896
- }
1897
- /**
1898
- * Executes queued send operations.
1899
- *
1900
- * @private
1901
- */
1902
- dequeue() {
1903
- while (this._state === DEFAULT && this._queue.length) {
1904
- const params = this._queue.shift();
1905
- this._bufferedBytes -= params[3][kByteLength];
1906
- Reflect.apply(params[0], this, params.slice(1));
1907
- }
1908
- }
1909
- /**
1910
- * Enqueues a send operation.
1911
- *
1912
- * @param {Array} params Send operation parameters.
1913
- * @private
1914
- */
1915
- enqueue(params) {
1916
- this._bufferedBytes += params[3][kByteLength];
1917
- this._queue.push(params);
1918
- }
1919
- /**
1920
- * Sends a frame.
1921
- *
1922
- * @param {Buffer[]} list The frame to send
1923
- * @param {Function} [cb] Callback
1924
- * @private
1925
- */
1926
- sendFrame(list, cb) {
1927
- if (list.length === 2) {
1928
- this._socket.cork();
1929
- this._socket.write(list[0]);
1930
- this._socket.write(list[1], cb);
1931
- this._socket.uncork();
1932
- } else {
1933
- this._socket.write(list[0], cb);
1934
- }
1935
- }
1936
- };
1937
- module.exports = Sender2;
1938
- function callCallbacks(sender, err, cb) {
1939
- if (typeof cb === "function") cb(err);
1940
- for (let i = 0; i < sender._queue.length; i++) {
1941
- const params = sender._queue[i];
1942
- const callback = params[params.length - 1];
1943
- if (typeof callback === "function") callback(err);
1944
- }
1945
- }
1946
- function onError(sender, err, cb) {
1947
- callCallbacks(sender, err, cb);
1948
- sender.onerror(err);
1949
- }
1950
- }
1951
- });
1952
-
1953
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/event-target.js
1954
- var require_event_target = __commonJS({
1955
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/event-target.js"(exports, module) {
1956
- "use strict";
1957
- var { kForOnEventAttribute, kListener } = require_constants();
1958
- var kCode = /* @__PURE__ */ Symbol("kCode");
1959
- var kData = /* @__PURE__ */ Symbol("kData");
1960
- var kError = /* @__PURE__ */ Symbol("kError");
1961
- var kMessage = /* @__PURE__ */ Symbol("kMessage");
1962
- var kReason = /* @__PURE__ */ Symbol("kReason");
1963
- var kTarget = /* @__PURE__ */ Symbol("kTarget");
1964
- var kType = /* @__PURE__ */ Symbol("kType");
1965
- var kWasClean = /* @__PURE__ */ Symbol("kWasClean");
1966
- var Event = class {
1967
- /**
1968
- * Create a new `Event`.
1969
- *
1970
- * @param {String} type The name of the event
1971
- * @throws {TypeError} If the `type` argument is not specified
1972
- */
1973
- constructor(type) {
1974
- this[kTarget] = null;
1975
- this[kType] = type;
1976
- }
1977
- /**
1978
- * @type {*}
1979
- */
1980
- get target() {
1981
- return this[kTarget];
1982
- }
1983
- /**
1984
- * @type {String}
1985
- */
1986
- get type() {
1987
- return this[kType];
1988
- }
1989
- };
1990
- Object.defineProperty(Event.prototype, "target", { enumerable: true });
1991
- Object.defineProperty(Event.prototype, "type", { enumerable: true });
1992
- var CloseEvent = class extends Event {
1993
- /**
1994
- * Create a new `CloseEvent`.
1995
- *
1996
- * @param {String} type The name of the event
1997
- * @param {Object} [options] A dictionary object that allows for setting
1998
- * attributes via object members of the same name
1999
- * @param {Number} [options.code=0] The status code explaining why the
2000
- * connection was closed
2001
- * @param {String} [options.reason=''] A human-readable string explaining why
2002
- * the connection was closed
2003
- * @param {Boolean} [options.wasClean=false] Indicates whether or not the
2004
- * connection was cleanly closed
2005
- */
2006
- constructor(type, options = {}) {
2007
- super(type);
2008
- this[kCode] = options.code === void 0 ? 0 : options.code;
2009
- this[kReason] = options.reason === void 0 ? "" : options.reason;
2010
- this[kWasClean] = options.wasClean === void 0 ? false : options.wasClean;
2011
- }
2012
- /**
2013
- * @type {Number}
2014
- */
2015
- get code() {
2016
- return this[kCode];
2017
- }
2018
- /**
2019
- * @type {String}
2020
- */
2021
- get reason() {
2022
- return this[kReason];
2023
- }
2024
- /**
2025
- * @type {Boolean}
2026
- */
2027
- get wasClean() {
2028
- return this[kWasClean];
2029
- }
2030
- };
2031
- Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true });
2032
- Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true });
2033
- Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true });
2034
- var ErrorEvent = class extends Event {
2035
- /**
2036
- * Create a new `ErrorEvent`.
2037
- *
2038
- * @param {String} type The name of the event
2039
- * @param {Object} [options] A dictionary object that allows for setting
2040
- * attributes via object members of the same name
2041
- * @param {*} [options.error=null] The error that generated this event
2042
- * @param {String} [options.message=''] The error message
2043
- */
2044
- constructor(type, options = {}) {
2045
- super(type);
2046
- this[kError] = options.error === void 0 ? null : options.error;
2047
- this[kMessage] = options.message === void 0 ? "" : options.message;
2048
- }
2049
- /**
2050
- * @type {*}
2051
- */
2052
- get error() {
2053
- return this[kError];
2054
- }
2055
- /**
2056
- * @type {String}
2057
- */
2058
- get message() {
2059
- return this[kMessage];
2060
- }
2061
- };
2062
- Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true });
2063
- Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true });
2064
- var MessageEvent = class extends Event {
2065
- /**
2066
- * Create a new `MessageEvent`.
2067
- *
2068
- * @param {String} type The name of the event
2069
- * @param {Object} [options] A dictionary object that allows for setting
2070
- * attributes via object members of the same name
2071
- * @param {*} [options.data=null] The message content
2072
- */
2073
- constructor(type, options = {}) {
2074
- super(type);
2075
- this[kData] = options.data === void 0 ? null : options.data;
2076
- }
2077
- /**
2078
- * @type {*}
2079
- */
2080
- get data() {
2081
- return this[kData];
2082
- }
2083
- };
2084
- Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
2085
- var EventTarget = {
2086
- /**
2087
- * Register an event listener.
2088
- *
2089
- * @param {String} type A string representing the event type to listen for
2090
- * @param {(Function|Object)} handler The listener to add
2091
- * @param {Object} [options] An options object specifies characteristics about
2092
- * the event listener
2093
- * @param {Boolean} [options.once=false] A `Boolean` indicating that the
2094
- * listener should be invoked at most once after being added. If `true`,
2095
- * the listener would be automatically removed when invoked.
2096
- * @public
2097
- */
2098
- addEventListener(type, handler, options = {}) {
2099
- for (const listener of this.listeners(type)) {
2100
- if (!options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute]) {
2101
- return;
2102
- }
2103
- }
2104
- let wrapper;
2105
- if (type === "message") {
2106
- wrapper = function onMessage(data, isBinary) {
2107
- const event = new MessageEvent("message", {
2108
- data: isBinary ? data : data.toString()
2109
- });
2110
- event[kTarget] = this;
2111
- callListener(handler, this, event);
2112
- };
2113
- } else if (type === "close") {
2114
- wrapper = function onClose(code, message) {
2115
- const event = new CloseEvent("close", {
2116
- code,
2117
- reason: message.toString(),
2118
- wasClean: this._closeFrameReceived && this._closeFrameSent
2119
- });
2120
- event[kTarget] = this;
2121
- callListener(handler, this, event);
2122
- };
2123
- } else if (type === "error") {
2124
- wrapper = function onError(error) {
2125
- const event = new ErrorEvent("error", {
2126
- error,
2127
- message: error.message
2128
- });
2129
- event[kTarget] = this;
2130
- callListener(handler, this, event);
2131
- };
2132
- } else if (type === "open") {
2133
- wrapper = function onOpen() {
2134
- const event = new Event("open");
2135
- event[kTarget] = this;
2136
- callListener(handler, this, event);
2137
- };
2138
- } else {
2139
- return;
2140
- }
2141
- wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
2142
- wrapper[kListener] = handler;
2143
- if (options.once) {
2144
- this.once(type, wrapper);
2145
- } else {
2146
- this.on(type, wrapper);
2147
- }
2148
- },
2149
- /**
2150
- * Remove an event listener.
2151
- *
2152
- * @param {String} type A string representing the event type to remove
2153
- * @param {(Function|Object)} handler The listener to remove
2154
- * @public
2155
- */
2156
- removeEventListener(type, handler) {
2157
- for (const listener of this.listeners(type)) {
2158
- if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
2159
- this.removeListener(type, listener);
2160
- break;
2161
- }
2162
- }
2163
- }
2164
- };
2165
- module.exports = {
2166
- CloseEvent,
2167
- ErrorEvent,
2168
- Event,
2169
- EventTarget,
2170
- MessageEvent
2171
- };
2172
- function callListener(listener, thisArg, event) {
2173
- if (typeof listener === "object" && listener.handleEvent) {
2174
- listener.handleEvent.call(listener, event);
2175
- } else {
2176
- listener.call(thisArg, event);
2177
- }
2178
- }
47
+ // ../gateway-server/src/auth-middleware.ts
48
+ var ADMIN_ACTIONS = /* @__PURE__ */ new Set([
49
+ "flush",
50
+ "schema",
51
+ "sync-rules",
52
+ "register-connector",
53
+ "unregister-connector",
54
+ "list-connectors",
55
+ "metrics"
56
+ ]);
57
+ function extractBearerToken(req) {
58
+ const header = req.headers.authorization;
59
+ if (!header) return null;
60
+ const match = header.match(/^Bearer\s+(\S+)$/);
61
+ return match?.[1] ?? null;
62
+ }
63
+ async function authenticateRequest(req, routeGatewayId, routeAction, jwtSecret) {
64
+ if (!jwtSecret) {
65
+ return { authenticated: true, claims: void 0 };
2179
66
  }
2180
- });
2181
-
2182
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/extension.js
2183
- var require_extension = __commonJS({
2184
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/extension.js"(exports, module) {
2185
- "use strict";
2186
- var { tokenChars } = require_validation();
2187
- function push(dest, name, elem) {
2188
- if (dest[name] === void 0) dest[name] = [elem];
2189
- else dest[name].push(elem);
2190
- }
2191
- function parse(header) {
2192
- const offers = /* @__PURE__ */ Object.create(null);
2193
- let params = /* @__PURE__ */ Object.create(null);
2194
- let mustUnescape = false;
2195
- let isEscaping = false;
2196
- let inQuotes = false;
2197
- let extensionName;
2198
- let paramName;
2199
- let start = -1;
2200
- let code = -1;
2201
- let end = -1;
2202
- let i = 0;
2203
- for (; i < header.length; i++) {
2204
- code = header.charCodeAt(i);
2205
- if (extensionName === void 0) {
2206
- if (end === -1 && tokenChars[code] === 1) {
2207
- if (start === -1) start = i;
2208
- } else if (i !== 0 && (code === 32 || code === 9)) {
2209
- if (end === -1 && start !== -1) end = i;
2210
- } else if (code === 59 || code === 44) {
2211
- if (start === -1) {
2212
- throw new SyntaxError(`Unexpected character at index ${i}`);
2213
- }
2214
- if (end === -1) end = i;
2215
- const name = header.slice(start, end);
2216
- if (code === 44) {
2217
- push(offers, name, params);
2218
- params = /* @__PURE__ */ Object.create(null);
2219
- } else {
2220
- extensionName = name;
2221
- }
2222
- start = end = -1;
2223
- } else {
2224
- throw new SyntaxError(`Unexpected character at index ${i}`);
2225
- }
2226
- } else if (paramName === void 0) {
2227
- if (end === -1 && tokenChars[code] === 1) {
2228
- if (start === -1) start = i;
2229
- } else if (code === 32 || code === 9) {
2230
- if (end === -1 && start !== -1) end = i;
2231
- } else if (code === 59 || code === 44) {
2232
- if (start === -1) {
2233
- throw new SyntaxError(`Unexpected character at index ${i}`);
2234
- }
2235
- if (end === -1) end = i;
2236
- push(params, header.slice(start, end), true);
2237
- if (code === 44) {
2238
- push(offers, extensionName, params);
2239
- params = /* @__PURE__ */ Object.create(null);
2240
- extensionName = void 0;
2241
- }
2242
- start = end = -1;
2243
- } else if (code === 61 && start !== -1 && end === -1) {
2244
- paramName = header.slice(start, i);
2245
- start = end = -1;
2246
- } else {
2247
- throw new SyntaxError(`Unexpected character at index ${i}`);
2248
- }
2249
- } else {
2250
- if (isEscaping) {
2251
- if (tokenChars[code] !== 1) {
2252
- throw new SyntaxError(`Unexpected character at index ${i}`);
2253
- }
2254
- if (start === -1) start = i;
2255
- else if (!mustUnescape) mustUnescape = true;
2256
- isEscaping = false;
2257
- } else if (inQuotes) {
2258
- if (tokenChars[code] === 1) {
2259
- if (start === -1) start = i;
2260
- } else if (code === 34 && start !== -1) {
2261
- inQuotes = false;
2262
- end = i;
2263
- } else if (code === 92) {
2264
- isEscaping = true;
2265
- } else {
2266
- throw new SyntaxError(`Unexpected character at index ${i}`);
2267
- }
2268
- } else if (code === 34 && header.charCodeAt(i - 1) === 61) {
2269
- inQuotes = true;
2270
- } else if (end === -1 && tokenChars[code] === 1) {
2271
- if (start === -1) start = i;
2272
- } else if (start !== -1 && (code === 32 || code === 9)) {
2273
- if (end === -1) end = i;
2274
- } else if (code === 59 || code === 44) {
2275
- if (start === -1) {
2276
- throw new SyntaxError(`Unexpected character at index ${i}`);
2277
- }
2278
- if (end === -1) end = i;
2279
- let value = header.slice(start, end);
2280
- if (mustUnescape) {
2281
- value = value.replace(/\\/g, "");
2282
- mustUnescape = false;
2283
- }
2284
- push(params, paramName, value);
2285
- if (code === 44) {
2286
- push(offers, extensionName, params);
2287
- params = /* @__PURE__ */ Object.create(null);
2288
- extensionName = void 0;
2289
- }
2290
- paramName = void 0;
2291
- start = end = -1;
2292
- } else {
2293
- throw new SyntaxError(`Unexpected character at index ${i}`);
2294
- }
2295
- }
2296
- }
2297
- if (start === -1 || inQuotes || code === 32 || code === 9) {
2298
- throw new SyntaxError("Unexpected end of input");
2299
- }
2300
- if (end === -1) end = i;
2301
- const token = header.slice(start, end);
2302
- if (extensionName === void 0) {
2303
- push(offers, token, params);
2304
- } else {
2305
- if (paramName === void 0) {
2306
- push(params, token, true);
2307
- } else if (mustUnescape) {
2308
- push(params, paramName, token.replace(/\\/g, ""));
2309
- } else {
2310
- push(params, paramName, token);
2311
- }
2312
- push(offers, extensionName, params);
2313
- }
2314
- return offers;
2315
- }
2316
- function format(extensions) {
2317
- return Object.keys(extensions).map((extension) => {
2318
- let configurations = extensions[extension];
2319
- if (!Array.isArray(configurations)) configurations = [configurations];
2320
- return configurations.map((params) => {
2321
- return [extension].concat(
2322
- Object.keys(params).map((k) => {
2323
- let values = params[k];
2324
- if (!Array.isArray(values)) values = [values];
2325
- return values.map((v) => v === true ? k : `${k}=${v}`).join("; ");
2326
- })
2327
- ).join("; ");
2328
- }).join(", ");
2329
- }).join(", ");
2330
- }
2331
- module.exports = { format, parse };
67
+ const token = extractBearerToken(req);
68
+ if (!token) {
69
+ return { authenticated: false, status: 401, message: "Missing Bearer token" };
2332
70
  }
2333
- });
2334
-
2335
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/websocket.js
2336
- var require_websocket = __commonJS({
2337
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/websocket.js"(exports, module) {
2338
- "use strict";
2339
- var EventEmitter = __require("events");
2340
- var https = __require("https");
2341
- var http = __require("http");
2342
- var net = __require("net");
2343
- var tls = __require("tls");
2344
- var { randomBytes, createHash } = __require("crypto");
2345
- var { Duplex, Readable } = __require("stream");
2346
- var { URL: URL2 } = __require("url");
2347
- var PerMessageDeflate = require_permessage_deflate();
2348
- var Receiver2 = require_receiver();
2349
- var Sender2 = require_sender();
2350
- var { isBlob } = require_validation();
2351
- var {
2352
- BINARY_TYPES,
2353
- EMPTY_BUFFER,
2354
- GUID,
2355
- kForOnEventAttribute,
2356
- kListener,
2357
- kStatusCode,
2358
- kWebSocket,
2359
- NOOP
2360
- } = require_constants();
2361
- var {
2362
- EventTarget: { addEventListener, removeEventListener }
2363
- } = require_event_target();
2364
- var { format, parse } = require_extension();
2365
- var { toBuffer } = require_buffer_util();
2366
- var closeTimeout = 30 * 1e3;
2367
- var kAborted = /* @__PURE__ */ Symbol("kAborted");
2368
- var protocolVersions = [8, 13];
2369
- var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
2370
- var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
2371
- var WebSocket2 = class _WebSocket extends EventEmitter {
2372
- /**
2373
- * Create a new `WebSocket`.
2374
- *
2375
- * @param {(String|URL)} address The URL to which to connect
2376
- * @param {(String|String[])} [protocols] The subprotocols
2377
- * @param {Object} [options] Connection options
2378
- */
2379
- constructor(address, protocols, options) {
2380
- super();
2381
- this._binaryType = BINARY_TYPES[0];
2382
- this._closeCode = 1006;
2383
- this._closeFrameReceived = false;
2384
- this._closeFrameSent = false;
2385
- this._closeMessage = EMPTY_BUFFER;
2386
- this._closeTimer = null;
2387
- this._errorEmitted = false;
2388
- this._extensions = {};
2389
- this._paused = false;
2390
- this._protocol = "";
2391
- this._readyState = _WebSocket.CONNECTING;
2392
- this._receiver = null;
2393
- this._sender = null;
2394
- this._socket = null;
2395
- if (address !== null) {
2396
- this._bufferedAmount = 0;
2397
- this._isServer = false;
2398
- this._redirects = 0;
2399
- if (protocols === void 0) {
2400
- protocols = [];
2401
- } else if (!Array.isArray(protocols)) {
2402
- if (typeof protocols === "object" && protocols !== null) {
2403
- options = protocols;
2404
- protocols = [];
2405
- } else {
2406
- protocols = [protocols];
2407
- }
2408
- }
2409
- initAsClient(this, address, protocols, options);
2410
- } else {
2411
- this._autoPong = options.autoPong;
2412
- this._isServer = true;
2413
- }
2414
- }
2415
- /**
2416
- * For historical reasons, the custom "nodebuffer" type is used by the default
2417
- * instead of "blob".
2418
- *
2419
- * @type {String}
2420
- */
2421
- get binaryType() {
2422
- return this._binaryType;
2423
- }
2424
- set binaryType(type) {
2425
- if (!BINARY_TYPES.includes(type)) return;
2426
- this._binaryType = type;
2427
- if (this._receiver) this._receiver._binaryType = type;
2428
- }
2429
- /**
2430
- * @type {Number}
2431
- */
2432
- get bufferedAmount() {
2433
- if (!this._socket) return this._bufferedAmount;
2434
- return this._socket._writableState.length + this._sender._bufferedBytes;
2435
- }
2436
- /**
2437
- * @type {String}
2438
- */
2439
- get extensions() {
2440
- return Object.keys(this._extensions).join();
2441
- }
2442
- /**
2443
- * @type {Boolean}
2444
- */
2445
- get isPaused() {
2446
- return this._paused;
2447
- }
2448
- /**
2449
- * @type {Function}
2450
- */
2451
- /* istanbul ignore next */
2452
- get onclose() {
2453
- return null;
2454
- }
2455
- /**
2456
- * @type {Function}
2457
- */
2458
- /* istanbul ignore next */
2459
- get onerror() {
2460
- return null;
2461
- }
2462
- /**
2463
- * @type {Function}
2464
- */
2465
- /* istanbul ignore next */
2466
- get onopen() {
2467
- return null;
2468
- }
2469
- /**
2470
- * @type {Function}
2471
- */
2472
- /* istanbul ignore next */
2473
- get onmessage() {
2474
- return null;
2475
- }
2476
- /**
2477
- * @type {String}
2478
- */
2479
- get protocol() {
2480
- return this._protocol;
2481
- }
2482
- /**
2483
- * @type {Number}
2484
- */
2485
- get readyState() {
2486
- return this._readyState;
2487
- }
2488
- /**
2489
- * @type {String}
2490
- */
2491
- get url() {
2492
- return this._url;
2493
- }
2494
- /**
2495
- * Set up the socket and the internal resources.
2496
- *
2497
- * @param {Duplex} socket The network socket between the server and client
2498
- * @param {Buffer} head The first packet of the upgraded stream
2499
- * @param {Object} options Options object
2500
- * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
2501
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
2502
- * multiple times in the same tick
2503
- * @param {Function} [options.generateMask] The function used to generate the
2504
- * masking key
2505
- * @param {Number} [options.maxPayload=0] The maximum allowed message size
2506
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
2507
- * not to skip UTF-8 validation for text and close messages
2508
- * @private
2509
- */
2510
- setSocket(socket, head, options) {
2511
- const receiver = new Receiver2({
2512
- allowSynchronousEvents: options.allowSynchronousEvents,
2513
- binaryType: this.binaryType,
2514
- extensions: this._extensions,
2515
- isServer: this._isServer,
2516
- maxPayload: options.maxPayload,
2517
- skipUTF8Validation: options.skipUTF8Validation
2518
- });
2519
- const sender = new Sender2(socket, this._extensions, options.generateMask);
2520
- this._receiver = receiver;
2521
- this._sender = sender;
2522
- this._socket = socket;
2523
- receiver[kWebSocket] = this;
2524
- sender[kWebSocket] = this;
2525
- socket[kWebSocket] = this;
2526
- receiver.on("conclude", receiverOnConclude);
2527
- receiver.on("drain", receiverOnDrain);
2528
- receiver.on("error", receiverOnError);
2529
- receiver.on("message", receiverOnMessage);
2530
- receiver.on("ping", receiverOnPing);
2531
- receiver.on("pong", receiverOnPong);
2532
- sender.onerror = senderOnError;
2533
- if (socket.setTimeout) socket.setTimeout(0);
2534
- if (socket.setNoDelay) socket.setNoDelay();
2535
- if (head.length > 0) socket.unshift(head);
2536
- socket.on("close", socketOnClose);
2537
- socket.on("data", socketOnData);
2538
- socket.on("end", socketOnEnd);
2539
- socket.on("error", socketOnError);
2540
- this._readyState = _WebSocket.OPEN;
2541
- this.emit("open");
2542
- }
2543
- /**
2544
- * Emit the `'close'` event.
2545
- *
2546
- * @private
2547
- */
2548
- emitClose() {
2549
- if (!this._socket) {
2550
- this._readyState = _WebSocket.CLOSED;
2551
- this.emit("close", this._closeCode, this._closeMessage);
2552
- return;
2553
- }
2554
- if (this._extensions[PerMessageDeflate.extensionName]) {
2555
- this._extensions[PerMessageDeflate.extensionName].cleanup();
2556
- }
2557
- this._receiver.removeAllListeners();
2558
- this._readyState = _WebSocket.CLOSED;
2559
- this.emit("close", this._closeCode, this._closeMessage);
2560
- }
2561
- /**
2562
- * Start a closing handshake.
2563
- *
2564
- * +----------+ +-----------+ +----------+
2565
- * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
2566
- * | +----------+ +-----------+ +----------+ |
2567
- * +----------+ +-----------+ |
2568
- * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
2569
- * +----------+ +-----------+ |
2570
- * | | | +---+ |
2571
- * +------------------------+-->|fin| - - - -
2572
- * | +---+ | +---+
2573
- * - - - - -|fin|<---------------------+
2574
- * +---+
2575
- *
2576
- * @param {Number} [code] Status code explaining why the connection is closing
2577
- * @param {(String|Buffer)} [data] The reason why the connection is
2578
- * closing
2579
- * @public
2580
- */
2581
- close(code, data) {
2582
- if (this.readyState === _WebSocket.CLOSED) return;
2583
- if (this.readyState === _WebSocket.CONNECTING) {
2584
- const msg = "WebSocket was closed before the connection was established";
2585
- abortHandshake(this, this._req, msg);
2586
- return;
2587
- }
2588
- if (this.readyState === _WebSocket.CLOSING) {
2589
- if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) {
2590
- this._socket.end();
2591
- }
2592
- return;
2593
- }
2594
- this._readyState = _WebSocket.CLOSING;
2595
- this._sender.close(code, data, !this._isServer, (err) => {
2596
- if (err) return;
2597
- this._closeFrameSent = true;
2598
- if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) {
2599
- this._socket.end();
2600
- }
2601
- });
2602
- setCloseTimer(this);
2603
- }
2604
- /**
2605
- * Pause the socket.
2606
- *
2607
- * @public
2608
- */
2609
- pause() {
2610
- if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) {
2611
- return;
2612
- }
2613
- this._paused = true;
2614
- this._socket.pause();
2615
- }
2616
- /**
2617
- * Send a ping.
2618
- *
2619
- * @param {*} [data] The data to send
2620
- * @param {Boolean} [mask] Indicates whether or not to mask `data`
2621
- * @param {Function} [cb] Callback which is executed when the ping is sent
2622
- * @public
2623
- */
2624
- ping(data, mask, cb) {
2625
- if (this.readyState === _WebSocket.CONNECTING) {
2626
- throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
2627
- }
2628
- if (typeof data === "function") {
2629
- cb = data;
2630
- data = mask = void 0;
2631
- } else if (typeof mask === "function") {
2632
- cb = mask;
2633
- mask = void 0;
2634
- }
2635
- if (typeof data === "number") data = data.toString();
2636
- if (this.readyState !== _WebSocket.OPEN) {
2637
- sendAfterClose(this, data, cb);
2638
- return;
2639
- }
2640
- if (mask === void 0) mask = !this._isServer;
2641
- this._sender.ping(data || EMPTY_BUFFER, mask, cb);
2642
- }
2643
- /**
2644
- * Send a pong.
2645
- *
2646
- * @param {*} [data] The data to send
2647
- * @param {Boolean} [mask] Indicates whether or not to mask `data`
2648
- * @param {Function} [cb] Callback which is executed when the pong is sent
2649
- * @public
2650
- */
2651
- pong(data, mask, cb) {
2652
- if (this.readyState === _WebSocket.CONNECTING) {
2653
- throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
2654
- }
2655
- if (typeof data === "function") {
2656
- cb = data;
2657
- data = mask = void 0;
2658
- } else if (typeof mask === "function") {
2659
- cb = mask;
2660
- mask = void 0;
2661
- }
2662
- if (typeof data === "number") data = data.toString();
2663
- if (this.readyState !== _WebSocket.OPEN) {
2664
- sendAfterClose(this, data, cb);
2665
- return;
2666
- }
2667
- if (mask === void 0) mask = !this._isServer;
2668
- this._sender.pong(data || EMPTY_BUFFER, mask, cb);
2669
- }
2670
- /**
2671
- * Resume the socket.
2672
- *
2673
- * @public
2674
- */
2675
- resume() {
2676
- if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) {
2677
- return;
2678
- }
2679
- this._paused = false;
2680
- if (!this._receiver._writableState.needDrain) this._socket.resume();
2681
- }
2682
- /**
2683
- * Send a data message.
2684
- *
2685
- * @param {*} data The message to send
2686
- * @param {Object} [options] Options object
2687
- * @param {Boolean} [options.binary] Specifies whether `data` is binary or
2688
- * text
2689
- * @param {Boolean} [options.compress] Specifies whether or not to compress
2690
- * `data`
2691
- * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
2692
- * last one
2693
- * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
2694
- * @param {Function} [cb] Callback which is executed when data is written out
2695
- * @public
2696
- */
2697
- send(data, options, cb) {
2698
- if (this.readyState === _WebSocket.CONNECTING) {
2699
- throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
2700
- }
2701
- if (typeof options === "function") {
2702
- cb = options;
2703
- options = {};
2704
- }
2705
- if (typeof data === "number") data = data.toString();
2706
- if (this.readyState !== _WebSocket.OPEN) {
2707
- sendAfterClose(this, data, cb);
2708
- return;
2709
- }
2710
- const opts = {
2711
- binary: typeof data !== "string",
2712
- mask: !this._isServer,
2713
- compress: true,
2714
- fin: true,
2715
- ...options
2716
- };
2717
- if (!this._extensions[PerMessageDeflate.extensionName]) {
2718
- opts.compress = false;
2719
- }
2720
- this._sender.send(data || EMPTY_BUFFER, opts, cb);
2721
- }
2722
- /**
2723
- * Forcibly close the connection.
2724
- *
2725
- * @public
2726
- */
2727
- terminate() {
2728
- if (this.readyState === _WebSocket.CLOSED) return;
2729
- if (this.readyState === _WebSocket.CONNECTING) {
2730
- const msg = "WebSocket was closed before the connection was established";
2731
- abortHandshake(this, this._req, msg);
2732
- return;
2733
- }
2734
- if (this._socket) {
2735
- this._readyState = _WebSocket.CLOSING;
2736
- this._socket.destroy();
2737
- }
2738
- }
2739
- };
2740
- Object.defineProperty(WebSocket2, "CONNECTING", {
2741
- enumerable: true,
2742
- value: readyStates.indexOf("CONNECTING")
2743
- });
2744
- Object.defineProperty(WebSocket2.prototype, "CONNECTING", {
2745
- enumerable: true,
2746
- value: readyStates.indexOf("CONNECTING")
2747
- });
2748
- Object.defineProperty(WebSocket2, "OPEN", {
2749
- enumerable: true,
2750
- value: readyStates.indexOf("OPEN")
2751
- });
2752
- Object.defineProperty(WebSocket2.prototype, "OPEN", {
2753
- enumerable: true,
2754
- value: readyStates.indexOf("OPEN")
2755
- });
2756
- Object.defineProperty(WebSocket2, "CLOSING", {
2757
- enumerable: true,
2758
- value: readyStates.indexOf("CLOSING")
2759
- });
2760
- Object.defineProperty(WebSocket2.prototype, "CLOSING", {
2761
- enumerable: true,
2762
- value: readyStates.indexOf("CLOSING")
2763
- });
2764
- Object.defineProperty(WebSocket2, "CLOSED", {
2765
- enumerable: true,
2766
- value: readyStates.indexOf("CLOSED")
2767
- });
2768
- Object.defineProperty(WebSocket2.prototype, "CLOSED", {
2769
- enumerable: true,
2770
- value: readyStates.indexOf("CLOSED")
2771
- });
2772
- [
2773
- "binaryType",
2774
- "bufferedAmount",
2775
- "extensions",
2776
- "isPaused",
2777
- "protocol",
2778
- "readyState",
2779
- "url"
2780
- ].forEach((property) => {
2781
- Object.defineProperty(WebSocket2.prototype, property, { enumerable: true });
2782
- });
2783
- ["open", "error", "close", "message"].forEach((method) => {
2784
- Object.defineProperty(WebSocket2.prototype, `on${method}`, {
2785
- enumerable: true,
2786
- get() {
2787
- for (const listener of this.listeners(method)) {
2788
- if (listener[kForOnEventAttribute]) return listener[kListener];
2789
- }
2790
- return null;
2791
- },
2792
- set(handler) {
2793
- for (const listener of this.listeners(method)) {
2794
- if (listener[kForOnEventAttribute]) {
2795
- this.removeListener(method, listener);
2796
- break;
2797
- }
2798
- }
2799
- if (typeof handler !== "function") return;
2800
- this.addEventListener(method, handler, {
2801
- [kForOnEventAttribute]: true
2802
- });
2803
- }
2804
- });
2805
- });
2806
- WebSocket2.prototype.addEventListener = addEventListener;
2807
- WebSocket2.prototype.removeEventListener = removeEventListener;
2808
- module.exports = WebSocket2;
2809
- function initAsClient(websocket, address, protocols, options) {
2810
- const opts = {
2811
- allowSynchronousEvents: true,
2812
- autoPong: true,
2813
- protocolVersion: protocolVersions[1],
2814
- maxPayload: 100 * 1024 * 1024,
2815
- skipUTF8Validation: false,
2816
- perMessageDeflate: true,
2817
- followRedirects: false,
2818
- maxRedirects: 10,
2819
- ...options,
2820
- socketPath: void 0,
2821
- hostname: void 0,
2822
- protocol: void 0,
2823
- timeout: void 0,
2824
- method: "GET",
2825
- host: void 0,
2826
- path: void 0,
2827
- port: void 0
2828
- };
2829
- websocket._autoPong = opts.autoPong;
2830
- if (!protocolVersions.includes(opts.protocolVersion)) {
2831
- throw new RangeError(
2832
- `Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`
2833
- );
2834
- }
2835
- let parsedUrl;
2836
- if (address instanceof URL2) {
2837
- parsedUrl = address;
2838
- } else {
2839
- try {
2840
- parsedUrl = new URL2(address);
2841
- } catch (e) {
2842
- throw new SyntaxError(`Invalid URL: ${address}`);
2843
- }
2844
- }
2845
- if (parsedUrl.protocol === "http:") {
2846
- parsedUrl.protocol = "ws:";
2847
- } else if (parsedUrl.protocol === "https:") {
2848
- parsedUrl.protocol = "wss:";
2849
- }
2850
- websocket._url = parsedUrl.href;
2851
- const isSecure = parsedUrl.protocol === "wss:";
2852
- const isIpcUrl = parsedUrl.protocol === "ws+unix:";
2853
- let invalidUrlMessage;
2854
- if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) {
2855
- invalidUrlMessage = `The URL's protocol must be one of "ws:", "wss:", "http:", "https", or "ws+unix:"`;
2856
- } else if (isIpcUrl && !parsedUrl.pathname) {
2857
- invalidUrlMessage = "The URL's pathname is empty";
2858
- } else if (parsedUrl.hash) {
2859
- invalidUrlMessage = "The URL contains a fragment identifier";
2860
- }
2861
- if (invalidUrlMessage) {
2862
- const err = new SyntaxError(invalidUrlMessage);
2863
- if (websocket._redirects === 0) {
2864
- throw err;
2865
- } else {
2866
- emitErrorAndClose(websocket, err);
2867
- return;
2868
- }
2869
- }
2870
- const defaultPort = isSecure ? 443 : 80;
2871
- const key = randomBytes(16).toString("base64");
2872
- const request = isSecure ? https.request : http.request;
2873
- const protocolSet = /* @__PURE__ */ new Set();
2874
- let perMessageDeflate;
2875
- opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
2876
- opts.defaultPort = opts.defaultPort || defaultPort;
2877
- opts.port = parsedUrl.port || defaultPort;
2878
- opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname;
2879
- opts.headers = {
2880
- ...opts.headers,
2881
- "Sec-WebSocket-Version": opts.protocolVersion,
2882
- "Sec-WebSocket-Key": key,
2883
- Connection: "Upgrade",
2884
- Upgrade: "websocket"
2885
- };
2886
- opts.path = parsedUrl.pathname + parsedUrl.search;
2887
- opts.timeout = opts.handshakeTimeout;
2888
- if (opts.perMessageDeflate) {
2889
- perMessageDeflate = new PerMessageDeflate(
2890
- opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
2891
- false,
2892
- opts.maxPayload
2893
- );
2894
- opts.headers["Sec-WebSocket-Extensions"] = format({
2895
- [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
2896
- });
2897
- }
2898
- if (protocols.length) {
2899
- for (const protocol of protocols) {
2900
- if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) {
2901
- throw new SyntaxError(
2902
- "An invalid or duplicated subprotocol was specified"
2903
- );
2904
- }
2905
- protocolSet.add(protocol);
2906
- }
2907
- opts.headers["Sec-WebSocket-Protocol"] = protocols.join(",");
2908
- }
2909
- if (opts.origin) {
2910
- if (opts.protocolVersion < 13) {
2911
- opts.headers["Sec-WebSocket-Origin"] = opts.origin;
2912
- } else {
2913
- opts.headers.Origin = opts.origin;
2914
- }
2915
- }
2916
- if (parsedUrl.username || parsedUrl.password) {
2917
- opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
2918
- }
2919
- if (isIpcUrl) {
2920
- const parts = opts.path.split(":");
2921
- opts.socketPath = parts[0];
2922
- opts.path = parts[1];
2923
- }
2924
- let req;
2925
- if (opts.followRedirects) {
2926
- if (websocket._redirects === 0) {
2927
- websocket._originalIpc = isIpcUrl;
2928
- websocket._originalSecure = isSecure;
2929
- websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host;
2930
- const headers = options && options.headers;
2931
- options = { ...options, headers: {} };
2932
- if (headers) {
2933
- for (const [key2, value] of Object.entries(headers)) {
2934
- options.headers[key2.toLowerCase()] = value;
2935
- }
2936
- }
2937
- } else if (websocket.listenerCount("redirect") === 0) {
2938
- const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath;
2939
- if (!isSameHost || websocket._originalSecure && !isSecure) {
2940
- delete opts.headers.authorization;
2941
- delete opts.headers.cookie;
2942
- if (!isSameHost) delete opts.headers.host;
2943
- opts.auth = void 0;
2944
- }
2945
- }
2946
- if (opts.auth && !options.headers.authorization) {
2947
- options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
2948
- }
2949
- req = websocket._req = request(opts);
2950
- if (websocket._redirects) {
2951
- websocket.emit("redirect", websocket.url, req);
2952
- }
2953
- } else {
2954
- req = websocket._req = request(opts);
2955
- }
2956
- if (opts.timeout) {
2957
- req.on("timeout", () => {
2958
- abortHandshake(websocket, req, "Opening handshake has timed out");
2959
- });
2960
- }
2961
- req.on("error", (err) => {
2962
- if (req === null || req[kAborted]) return;
2963
- req = websocket._req = null;
2964
- emitErrorAndClose(websocket, err);
2965
- });
2966
- req.on("response", (res) => {
2967
- const location = res.headers.location;
2968
- const statusCode = res.statusCode;
2969
- if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
2970
- if (++websocket._redirects > opts.maxRedirects) {
2971
- abortHandshake(websocket, req, "Maximum redirects exceeded");
2972
- return;
2973
- }
2974
- req.abort();
2975
- let addr;
2976
- try {
2977
- addr = new URL2(location, address);
2978
- } catch (e) {
2979
- const err = new SyntaxError(`Invalid URL: ${location}`);
2980
- emitErrorAndClose(websocket, err);
2981
- return;
2982
- }
2983
- initAsClient(websocket, addr, protocols, options);
2984
- } else if (!websocket.emit("unexpected-response", req, res)) {
2985
- abortHandshake(
2986
- websocket,
2987
- req,
2988
- `Unexpected server response: ${res.statusCode}`
2989
- );
2990
- }
2991
- });
2992
- req.on("upgrade", (res, socket, head) => {
2993
- websocket.emit("upgrade", res);
2994
- if (websocket.readyState !== WebSocket2.CONNECTING) return;
2995
- req = websocket._req = null;
2996
- const upgrade = res.headers.upgrade;
2997
- if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
2998
- abortHandshake(websocket, socket, "Invalid Upgrade header");
2999
- return;
3000
- }
3001
- const digest = createHash("sha1").update(key + GUID).digest("base64");
3002
- if (res.headers["sec-websocket-accept"] !== digest) {
3003
- abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
3004
- return;
3005
- }
3006
- const serverProt = res.headers["sec-websocket-protocol"];
3007
- let protError;
3008
- if (serverProt !== void 0) {
3009
- if (!protocolSet.size) {
3010
- protError = "Server sent a subprotocol but none was requested";
3011
- } else if (!protocolSet.has(serverProt)) {
3012
- protError = "Server sent an invalid subprotocol";
3013
- }
3014
- } else if (protocolSet.size) {
3015
- protError = "Server sent no subprotocol";
3016
- }
3017
- if (protError) {
3018
- abortHandshake(websocket, socket, protError);
3019
- return;
3020
- }
3021
- if (serverProt) websocket._protocol = serverProt;
3022
- const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
3023
- if (secWebSocketExtensions !== void 0) {
3024
- if (!perMessageDeflate) {
3025
- const message = "Server sent a Sec-WebSocket-Extensions header but no extension was requested";
3026
- abortHandshake(websocket, socket, message);
3027
- return;
3028
- }
3029
- let extensions;
3030
- try {
3031
- extensions = parse(secWebSocketExtensions);
3032
- } catch (err) {
3033
- const message = "Invalid Sec-WebSocket-Extensions header";
3034
- abortHandshake(websocket, socket, message);
3035
- return;
3036
- }
3037
- const extensionNames = Object.keys(extensions);
3038
- if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) {
3039
- const message = "Server indicated an extension that was not requested";
3040
- abortHandshake(websocket, socket, message);
3041
- return;
3042
- }
3043
- try {
3044
- perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
3045
- } catch (err) {
3046
- const message = "Invalid Sec-WebSocket-Extensions header";
3047
- abortHandshake(websocket, socket, message);
3048
- return;
3049
- }
3050
- websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
3051
- }
3052
- websocket.setSocket(socket, head, {
3053
- allowSynchronousEvents: opts.allowSynchronousEvents,
3054
- generateMask: opts.generateMask,
3055
- maxPayload: opts.maxPayload,
3056
- skipUTF8Validation: opts.skipUTF8Validation
3057
- });
3058
- });
3059
- if (opts.finishRequest) {
3060
- opts.finishRequest(req, websocket);
3061
- } else {
3062
- req.end();
3063
- }
3064
- }
3065
- function emitErrorAndClose(websocket, err) {
3066
- websocket._readyState = WebSocket2.CLOSING;
3067
- websocket._errorEmitted = true;
3068
- websocket.emit("error", err);
3069
- websocket.emitClose();
3070
- }
3071
- function netConnect(options) {
3072
- options.path = options.socketPath;
3073
- return net.connect(options);
3074
- }
3075
- function tlsConnect(options) {
3076
- options.path = void 0;
3077
- if (!options.servername && options.servername !== "") {
3078
- options.servername = net.isIP(options.host) ? "" : options.host;
3079
- }
3080
- return tls.connect(options);
3081
- }
3082
- function abortHandshake(websocket, stream, message) {
3083
- websocket._readyState = WebSocket2.CLOSING;
3084
- const err = new Error(message);
3085
- Error.captureStackTrace(err, abortHandshake);
3086
- if (stream.setHeader) {
3087
- stream[kAborted] = true;
3088
- stream.abort();
3089
- if (stream.socket && !stream.socket.destroyed) {
3090
- stream.socket.destroy();
3091
- }
3092
- process.nextTick(emitErrorAndClose, websocket, err);
3093
- } else {
3094
- stream.destroy(err);
3095
- stream.once("error", websocket.emit.bind(websocket, "error"));
3096
- stream.once("close", websocket.emitClose.bind(websocket));
3097
- }
3098
- }
3099
- function sendAfterClose(websocket, data, cb) {
3100
- if (data) {
3101
- const length = isBlob(data) ? data.size : toBuffer(data).length;
3102
- if (websocket._socket) websocket._sender._bufferedBytes += length;
3103
- else websocket._bufferedAmount += length;
3104
- }
3105
- if (cb) {
3106
- const err = new Error(
3107
- `WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})`
3108
- );
3109
- process.nextTick(cb, err);
3110
- }
3111
- }
3112
- function receiverOnConclude(code, reason) {
3113
- const websocket = this[kWebSocket];
3114
- websocket._closeFrameReceived = true;
3115
- websocket._closeMessage = reason;
3116
- websocket._closeCode = code;
3117
- if (websocket._socket[kWebSocket] === void 0) return;
3118
- websocket._socket.removeListener("data", socketOnData);
3119
- process.nextTick(resume, websocket._socket);
3120
- if (code === 1005) websocket.close();
3121
- else websocket.close(code, reason);
3122
- }
3123
- function receiverOnDrain() {
3124
- const websocket = this[kWebSocket];
3125
- if (!websocket.isPaused) websocket._socket.resume();
3126
- }
3127
- function receiverOnError(err) {
3128
- const websocket = this[kWebSocket];
3129
- if (websocket._socket[kWebSocket] !== void 0) {
3130
- websocket._socket.removeListener("data", socketOnData);
3131
- process.nextTick(resume, websocket._socket);
3132
- websocket.close(err[kStatusCode]);
3133
- }
3134
- if (!websocket._errorEmitted) {
3135
- websocket._errorEmitted = true;
3136
- websocket.emit("error", err);
3137
- }
3138
- }
3139
- function receiverOnFinish() {
3140
- this[kWebSocket].emitClose();
3141
- }
3142
- function receiverOnMessage(data, isBinary) {
3143
- this[kWebSocket].emit("message", data, isBinary);
3144
- }
3145
- function receiverOnPing(data) {
3146
- const websocket = this[kWebSocket];
3147
- if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
3148
- websocket.emit("ping", data);
3149
- }
3150
- function receiverOnPong(data) {
3151
- this[kWebSocket].emit("pong", data);
3152
- }
3153
- function resume(stream) {
3154
- stream.resume();
3155
- }
3156
- function senderOnError(err) {
3157
- const websocket = this[kWebSocket];
3158
- if (websocket.readyState === WebSocket2.CLOSED) return;
3159
- if (websocket.readyState === WebSocket2.OPEN) {
3160
- websocket._readyState = WebSocket2.CLOSING;
3161
- setCloseTimer(websocket);
3162
- }
3163
- this._socket.end();
3164
- if (!websocket._errorEmitted) {
3165
- websocket._errorEmitted = true;
3166
- websocket.emit("error", err);
3167
- }
3168
- }
3169
- function setCloseTimer(websocket) {
3170
- websocket._closeTimer = setTimeout(
3171
- websocket._socket.destroy.bind(websocket._socket),
3172
- closeTimeout
3173
- );
3174
- }
3175
- function socketOnClose() {
3176
- const websocket = this[kWebSocket];
3177
- this.removeListener("close", socketOnClose);
3178
- this.removeListener("data", socketOnData);
3179
- this.removeListener("end", socketOnEnd);
3180
- websocket._readyState = WebSocket2.CLOSING;
3181
- let chunk;
3182
- if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) {
3183
- websocket._receiver.write(chunk);
3184
- }
3185
- websocket._receiver.end();
3186
- this[kWebSocket] = void 0;
3187
- clearTimeout(websocket._closeTimer);
3188
- if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) {
3189
- websocket.emitClose();
3190
- } else {
3191
- websocket._receiver.on("error", receiverOnFinish);
3192
- websocket._receiver.on("finish", receiverOnFinish);
3193
- }
3194
- }
3195
- function socketOnData(chunk) {
3196
- if (!this[kWebSocket]._receiver.write(chunk)) {
3197
- this.pause();
3198
- }
3199
- }
3200
- function socketOnEnd() {
3201
- const websocket = this[kWebSocket];
3202
- websocket._readyState = WebSocket2.CLOSING;
3203
- websocket._receiver.end();
3204
- this.end();
3205
- }
3206
- function socketOnError() {
3207
- const websocket = this[kWebSocket];
3208
- this.removeListener("error", socketOnError);
3209
- this.on("error", NOOP);
3210
- if (websocket) {
3211
- websocket._readyState = WebSocket2.CLOSING;
3212
- this.destroy();
3213
- }
3214
- }
71
+ const authResult = await verifyToken(token, jwtSecret);
72
+ if (!authResult.ok) {
73
+ return { authenticated: false, status: 401, message: authResult.error.message };
3215
74
  }
3216
- });
3217
-
3218
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/subprotocol.js
3219
- var require_subprotocol = __commonJS({
3220
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
3221
- "use strict";
3222
- var { tokenChars } = require_validation();
3223
- function parse(header) {
3224
- const protocols = /* @__PURE__ */ new Set();
3225
- let start = -1;
3226
- let end = -1;
3227
- let i = 0;
3228
- for (i; i < header.length; i++) {
3229
- const code = header.charCodeAt(i);
3230
- if (end === -1 && tokenChars[code] === 1) {
3231
- if (start === -1) start = i;
3232
- } else if (i !== 0 && (code === 32 || code === 9)) {
3233
- if (end === -1 && start !== -1) end = i;
3234
- } else if (code === 44) {
3235
- if (start === -1) {
3236
- throw new SyntaxError(`Unexpected character at index ${i}`);
3237
- }
3238
- if (end === -1) end = i;
3239
- const protocol2 = header.slice(start, end);
3240
- if (protocols.has(protocol2)) {
3241
- throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`);
3242
- }
3243
- protocols.add(protocol2);
3244
- start = end = -1;
3245
- } else {
3246
- throw new SyntaxError(`Unexpected character at index ${i}`);
3247
- }
3248
- }
3249
- if (start === -1 || end !== -1) {
3250
- throw new SyntaxError("Unexpected end of input");
3251
- }
3252
- const protocol = header.slice(start, i);
3253
- if (protocols.has(protocol)) {
3254
- throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
3255
- }
3256
- protocols.add(protocol);
3257
- return protocols;
3258
- }
3259
- module.exports = { parse };
3260
- }
3261
- });
3262
-
3263
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/websocket-server.js
3264
- var require_websocket_server = __commonJS({
3265
- "../../node_modules/.bun/ws@8.18.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
3266
- "use strict";
3267
- var EventEmitter = __require("events");
3268
- var http = __require("http");
3269
- var { Duplex } = __require("stream");
3270
- var { createHash } = __require("crypto");
3271
- var extension = require_extension();
3272
- var PerMessageDeflate = require_permessage_deflate();
3273
- var subprotocol = require_subprotocol();
3274
- var WebSocket2 = require_websocket();
3275
- var { GUID, kWebSocket } = require_constants();
3276
- var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
3277
- var RUNNING = 0;
3278
- var CLOSING = 1;
3279
- var CLOSED = 2;
3280
- var WebSocketServer2 = class extends EventEmitter {
3281
- /**
3282
- * Create a `WebSocketServer` instance.
3283
- *
3284
- * @param {Object} options Configuration options
3285
- * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
3286
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
3287
- * multiple times in the same tick
3288
- * @param {Boolean} [options.autoPong=true] Specifies whether or not to
3289
- * automatically send a pong in response to a ping
3290
- * @param {Number} [options.backlog=511] The maximum length of the queue of
3291
- * pending connections
3292
- * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
3293
- * track clients
3294
- * @param {Function} [options.handleProtocols] A hook to handle protocols
3295
- * @param {String} [options.host] The hostname where to bind the server
3296
- * @param {Number} [options.maxPayload=104857600] The maximum allowed message
3297
- * size
3298
- * @param {Boolean} [options.noServer=false] Enable no server mode
3299
- * @param {String} [options.path] Accept only connections matching this path
3300
- * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
3301
- * permessage-deflate
3302
- * @param {Number} [options.port] The port where to bind the server
3303
- * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
3304
- * server to use
3305
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
3306
- * not to skip UTF-8 validation for text and close messages
3307
- * @param {Function} [options.verifyClient] A hook to reject connections
3308
- * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
3309
- * class to use. It must be the `WebSocket` class or class that extends it
3310
- * @param {Function} [callback] A listener for the `listening` event
3311
- */
3312
- constructor(options, callback) {
3313
- super();
3314
- options = {
3315
- allowSynchronousEvents: true,
3316
- autoPong: true,
3317
- maxPayload: 100 * 1024 * 1024,
3318
- skipUTF8Validation: false,
3319
- perMessageDeflate: false,
3320
- handleProtocols: null,
3321
- clientTracking: true,
3322
- verifyClient: null,
3323
- noServer: false,
3324
- backlog: null,
3325
- // use default (511 as implemented in net.js)
3326
- server: null,
3327
- host: null,
3328
- path: null,
3329
- port: null,
3330
- WebSocket: WebSocket2,
3331
- ...options
3332
- };
3333
- if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) {
3334
- throw new TypeError(
3335
- 'One and only one of the "port", "server", or "noServer" options must be specified'
3336
- );
3337
- }
3338
- if (options.port != null) {
3339
- this._server = http.createServer((req, res) => {
3340
- const body = http.STATUS_CODES[426];
3341
- res.writeHead(426, {
3342
- "Content-Length": body.length,
3343
- "Content-Type": "text/plain"
3344
- });
3345
- res.end(body);
3346
- });
3347
- this._server.listen(
3348
- options.port,
3349
- options.host,
3350
- options.backlog,
3351
- callback
3352
- );
3353
- } else if (options.server) {
3354
- this._server = options.server;
3355
- }
3356
- if (this._server) {
3357
- const emitConnection = this.emit.bind(this, "connection");
3358
- this._removeListeners = addListeners(this._server, {
3359
- listening: this.emit.bind(this, "listening"),
3360
- error: this.emit.bind(this, "error"),
3361
- upgrade: (req, socket, head) => {
3362
- this.handleUpgrade(req, socket, head, emitConnection);
3363
- }
3364
- });
3365
- }
3366
- if (options.perMessageDeflate === true) options.perMessageDeflate = {};
3367
- if (options.clientTracking) {
3368
- this.clients = /* @__PURE__ */ new Set();
3369
- this._shouldEmitClose = false;
3370
- }
3371
- this.options = options;
3372
- this._state = RUNNING;
3373
- }
3374
- /**
3375
- * Returns the bound address, the address family name, and port of the server
3376
- * as reported by the operating system if listening on an IP socket.
3377
- * If the server is listening on a pipe or UNIX domain socket, the name is
3378
- * returned as a string.
3379
- *
3380
- * @return {(Object|String|null)} The address of the server
3381
- * @public
3382
- */
3383
- address() {
3384
- if (this.options.noServer) {
3385
- throw new Error('The server is operating in "noServer" mode');
3386
- }
3387
- if (!this._server) return null;
3388
- return this._server.address();
3389
- }
3390
- /**
3391
- * Stop the server from accepting new connections and emit the `'close'` event
3392
- * when all existing connections are closed.
3393
- *
3394
- * @param {Function} [cb] A one-time listener for the `'close'` event
3395
- * @public
3396
- */
3397
- close(cb) {
3398
- if (this._state === CLOSED) {
3399
- if (cb) {
3400
- this.once("close", () => {
3401
- cb(new Error("The server is not running"));
3402
- });
3403
- }
3404
- process.nextTick(emitClose, this);
3405
- return;
3406
- }
3407
- if (cb) this.once("close", cb);
3408
- if (this._state === CLOSING) return;
3409
- this._state = CLOSING;
3410
- if (this.options.noServer || this.options.server) {
3411
- if (this._server) {
3412
- this._removeListeners();
3413
- this._removeListeners = this._server = null;
3414
- }
3415
- if (this.clients) {
3416
- if (!this.clients.size) {
3417
- process.nextTick(emitClose, this);
3418
- } else {
3419
- this._shouldEmitClose = true;
3420
- }
3421
- } else {
3422
- process.nextTick(emitClose, this);
3423
- }
3424
- } else {
3425
- const server = this._server;
3426
- this._removeListeners();
3427
- this._removeListeners = this._server = null;
3428
- server.close(() => {
3429
- emitClose(this);
3430
- });
3431
- }
3432
- }
3433
- /**
3434
- * See if a given request should be handled by this server instance.
3435
- *
3436
- * @param {http.IncomingMessage} req Request object to inspect
3437
- * @return {Boolean} `true` if the request is valid, else `false`
3438
- * @public
3439
- */
3440
- shouldHandle(req) {
3441
- if (this.options.path) {
3442
- const index = req.url.indexOf("?");
3443
- const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
3444
- if (pathname !== this.options.path) return false;
3445
- }
3446
- return true;
3447
- }
3448
- /**
3449
- * Handle a HTTP Upgrade request.
3450
- *
3451
- * @param {http.IncomingMessage} req The request object
3452
- * @param {Duplex} socket The network socket between the server and client
3453
- * @param {Buffer} head The first packet of the upgraded stream
3454
- * @param {Function} cb Callback
3455
- * @public
3456
- */
3457
- handleUpgrade(req, socket, head, cb) {
3458
- socket.on("error", socketOnError);
3459
- const key = req.headers["sec-websocket-key"];
3460
- const upgrade = req.headers.upgrade;
3461
- const version = +req.headers["sec-websocket-version"];
3462
- if (req.method !== "GET") {
3463
- const message = "Invalid HTTP method";
3464
- abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
3465
- return;
3466
- }
3467
- if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
3468
- const message = "Invalid Upgrade header";
3469
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3470
- return;
3471
- }
3472
- if (key === void 0 || !keyRegex.test(key)) {
3473
- const message = "Missing or invalid Sec-WebSocket-Key header";
3474
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3475
- return;
3476
- }
3477
- if (version !== 8 && version !== 13) {
3478
- const message = "Missing or invalid Sec-WebSocket-Version header";
3479
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3480
- return;
3481
- }
3482
- if (!this.shouldHandle(req)) {
3483
- abortHandshake(socket, 400);
3484
- return;
3485
- }
3486
- const secWebSocketProtocol = req.headers["sec-websocket-protocol"];
3487
- let protocols = /* @__PURE__ */ new Set();
3488
- if (secWebSocketProtocol !== void 0) {
3489
- try {
3490
- protocols = subprotocol.parse(secWebSocketProtocol);
3491
- } catch (err) {
3492
- const message = "Invalid Sec-WebSocket-Protocol header";
3493
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3494
- return;
3495
- }
3496
- }
3497
- const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
3498
- const extensions = {};
3499
- if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
3500
- const perMessageDeflate = new PerMessageDeflate(
3501
- this.options.perMessageDeflate,
3502
- true,
3503
- this.options.maxPayload
3504
- );
3505
- try {
3506
- const offers = extension.parse(secWebSocketExtensions);
3507
- if (offers[PerMessageDeflate.extensionName]) {
3508
- perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
3509
- extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
3510
- }
3511
- } catch (err) {
3512
- const message = "Invalid or unacceptable Sec-WebSocket-Extensions header";
3513
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
3514
- return;
3515
- }
3516
- }
3517
- if (this.options.verifyClient) {
3518
- const info = {
3519
- origin: req.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`],
3520
- secure: !!(req.socket.authorized || req.socket.encrypted),
3521
- req
3522
- };
3523
- if (this.options.verifyClient.length === 2) {
3524
- this.options.verifyClient(info, (verified, code, message, headers) => {
3525
- if (!verified) {
3526
- return abortHandshake(socket, code || 401, message, headers);
3527
- }
3528
- this.completeUpgrade(
3529
- extensions,
3530
- key,
3531
- protocols,
3532
- req,
3533
- socket,
3534
- head,
3535
- cb
3536
- );
3537
- });
3538
- return;
3539
- }
3540
- if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
3541
- }
3542
- this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
3543
- }
3544
- /**
3545
- * Upgrade the connection to WebSocket.
3546
- *
3547
- * @param {Object} extensions The accepted extensions
3548
- * @param {String} key The value of the `Sec-WebSocket-Key` header
3549
- * @param {Set} protocols The subprotocols
3550
- * @param {http.IncomingMessage} req The request object
3551
- * @param {Duplex} socket The network socket between the server and client
3552
- * @param {Buffer} head The first packet of the upgraded stream
3553
- * @param {Function} cb Callback
3554
- * @throws {Error} If called more than once with the same socket
3555
- * @private
3556
- */
3557
- completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
3558
- if (!socket.readable || !socket.writable) return socket.destroy();
3559
- if (socket[kWebSocket]) {
3560
- throw new Error(
3561
- "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration"
3562
- );
3563
- }
3564
- if (this._state > RUNNING) return abortHandshake(socket, 503);
3565
- const digest = createHash("sha1").update(key + GUID).digest("base64");
3566
- const headers = [
3567
- "HTTP/1.1 101 Switching Protocols",
3568
- "Upgrade: websocket",
3569
- "Connection: Upgrade",
3570
- `Sec-WebSocket-Accept: ${digest}`
3571
- ];
3572
- const ws = new this.options.WebSocket(null, void 0, this.options);
3573
- if (protocols.size) {
3574
- const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value;
3575
- if (protocol) {
3576
- headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
3577
- ws._protocol = protocol;
3578
- }
3579
- }
3580
- if (extensions[PerMessageDeflate.extensionName]) {
3581
- const params = extensions[PerMessageDeflate.extensionName].params;
3582
- const value = extension.format({
3583
- [PerMessageDeflate.extensionName]: [params]
3584
- });
3585
- headers.push(`Sec-WebSocket-Extensions: ${value}`);
3586
- ws._extensions = extensions;
3587
- }
3588
- this.emit("headers", headers, req);
3589
- socket.write(headers.concat("\r\n").join("\r\n"));
3590
- socket.removeListener("error", socketOnError);
3591
- ws.setSocket(socket, head, {
3592
- allowSynchronousEvents: this.options.allowSynchronousEvents,
3593
- maxPayload: this.options.maxPayload,
3594
- skipUTF8Validation: this.options.skipUTF8Validation
3595
- });
3596
- if (this.clients) {
3597
- this.clients.add(ws);
3598
- ws.on("close", () => {
3599
- this.clients.delete(ws);
3600
- if (this._shouldEmitClose && !this.clients.size) {
3601
- process.nextTick(emitClose, this);
3602
- }
3603
- });
3604
- }
3605
- cb(ws, req);
3606
- }
3607
- };
3608
- module.exports = WebSocketServer2;
3609
- function addListeners(server, map) {
3610
- for (const event of Object.keys(map)) server.on(event, map[event]);
3611
- return function removeListeners() {
3612
- for (const event of Object.keys(map)) {
3613
- server.removeListener(event, map[event]);
3614
- }
3615
- };
3616
- }
3617
- function emitClose(server) {
3618
- server._state = CLOSED;
3619
- server.emit("close");
3620
- }
3621
- function socketOnError() {
3622
- this.destroy();
3623
- }
3624
- function abortHandshake(socket, code, message, headers) {
3625
- message = message || http.STATUS_CODES[code];
3626
- headers = {
3627
- Connection: "close",
3628
- "Content-Type": "text/html",
3629
- "Content-Length": Buffer.byteLength(message),
3630
- ...headers
3631
- };
3632
- socket.once("finish", socket.destroy);
3633
- socket.end(
3634
- `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r
3635
- ` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join("\r\n") + "\r\n\r\n" + message
3636
- );
3637
- }
3638
- function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) {
3639
- if (server.listenerCount("wsClientError")) {
3640
- const err = new Error(message);
3641
- Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
3642
- server.emit("wsClientError", err, socket, req);
3643
- } else {
3644
- abortHandshake(socket, code, message);
3645
- }
3646
- }
75
+ const claims = authResult.value;
76
+ if (claims.gatewayId !== routeGatewayId) {
77
+ return {
78
+ authenticated: false,
79
+ status: 403,
80
+ message: "Gateway ID mismatch: JWT authorises a different gateway"
81
+ };
82
+ }
83
+ if (ADMIN_ACTIONS.has(routeAction) && claims.role !== "admin") {
84
+ return { authenticated: false, status: 403, message: "Admin role required" };
3647
85
  }
3648
- });
86
+ return { authenticated: true, claims };
87
+ }
3649
88
 
3650
89
  // ../gateway-server/src/cluster.ts
3651
90
  var AdapterBasedLock = class {
@@ -3657,11 +96,20 @@ var AdapterBasedLock = class {
3657
96
  }
3658
97
  async acquire(key, ttlMs) {
3659
98
  try {
99
+ const now = Date.now();
3660
100
  const result = await this.adapter.insertDeltas([
3661
- this.makeLockDelta("INSERT", key, [
3662
- { column: "holder", value: this.instanceId },
3663
- { column: "expires_at", value: Date.now() + ttlMs }
3664
- ])
101
+ {
102
+ op: "INSERT",
103
+ table: "__lakesync_locks",
104
+ rowId: key,
105
+ clientId: this.instanceId,
106
+ columns: [
107
+ { column: "holder", value: this.instanceId },
108
+ { column: "expires_at", value: now + ttlMs }
109
+ ],
110
+ hlc: this.makeHlc(now),
111
+ deltaId: `lock-${key}-${now}`
112
+ }
3665
113
  ]);
3666
114
  return result.ok;
3667
115
  } catch {
@@ -3670,20 +118,28 @@ var AdapterBasedLock = class {
3670
118
  }
3671
119
  async release(key) {
3672
120
  try {
3673
- await this.adapter.insertDeltas([this.makeLockDelta("DELETE", key, [])]);
121
+ const now = Date.now();
122
+ await this.adapter.insertDeltas([
123
+ {
124
+ op: "DELETE",
125
+ table: "__lakesync_locks",
126
+ rowId: key,
127
+ clientId: this.instanceId,
128
+ columns: [],
129
+ hlc: this.makeHlc(now),
130
+ deltaId: `unlock-${key}-${now}`
131
+ }
132
+ ]);
3674
133
  } catch {
3675
134
  }
3676
135
  }
3677
- makeLockDelta(op, key, columns) {
3678
- return {
3679
- op,
3680
- table: "__lakesync_locks",
3681
- rowId: key,
3682
- clientId: this.instanceId,
3683
- columns,
3684
- hlc: BigInt(Date.now()) << 16n,
3685
- deltaId: `${op === "INSERT" ? "lock" : "unlock"}-${key}-${Date.now()}`
3686
- };
136
+ /**
137
+ * Create an HLC-format timestamp from wall clock time.
138
+ *
139
+ * Uses the standard 48-bit wall + 16-bit counter encoding.
140
+ */
141
+ makeHlc(wallMs) {
142
+ return BigInt(wallMs) << 16n;
3687
143
  }
3688
144
  };
3689
145
 
@@ -3863,6 +319,185 @@ var SourcePoller = class {
3863
319
  }
3864
320
  };
3865
321
 
322
+ // ../gateway-server/src/connector-manager.ts
323
+ var ConnectorManager = class {
324
+ constructor(configStore, gateway) {
325
+ this.configStore = configStore;
326
+ this.gateway = gateway;
327
+ }
328
+ adapters = /* @__PURE__ */ new Map();
329
+ pollers = /* @__PURE__ */ new Map();
330
+ /**
331
+ * Register a connector from raw JSON body.
332
+ *
333
+ * Validates via shared handler, creates adapter/poller as appropriate,
334
+ * registers with the gateway.
335
+ */
336
+ async register(raw) {
337
+ const result = await handleRegisterConnector(raw, this.configStore);
338
+ if (result.status !== 200) {
339
+ return result;
340
+ }
341
+ const connectors = await this.configStore.getConnectors();
342
+ const registeredName = result.body.name;
343
+ const config = connectors[registeredName];
344
+ if (!config) {
345
+ return result;
346
+ }
347
+ if (config.type === "jira") {
348
+ try {
349
+ const { JiraSourcePoller } = await import("./src-ZRHKG42A.js");
350
+ const ingestConfig = config.ingest ? { intervalMs: config.ingest.intervalMs } : void 0;
351
+ const poller = new JiraSourcePoller(config.jira, ingestConfig, config.name, this.gateway);
352
+ poller.start();
353
+ this.pollers.set(config.name, poller);
354
+ return result;
355
+ } catch (err) {
356
+ await this.rollbackRegistration(connectors, registeredName);
357
+ const message = err instanceof Error ? err.message : String(err);
358
+ return { status: 500, body: { error: `Failed to load Jira connector: ${message}` } };
359
+ }
360
+ }
361
+ if (config.type === "salesforce") {
362
+ try {
363
+ const { SalesforceSourcePoller } = await import("./src-B6NLV3FP.js");
364
+ const ingestConfig = config.ingest ? { intervalMs: config.ingest.intervalMs } : void 0;
365
+ const poller = new SalesforceSourcePoller(
366
+ config.salesforce,
367
+ ingestConfig,
368
+ config.name,
369
+ this.gateway
370
+ );
371
+ poller.start();
372
+ this.pollers.set(config.name, poller);
373
+ return result;
374
+ } catch (err) {
375
+ await this.rollbackRegistration(connectors, registeredName);
376
+ const message = err instanceof Error ? err.message : String(err);
377
+ return {
378
+ status: 500,
379
+ body: { error: `Failed to load Salesforce connector: ${message}` }
380
+ };
381
+ }
382
+ }
383
+ const adapterResult = createDatabaseAdapter(config);
384
+ if (!adapterResult.ok) {
385
+ await this.rollbackRegistration(connectors, registeredName);
386
+ return { status: 500, body: { error: adapterResult.error.message } };
387
+ }
388
+ const adapter = adapterResult.value;
389
+ this.gateway.registerSource(config.name, adapter);
390
+ this.adapters.set(config.name, adapter);
391
+ if (isActionHandler(adapter)) {
392
+ this.gateway.registerActionHandler(config.name, adapter);
393
+ }
394
+ if (config.ingest) {
395
+ const queryFn = await createQueryFn(config);
396
+ if (queryFn) {
397
+ const pollerConfig = {
398
+ name: config.name,
399
+ queryFn,
400
+ tables: config.ingest.tables.map((t) => ({
401
+ table: t.table,
402
+ query: t.query,
403
+ rowIdColumn: t.rowIdColumn,
404
+ strategy: t.strategy
405
+ })),
406
+ intervalMs: config.ingest.intervalMs
407
+ };
408
+ const poller = new SourcePoller(pollerConfig, this.gateway);
409
+ poller.start();
410
+ this.pollers.set(config.name, poller);
411
+ }
412
+ }
413
+ return result;
414
+ }
415
+ /**
416
+ * Unregister a connector by name.
417
+ *
418
+ * Stops poller, closes adapter, and unregisters from gateway.
419
+ */
420
+ async unregister(name) {
421
+ const result = await handleUnregisterConnector(name, this.configStore);
422
+ if (result.status !== 200) {
423
+ return result;
424
+ }
425
+ const poller = this.pollers.get(name);
426
+ if (poller) {
427
+ poller.stop();
428
+ this.pollers.delete(name);
429
+ }
430
+ const adapter = this.adapters.get(name);
431
+ if (adapter) {
432
+ await adapter.close();
433
+ this.adapters.delete(name);
434
+ }
435
+ this.gateway.unregisterSource(name);
436
+ this.gateway.unregisterActionHandler(name);
437
+ return result;
438
+ }
439
+ /**
440
+ * List registered connectors with live polling status.
441
+ */
442
+ async list() {
443
+ const result = await handleListConnectors(this.configStore);
444
+ if (result.status !== 200) {
445
+ return result;
446
+ }
447
+ const list = result.body;
448
+ const augmented = list.map((c) => ({
449
+ ...c,
450
+ isPolling: this.pollers.get(c.name)?.isRunning ?? false
451
+ }));
452
+ return { status: 200, body: augmented };
453
+ }
454
+ /** Stop all pollers and close all adapters. */
455
+ async stopAll() {
456
+ for (const [, poller] of this.pollers) {
457
+ poller.stop();
458
+ }
459
+ this.pollers.clear();
460
+ for (const [, adapter] of this.adapters) {
461
+ await adapter.close();
462
+ }
463
+ this.adapters.clear();
464
+ }
465
+ // -----------------------------------------------------------------------
466
+ // Internal helpers
467
+ // -----------------------------------------------------------------------
468
+ async rollbackRegistration(connectors, name) {
469
+ delete connectors[name];
470
+ await this.configStore.setConnectors(connectors);
471
+ }
472
+ };
473
+
474
+ // ../gateway-server/src/cors-middleware.ts
475
+ function corsHeaders(origin, config) {
476
+ const { allowedOrigins } = config;
477
+ let allowOrigin = "*";
478
+ if (allowedOrigins && allowedOrigins.length > 0) {
479
+ if (origin && allowedOrigins.includes(origin)) {
480
+ allowOrigin = origin;
481
+ } else {
482
+ return {};
483
+ }
484
+ } else if (origin) {
485
+ allowOrigin = origin;
486
+ }
487
+ return {
488
+ "Access-Control-Allow-Origin": allowOrigin,
489
+ "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
490
+ "Access-Control-Allow-Headers": "Authorization, Content-Type",
491
+ "Access-Control-Max-Age": "86400"
492
+ };
493
+ }
494
+ function handlePreflight(method, res, corsH) {
495
+ if (method !== "OPTIONS") return false;
496
+ res.writeHead(204, corsH);
497
+ res.end();
498
+ return true;
499
+ }
500
+
3866
501
  // ../gateway-server/src/persistence.ts
3867
502
  var MemoryPersistence = class {
3868
503
  buffer = [];
@@ -3910,16 +545,38 @@ var SqlitePersistence = class {
3910
545
  }
3911
546
  };
3912
547
 
548
+ // ../gateway-server/src/router.ts
549
+ var ROUTES = [
550
+ ["POST", /^\/sync\/([^/]+)\/push$/, "push"],
551
+ ["GET", /^\/sync\/([^/]+)\/pull$/, "pull"],
552
+ ["POST", /^\/sync\/([^/]+)\/action$/, "action"],
553
+ ["GET", /^\/sync\/([^/]+)\/actions$/, "describe-actions"],
554
+ ["GET", /^\/sync\/([^/]+)\/ws$/, "ws"],
555
+ ["POST", /^\/admin\/flush\/([^/]+)$/, "flush"],
556
+ ["POST", /^\/admin\/schema\/([^/]+)$/, "schema"],
557
+ ["POST", /^\/admin\/sync-rules\/([^/]+)$/, "sync-rules"],
558
+ ["POST", /^\/admin\/connectors\/([^/]+)$/, "register-connector"],
559
+ ["GET", /^\/admin\/connectors\/([^/]+)$/, "list-connectors"],
560
+ ["DELETE", /^\/admin\/connectors\/([^/]+)\/([^/]+)$/, "unregister-connector", true],
561
+ ["GET", /^\/admin\/metrics\/([^/]+)$/, "metrics"]
562
+ ];
563
+ function matchRoute(pathname, method) {
564
+ for (const [m, pattern, action, hasConnector] of ROUTES) {
565
+ if (method !== m) continue;
566
+ const match = pathname.match(pattern);
567
+ if (!match) continue;
568
+ return {
569
+ gatewayId: match[1],
570
+ action,
571
+ ...hasConnector ? { connectorName: match[2] } : {}
572
+ };
573
+ }
574
+ return null;
575
+ }
576
+
3913
577
  // ../gateway-server/src/server.ts
3914
578
  import { createServer } from "http";
3915
579
 
3916
- // ../../node_modules/.bun/ws@8.18.0/node_modules/ws/wrapper.mjs
3917
- var import_stream = __toESM(require_stream(), 1);
3918
- var import_receiver = __toESM(require_receiver(), 1);
3919
- var import_sender = __toESM(require_sender(), 1);
3920
- var import_websocket = __toESM(require_websocket(), 1);
3921
- var import_websocket_server = __toESM(require_websocket_server(), 1);
3922
-
3923
580
  // ../gateway-server/src/shared-buffer.ts
3924
581
  var SharedBuffer = class {
3925
582
  constructor(sharedAdapter) {
@@ -3963,167 +620,62 @@ var SharedBuffer = class {
3963
620
  } catch {
3964
621
  return localResult;
3965
622
  }
3966
- }
3967
- };
3968
-
3969
- // ../gateway-server/src/server.ts
3970
- var DEFAULT_PORT = 3e3;
3971
- var DEFAULT_FLUSH_INTERVAL_MS = 3e4;
3972
- var ADMIN_ACTIONS = /* @__PURE__ */ new Set([
3973
- "flush",
3974
- "schema",
3975
- "sync-rules",
3976
- "register-connector",
3977
- "unregister-connector",
3978
- "list-connectors",
3979
- "metrics"
3980
- ]);
3981
- var ROUTES = [
3982
- ["POST", /^\/sync\/([^/]+)\/push$/, "push"],
3983
- ["GET", /^\/sync\/([^/]+)\/pull$/, "pull"],
3984
- ["POST", /^\/sync\/([^/]+)\/action$/, "action"],
3985
- ["GET", /^\/sync\/([^/]+)\/actions$/, "describe-actions"],
3986
- ["GET", /^\/sync\/([^/]+)\/ws$/, "ws"],
3987
- ["POST", /^\/admin\/flush\/([^/]+)$/, "flush"],
3988
- ["POST", /^\/admin\/schema\/([^/]+)$/, "schema"],
3989
- ["POST", /^\/admin\/sync-rules\/([^/]+)$/, "sync-rules"],
3990
- ["POST", /^\/admin\/connectors\/([^/]+)$/, "register-connector"],
3991
- ["GET", /^\/admin\/connectors\/([^/]+)$/, "list-connectors"],
3992
- ["DELETE", /^\/admin\/connectors\/([^/]+)\/([^/]+)$/, "unregister-connector", true],
3993
- ["GET", /^\/admin\/metrics\/([^/]+)$/, "metrics"]
3994
- ];
3995
- function matchRoute(pathname, method) {
3996
- for (const [m, pattern, action, hasConnector] of ROUTES) {
3997
- if (method !== m) continue;
3998
- const match = pathname.match(pattern);
3999
- if (!match) continue;
4000
- return {
4001
- gatewayId: match[1],
4002
- action,
4003
- ...hasConnector ? { connectorName: match[2] } : {}
4004
- };
4005
- }
4006
- return null;
4007
- }
4008
- function readBody(req) {
4009
- return new Promise((resolve, reject) => {
4010
- const chunks = [];
4011
- req.on("data", (chunk) => chunks.push(chunk));
4012
- req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
4013
- req.on("error", reject);
4014
- });
4015
- }
4016
- function sendJson(res, body, status = 200, extraHeaders) {
4017
- const json = JSON.stringify(body, bigintReplacer);
4018
- res.writeHead(status, {
4019
- "Content-Type": "application/json",
4020
- ...extraHeaders
4021
- });
4022
- res.end(json);
4023
- }
4024
- function sendError(res, message, status, extraHeaders) {
4025
- sendJson(res, { error: message }, status, extraHeaders);
4026
- }
4027
- function sendResult(res, result, corsH) {
4028
- sendJson(res, result.body, result.status, corsH);
4029
- }
4030
- var GatewayServer = class {
4031
- gateway;
4032
- config;
4033
- httpServer = null;
4034
- flushTimer = null;
4035
- configStore;
4036
- persistence;
4037
- resolvedPort = 0;
4038
- wss = null;
4039
- wsClients = /* @__PURE__ */ new Map();
4040
- pollers = [];
4041
- connectorAdapters = /* @__PURE__ */ new Map();
4042
- connectorPollers = /* @__PURE__ */ new Map();
4043
- sharedBuffer = null;
4044
- constructor(config) {
4045
- this.config = {
4046
- port: config.port ?? DEFAULT_PORT,
4047
- flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,
4048
- ...config
4049
- };
4050
- this.gateway = new SyncGateway(
4051
- {
4052
- gatewayId: config.gatewayId,
4053
- maxBufferBytes: config.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES,
4054
- maxBufferAgeMs: config.maxBufferAgeMs ?? DEFAULT_MAX_BUFFER_AGE_MS
4055
- },
4056
- config.adapter
4057
- );
4058
- this.configStore = new MemoryConfigStore();
4059
- this.persistence = config.persistence === "sqlite" ? new SqlitePersistence(config.sqlitePath ?? "./lakesync-buffer.sqlite") : new MemoryPersistence();
4060
- if (config.cluster) {
4061
- this.sharedBuffer = new SharedBuffer(config.cluster.sharedAdapter);
4062
- }
4063
- }
4064
- /**
4065
- * Start the HTTP server and periodic flush timer.
4066
- *
4067
- * Rehydrates unflushed deltas from the persistence layer before
4068
- * accepting connections.
4069
- */
4070
- async start() {
4071
- const persisted = this.persistence.loadAll();
4072
- if (persisted.length > 0) {
4073
- const push = {
4074
- clientId: "__rehydrate__",
4075
- deltas: persisted,
4076
- lastSeenHlc: 0n
4077
- };
4078
- this.gateway.handlePush(push);
4079
- this.persistence.clear();
4080
- }
4081
- this.httpServer = createServer((req, res) => {
4082
- this.handleRequest(req, res);
4083
- });
4084
- await new Promise((resolve) => {
4085
- this.httpServer.listen(this.config.port, () => {
4086
- const addr = this.httpServer.address();
4087
- if (addr && typeof addr === "object") {
4088
- this.resolvedPort = addr.port;
4089
- }
4090
- resolve();
4091
- });
4092
- });
4093
- this.wss = new import_websocket_server.default({ noServer: true });
4094
- this.httpServer.on("upgrade", (req, socket, head) => {
623
+ }
624
+ };
625
+
626
+ // ../gateway-server/src/ws-manager.ts
627
+ import { WebSocketServer } from "ws";
628
+ var WebSocketManager = class {
629
+ constructor(gateway, configStore, gatewayId, jwtSecret) {
630
+ this.gateway = gateway;
631
+ this.configStore = configStore;
632
+ this.gatewayId = gatewayId;
633
+ this.jwtSecret = jwtSecret;
634
+ this.wss = new WebSocketServer({ noServer: true });
635
+ }
636
+ wss;
637
+ clients = /* @__PURE__ */ new Map();
638
+ /** Attach upgrade listener to an HTTP server. */
639
+ attach(httpServer) {
640
+ httpServer.on("upgrade", (req, socket, head) => {
4095
641
  void this.handleUpgrade(req, socket, head);
4096
642
  });
4097
- this.flushTimer = setInterval(() => {
4098
- this.periodicFlush();
4099
- }, this.config.flushIntervalMs);
4100
- if (this.config.ingestSources) {
4101
- for (const source of this.config.ingestSources) {
4102
- const poller = new SourcePoller(source, this.gateway);
4103
- poller.start();
4104
- this.pollers.push(poller);
4105
- }
4106
- }
4107
643
  }
4108
644
  /**
4109
- * Handle HTTP -> WebSocket upgrade.
4110
- *
4111
- * Authenticates via Bearer token in Authorization header or `?token=` query param.
645
+ * Broadcast ingested deltas to all connected WebSocket clients except the sender.
4112
646
  */
647
+ broadcastDeltas(deltas, serverHlc, excludeClientId) {
648
+ if (deltas.length === 0) return;
649
+ void this.broadcastDeltasAsync(deltas, serverHlc, excludeClientId);
650
+ }
651
+ /** Close all connections and shut down the WebSocket server. */
652
+ close() {
653
+ for (const ws of this.clients.keys()) {
654
+ try {
655
+ ws.close(1001, "Server shutting down");
656
+ } catch {
657
+ }
658
+ }
659
+ this.clients.clear();
660
+ this.wss.close();
661
+ }
662
+ // -----------------------------------------------------------------------
663
+ // Upgrade handling
664
+ // -----------------------------------------------------------------------
4113
665
  async handleUpgrade(req, socket, head) {
4114
666
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
4115
667
  let token = extractBearerToken(req);
4116
668
  if (!token) {
4117
669
  token = url.searchParams.get("token");
4118
670
  }
4119
- if (!token && this.config.jwtSecret) {
671
+ if (!token && this.jwtSecret) {
4120
672
  socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
4121
673
  socket.destroy();
4122
674
  return;
4123
675
  }
4124
676
  let auth;
4125
- if (this.config.jwtSecret && token) {
4126
- const authResult = await verifyToken(token, this.config.jwtSecret);
677
+ if (this.jwtSecret && token) {
678
+ const authResult = await verifyToken(token, this.jwtSecret);
4127
679
  if (!authResult.ok) {
4128
680
  socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
4129
681
  socket.destroy();
@@ -4140,22 +692,22 @@ var GatewayServer = class {
4140
692
  this.wss.handleUpgrade(req, socket, head, (ws) => {
4141
693
  const clientId = auth?.clientId ?? `anon-${crypto.randomUUID()}`;
4142
694
  const claims = auth?.customClaims ?? {};
4143
- this.wsClients.set(ws, { clientId, claims });
695
+ this.clients.set(ws, { clientId, claims });
4144
696
  ws.on("message", (data) => {
4145
- void this.handleWsMessage(ws, data, clientId, claims);
697
+ void this.handleMessage(ws, data, clientId, claims);
4146
698
  });
4147
699
  ws.on("close", () => {
4148
- this.wsClients.delete(ws);
700
+ this.clients.delete(ws);
4149
701
  });
4150
702
  ws.on("error", () => {
4151
- this.wsClients.delete(ws);
703
+ this.clients.delete(ws);
4152
704
  });
4153
705
  });
4154
706
  }
4155
- /**
4156
- * Handle an incoming WebSocket message (binary protobuf).
4157
- */
4158
- async handleWsMessage(ws, data, clientId, claims) {
707
+ // -----------------------------------------------------------------------
708
+ // Message handling
709
+ // -----------------------------------------------------------------------
710
+ async handleMessage(ws, data, clientId, claims) {
4159
711
  const bytes = new Uint8Array(data);
4160
712
  if (bytes.length < 2) {
4161
713
  ws.close(1002, "Message too short");
@@ -4189,7 +741,7 @@ var GatewayServer = class {
4189
741
  ws.close(1008, decoded.error.message);
4190
742
  return;
4191
743
  }
4192
- const context = await this.buildWsSyncRulesContext(claims);
744
+ const context = await this.buildSyncRulesContext(claims);
4193
745
  const pullResult = this.gateway.handlePull(
4194
746
  decoded.value,
4195
747
  context
@@ -4206,26 +758,22 @@ var GatewayServer = class {
4206
758
  ws.close(1002, `Unknown message tag: 0x${tag.toString(16).padStart(2, "0")}`);
4207
759
  }
4208
760
  }
4209
- /**
4210
- * Build sync rules context from WebSocket client claims.
4211
- */
4212
- async buildWsSyncRulesContext(claims) {
4213
- const rules = await this.configStore.getSyncRules(this.config.gatewayId);
761
+ // -----------------------------------------------------------------------
762
+ // Sync rules
763
+ // -----------------------------------------------------------------------
764
+ async buildSyncRulesContext(claims) {
765
+ const rules = await this.configStore.getSyncRules(this.gatewayId);
4214
766
  if (!rules || rules.buckets.length === 0) {
4215
767
  return void 0;
4216
768
  }
4217
769
  return { claims, rules };
4218
770
  }
4219
- /**
4220
- * Broadcast ingested deltas to all connected WebSocket clients except the sender.
4221
- */
4222
- broadcastDeltas(deltas, serverHlc, excludeClientId) {
4223
- if (deltas.length === 0) return;
4224
- void this.broadcastDeltasAsync(deltas, serverHlc, excludeClientId);
4225
- }
771
+ // -----------------------------------------------------------------------
772
+ // Broadcast
773
+ // -----------------------------------------------------------------------
4226
774
  async broadcastDeltasAsync(deltas, serverHlc, excludeClientId) {
4227
- const rules = await this.configStore.getSyncRules(this.config.gatewayId);
4228
- for (const [ws, meta] of this.wsClients) {
775
+ const rules = await this.configStore.getSyncRules(this.gatewayId);
776
+ for (const [ws, meta] of this.clients) {
4229
777
  if (meta.clientId === excludeClientId) continue;
4230
778
  try {
4231
779
  let filtered = deltas;
@@ -4248,16 +796,112 @@ var GatewayServer = class {
4248
796
  }
4249
797
  }
4250
798
  }
4251
- /** Stop the server and clear the flush timer. */
4252
- async stop() {
4253
- for (const [, poller] of this.connectorPollers) {
4254
- poller.stop();
799
+ };
800
+
801
+ // ../gateway-server/src/server.ts
802
+ var DEFAULT_PORT = 3e3;
803
+ var DEFAULT_FLUSH_INTERVAL_MS = 3e4;
804
+ function readBody(req) {
805
+ return new Promise((resolve, reject) => {
806
+ const chunks = [];
807
+ req.on("data", (chunk) => chunks.push(chunk));
808
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
809
+ req.on("error", reject);
810
+ });
811
+ }
812
+ function sendJson(res, body, status = 200, extraHeaders) {
813
+ const json = JSON.stringify(body, bigintReplacer);
814
+ res.writeHead(status, {
815
+ "Content-Type": "application/json",
816
+ ...extraHeaders
817
+ });
818
+ res.end(json);
819
+ }
820
+ function sendError(res, message, status, extraHeaders) {
821
+ sendJson(res, { error: message }, status, extraHeaders);
822
+ }
823
+ function sendResult(res, result, corsH) {
824
+ sendJson(res, result.body, result.status, corsH);
825
+ }
826
+ var GatewayServer = class {
827
+ gateway;
828
+ config;
829
+ configStore;
830
+ persistence;
831
+ connectors;
832
+ sharedBuffer;
833
+ httpServer = null;
834
+ wsManager = null;
835
+ flushTimer = null;
836
+ resolvedPort = 0;
837
+ pollers = [];
838
+ constructor(config) {
839
+ this.config = {
840
+ port: config.port ?? DEFAULT_PORT,
841
+ flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,
842
+ ...config
843
+ };
844
+ this.gateway = new SyncGateway(
845
+ {
846
+ gatewayId: config.gatewayId,
847
+ maxBufferBytes: config.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES,
848
+ maxBufferAgeMs: config.maxBufferAgeMs ?? DEFAULT_MAX_BUFFER_AGE_MS
849
+ },
850
+ config.adapter
851
+ );
852
+ this.configStore = new MemoryConfigStore();
853
+ this.persistence = config.persistence === "sqlite" ? new SqlitePersistence(config.sqlitePath ?? "./lakesync-buffer.sqlite") : new MemoryPersistence();
854
+ this.sharedBuffer = config.cluster ? new SharedBuffer(config.cluster.sharedAdapter) : null;
855
+ this.connectors = new ConnectorManager(this.configStore, this.gateway);
856
+ }
857
+ /**
858
+ * Start the HTTP server and periodic flush timer.
859
+ *
860
+ * Rehydrates unflushed deltas from the persistence layer directly
861
+ * into the buffer (bypassing push validation) before accepting
862
+ * connections.
863
+ */
864
+ async start() {
865
+ const persisted = this.persistence.loadAll();
866
+ if (persisted.length > 0) {
867
+ for (const delta of persisted) {
868
+ this.gateway.buffer.append(delta);
869
+ }
870
+ this.persistence.clear();
4255
871
  }
4256
- this.connectorPollers.clear();
4257
- for (const [, adapter] of this.connectorAdapters) {
4258
- await adapter.close();
872
+ this.httpServer = createServer((req, res) => {
873
+ void this.handleRequest(req, res);
874
+ });
875
+ await new Promise((resolve) => {
876
+ this.httpServer.listen(this.config.port, () => {
877
+ const addr = this.httpServer.address();
878
+ if (addr && typeof addr === "object") {
879
+ this.resolvedPort = addr.port;
880
+ }
881
+ resolve();
882
+ });
883
+ });
884
+ this.wsManager = new WebSocketManager(
885
+ this.gateway,
886
+ this.configStore,
887
+ this.config.gatewayId,
888
+ this.config.jwtSecret
889
+ );
890
+ this.wsManager.attach(this.httpServer);
891
+ this.flushTimer = setInterval(() => {
892
+ void this.periodicFlush();
893
+ }, this.config.flushIntervalMs);
894
+ if (this.config.ingestSources) {
895
+ for (const source of this.config.ingestSources) {
896
+ const poller = new SourcePoller(source, this.gateway);
897
+ poller.start();
898
+ this.pollers.push(poller);
899
+ }
4259
900
  }
4260
- this.connectorAdapters.clear();
901
+ }
902
+ /** Stop the server, pollers, connectors, and WebSocket connections. */
903
+ async stop() {
904
+ await this.connectors.stopAll();
4261
905
  for (const poller of this.pollers) {
4262
906
  poller.stop();
4263
907
  }
@@ -4266,16 +910,9 @@ var GatewayServer = class {
4266
910
  clearInterval(this.flushTimer);
4267
911
  this.flushTimer = null;
4268
912
  }
4269
- if (this.wss) {
4270
- for (const ws of this.wsClients.keys()) {
4271
- try {
4272
- ws.close(1001, "Server shutting down");
4273
- } catch {
4274
- }
4275
- }
4276
- this.wsClients.clear();
4277
- this.wss.close();
4278
- this.wss = null;
913
+ if (this.wsManager) {
914
+ this.wsManager.close();
915
+ this.wsManager = null;
4279
916
  }
4280
917
  if (this.httpServer) {
4281
918
  await new Promise((resolve) => {
@@ -4294,7 +931,7 @@ var GatewayServer = class {
4294
931
  return this.gateway;
4295
932
  }
4296
933
  // -----------------------------------------------------------------------
4297
- // Request handling
934
+ // Request handling — cors -> auth -> route -> handler
4298
935
  // -----------------------------------------------------------------------
4299
936
  async handleRequest(req, res) {
4300
937
  const method = req.method ?? "GET";
@@ -4302,12 +939,8 @@ var GatewayServer = class {
4302
939
  const url = new URL(rawUrl, `http://${req.headers.host ?? "localhost"}`);
4303
940
  const pathname = url.pathname;
4304
941
  const origin = req.headers.origin ?? null;
4305
- const corsH = this.corsHeaders(origin);
4306
- if (method === "OPTIONS") {
4307
- res.writeHead(204, corsH);
4308
- res.end();
4309
- return;
4310
- }
942
+ const corsH = corsHeaders(origin, { allowedOrigins: this.config.allowedOrigins });
943
+ if (handlePreflight(method, res, corsH)) return;
4311
944
  if (pathname === "/health" && method === "GET") {
4312
945
  sendJson(res, { status: "ok" }, 200, corsH);
4313
946
  return;
@@ -4326,28 +959,17 @@ var GatewayServer = class {
4326
959
  sendError(res, "Gateway ID mismatch", 404, corsH);
4327
960
  return;
4328
961
  }
4329
- let auth;
4330
- if (this.config.jwtSecret) {
4331
- const token = extractBearerToken(req);
4332
- if (!token) {
4333
- sendError(res, "Missing Bearer token", 401, corsH);
4334
- return;
4335
- }
4336
- const authResult = await verifyToken(token, this.config.jwtSecret);
4337
- if (!authResult.ok) {
4338
- sendError(res, authResult.error.message, 401, corsH);
4339
- return;
4340
- }
4341
- auth = authResult.value;
4342
- if (auth.gatewayId !== route.gatewayId) {
4343
- sendError(res, "Gateway ID mismatch: JWT authorises a different gateway", 403, corsH);
4344
- return;
4345
- }
4346
- if (ADMIN_ACTIONS.has(route.action) && auth.role !== "admin") {
4347
- sendError(res, "Admin role required", 403, corsH);
4348
- return;
4349
- }
962
+ const authResult = await authenticateRequest(
963
+ req,
964
+ route.gatewayId,
965
+ route.action,
966
+ this.config.jwtSecret
967
+ );
968
+ if (!authResult.authenticated) {
969
+ sendError(res, authResult.message, authResult.status, corsH);
970
+ return;
4350
971
  }
972
+ const auth = this.config.jwtSecret ? authResult.claims : void 0;
4351
973
  switch (route.action) {
4352
974
  case "push":
4353
975
  await this.handlePush(req, res, corsH, auth);
@@ -4371,10 +993,10 @@ var GatewayServer = class {
4371
993
  await this.handleSaveSyncRulesRoute(req, res, corsH);
4372
994
  break;
4373
995
  case "register-connector":
4374
- await this.handleRegisterConnector(req, res, corsH);
996
+ await this.handleRegisterConnectorRoute(req, res, corsH);
4375
997
  break;
4376
998
  case "unregister-connector":
4377
- await this.handleUnregisterConnector(route.connectorName, res, corsH);
999
+ await this.handleUnregisterConnectorRoute(route.connectorName, res, corsH);
4378
1000
  break;
4379
1001
  case "list-connectors":
4380
1002
  await this.handleListConnectorsRoute(res, corsH);
@@ -4387,11 +1009,8 @@ var GatewayServer = class {
4387
1009
  }
4388
1010
  }
4389
1011
  // -----------------------------------------------------------------------
4390
- // Route handlers — thin wrappers around shared request handlers
1012
+ // Route handlers — thin wrappers delegating to shared handlers or modules
4391
1013
  // -----------------------------------------------------------------------
4392
- /**
4393
- * Handle `POST /sync/:gatewayId/push` -- ingest client deltas.
4394
- */
4395
1014
  async handlePush(req, res, corsH, auth) {
4396
1015
  const contentLength = Number(req.headers["content-length"] ?? "0");
4397
1016
  if (contentLength > MAX_PUSH_PAYLOAD_BYTES) {
@@ -4402,7 +1021,7 @@ var GatewayServer = class {
4402
1021
  const result = handlePushRequest(this.gateway, raw, auth?.clientId, {
4403
1022
  persistBatch: (deltas) => this.persistence.appendBatch(deltas),
4404
1023
  clearPersistence: () => this.persistence.clear(),
4405
- broadcastFn: (deltas, serverHlc, excludeClientId) => this.broadcastDeltas(deltas, serverHlc, excludeClientId)
1024
+ broadcastFn: (deltas, serverHlc, excludeClientId) => this.wsManager?.broadcastDeltas(deltas, serverHlc, excludeClientId)
4406
1025
  });
4407
1026
  if (result.status === 200 && this.sharedBuffer) {
4408
1027
  const pushResult = result.body;
@@ -4412,9 +1031,6 @@ var GatewayServer = class {
4412
1031
  }
4413
1032
  sendResult(res, result, corsH);
4414
1033
  }
4415
- /**
4416
- * Handle `GET /sync/:gatewayId/pull` -- retrieve deltas since a given HLC.
4417
- */
4418
1034
  async handlePull(url, res, corsH, auth) {
4419
1035
  const syncRules = await this.configStore.getSyncRules(this.config.gatewayId);
4420
1036
  const result = await handlePullRequest(
@@ -4441,162 +1057,46 @@ var GatewayServer = class {
4441
1057
  }
4442
1058
  sendJson(res, body, result.status, corsH);
4443
1059
  }
4444
- /**
4445
- * Handle `POST /sync/:gatewayId/action` -- execute imperative actions.
4446
- */
4447
1060
  async handleAction(req, res, corsH, auth) {
4448
1061
  const raw = await readBody(req);
4449
1062
  const result = await handleActionRequest(this.gateway, raw, auth?.clientId, auth?.customClaims);
4450
1063
  sendResult(res, result, corsH);
4451
1064
  }
4452
- /** Handle `GET /sync/:gatewayId/actions` -- describe available action handlers. */
4453
1065
  handleDescribeActions(res, corsH) {
4454
1066
  sendJson(res, this.gateway.describeActions(), 200, corsH);
4455
1067
  }
4456
- /** Handle `POST /admin/flush/:gatewayId` -- manual flush. */
4457
1068
  async handleFlush(res, corsH) {
4458
1069
  const result = await handleFlushRequest(this.gateway, {
4459
1070
  clearPersistence: () => this.persistence.clear()
4460
1071
  });
4461
1072
  sendResult(res, result, corsH);
4462
1073
  }
4463
- /** Handle `POST /admin/schema/:gatewayId` -- save table schema. */
4464
1074
  async handleSaveSchemaRoute(req, res, corsH) {
4465
1075
  const raw = await readBody(req);
4466
1076
  const result = await handleSaveSchema(raw, this.configStore, this.config.gatewayId);
4467
1077
  sendResult(res, result, corsH);
4468
1078
  }
4469
- /** Handle `POST /admin/sync-rules/:gatewayId` -- save sync rules. */
4470
1079
  async handleSaveSyncRulesRoute(req, res, corsH) {
4471
1080
  const raw = await readBody(req);
4472
1081
  const result = await handleSaveSyncRules(raw, this.configStore, this.config.gatewayId);
4473
1082
  sendResult(res, result, corsH);
4474
1083
  }
4475
1084
  // -----------------------------------------------------------------------
4476
- // Connector management
1085
+ // Connector management — delegates to ConnectorManager
4477
1086
  // -----------------------------------------------------------------------
4478
- /** Handle `POST /admin/connectors/:gatewayId` -- register a new connector. */
4479
- async handleRegisterConnector(req, res, corsH) {
1087
+ async handleRegisterConnectorRoute(req, res, corsH) {
4480
1088
  const raw = await readBody(req);
4481
- const result = await handleRegisterConnector(raw, this.configStore);
4482
- if (result.status !== 200) {
4483
- sendResult(res, result, corsH);
4484
- return;
4485
- }
4486
- const connectors = await this.configStore.getConnectors();
4487
- const registeredName = result.body.name;
4488
- const config = connectors[registeredName];
4489
- if (!config) {
4490
- sendResult(res, result, corsH);
4491
- return;
4492
- }
4493
- if (config.type === "jira" && config.jira) {
4494
- try {
4495
- const { JiraSourcePoller } = await import("./src-V2CTPR7V.js");
4496
- const ingestConfig = config.ingest ? { intervalMs: config.ingest.intervalMs } : void 0;
4497
- const poller = new JiraSourcePoller(config.jira, ingestConfig, config.name, this.gateway);
4498
- poller.start();
4499
- this.connectorPollers.set(config.name, poller);
4500
- sendResult(res, result, corsH);
4501
- } catch (err) {
4502
- delete connectors[registeredName];
4503
- await this.configStore.setConnectors(connectors);
4504
- const message = err instanceof Error ? err.message : String(err);
4505
- sendError(res, `Failed to load Jira connector: ${message}`, 500, corsH);
4506
- }
4507
- return;
4508
- }
4509
- if (config.type === "salesforce" && config.salesforce) {
4510
- try {
4511
- const { SalesforceSourcePoller } = await import("./src-RR7I76OL.js");
4512
- const ingestConfig = config.ingest ? { intervalMs: config.ingest.intervalMs } : void 0;
4513
- const poller = new SalesforceSourcePoller(
4514
- config.salesforce,
4515
- ingestConfig,
4516
- config.name,
4517
- this.gateway
4518
- );
4519
- poller.start();
4520
- this.connectorPollers.set(config.name, poller);
4521
- sendResult(res, result, corsH);
4522
- } catch (err) {
4523
- delete connectors[registeredName];
4524
- await this.configStore.setConnectors(connectors);
4525
- const message = err instanceof Error ? err.message : String(err);
4526
- sendError(res, `Failed to load Salesforce connector: ${message}`, 500, corsH);
4527
- }
4528
- return;
4529
- }
4530
- const adapterResult = createDatabaseAdapter(config);
4531
- if (!adapterResult.ok) {
4532
- delete connectors[registeredName];
4533
- await this.configStore.setConnectors(connectors);
4534
- sendError(res, adapterResult.error.message, 500, corsH);
4535
- return;
4536
- }
4537
- const adapter = adapterResult.value;
4538
- this.gateway.registerSource(config.name, adapter);
4539
- this.connectorAdapters.set(config.name, adapter);
4540
- if (isActionHandler(adapter)) {
4541
- this.gateway.registerActionHandler(config.name, adapter);
4542
- }
4543
- if (config.ingest) {
4544
- const queryFn = await createQueryFn(config);
4545
- if (queryFn) {
4546
- const pollerConfig = {
4547
- name: config.name,
4548
- queryFn,
4549
- tables: config.ingest.tables.map((t) => ({
4550
- table: t.table,
4551
- query: t.query,
4552
- rowIdColumn: t.rowIdColumn,
4553
- strategy: t.strategy
4554
- })),
4555
- intervalMs: config.ingest.intervalMs
4556
- };
4557
- const poller = new SourcePoller(pollerConfig, this.gateway);
4558
- poller.start();
4559
- this.connectorPollers.set(config.name, poller);
4560
- }
4561
- }
1089
+ const result = await this.connectors.register(raw);
4562
1090
  sendResult(res, result, corsH);
4563
1091
  }
4564
- /** Handle `DELETE /admin/connectors/:gatewayId/:name` -- unregister a connector. */
4565
- async handleUnregisterConnector(name, res, corsH) {
4566
- const result = await handleUnregisterConnector(name, this.configStore);
4567
- if (result.status !== 200) {
4568
- sendResult(res, result, corsH);
4569
- return;
4570
- }
4571
- const poller = this.connectorPollers.get(name);
4572
- if (poller) {
4573
- poller.stop();
4574
- this.connectorPollers.delete(name);
4575
- }
4576
- const adapter = this.connectorAdapters.get(name);
4577
- if (adapter) {
4578
- await adapter.close();
4579
- this.connectorAdapters.delete(name);
4580
- }
4581
- this.gateway.unregisterSource(name);
4582
- this.gateway.unregisterActionHandler(name);
1092
+ async handleUnregisterConnectorRoute(name, res, corsH) {
1093
+ const result = await this.connectors.unregister(name);
4583
1094
  sendResult(res, result, corsH);
4584
1095
  }
4585
- /** Handle `GET /admin/connectors/:gatewayId` -- list registered connectors. */
4586
1096
  async handleListConnectorsRoute(res, corsH) {
4587
- const result = await handleListConnectors(this.configStore);
4588
- if (result.status !== 200) {
4589
- sendResult(res, result, corsH);
4590
- return;
4591
- }
4592
- const list = result.body;
4593
- const augmented = list.map((c) => ({
4594
- ...c,
4595
- isPolling: this.connectorPollers.get(c.name)?.isRunning ?? false
4596
- }));
4597
- sendJson(res, augmented, 200, corsH);
1097
+ const result = await this.connectors.list();
1098
+ sendJson(res, result.body, result.status, corsH);
4598
1099
  }
4599
- /** Handle `GET /admin/metrics/:gatewayId` -- return buffer stats and process memory. */
4600
1100
  handleMetricsRoute(res, corsH) {
4601
1101
  const result = handleMetrics(this.gateway, { process: process.memoryUsage() });
4602
1102
  sendResult(res, result, corsH);
@@ -4627,43 +1127,22 @@ var GatewayServer = class {
4627
1127
  }
4628
1128
  }
4629
1129
  }
4630
- // -----------------------------------------------------------------------
4631
- // CORS
4632
- // -----------------------------------------------------------------------
4633
- corsHeaders(origin) {
4634
- const allowedOrigins = this.config.allowedOrigins;
4635
- let allowOrigin = "*";
4636
- if (allowedOrigins && allowedOrigins.length > 0) {
4637
- if (origin && allowedOrigins.includes(origin)) {
4638
- allowOrigin = origin;
4639
- } else {
4640
- return {};
4641
- }
4642
- } else if (origin) {
4643
- allowOrigin = origin;
4644
- }
4645
- return {
4646
- "Access-Control-Allow-Origin": allowOrigin,
4647
- "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
4648
- "Access-Control-Allow-Headers": "Authorization, Content-Type",
4649
- "Access-Control-Max-Age": "86400"
4650
- };
4651
- }
4652
1130
  };
4653
- function extractBearerToken(req) {
4654
- const header = req.headers.authorization;
4655
- if (!header) return null;
4656
- const match = header.match(/^Bearer\s+(\S+)$/);
4657
- return match?.[1] ?? null;
4658
- }
4659
1131
  export {
4660
1132
  AdapterBasedLock,
4661
1133
  AuthError,
1134
+ ConnectorManager,
4662
1135
  GatewayServer,
4663
1136
  MemoryPersistence,
4664
1137
  SharedBuffer,
4665
1138
  SourcePoller,
4666
1139
  SqlitePersistence,
1140
+ WebSocketManager,
1141
+ authenticateRequest,
1142
+ corsHeaders,
1143
+ extractBearerToken,
1144
+ handlePreflight,
1145
+ matchRoute,
4667
1146
  verifyToken
4668
1147
  };
4669
1148
  //# sourceMappingURL=gateway-server.js.map