@atproto/xrpc-server 0.4.2 → 0.4.4-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE.txt +1 -1
  3. package/dist/auth.d.ts +3 -2
  4. package/dist/auth.d.ts.map +1 -0
  5. package/dist/auth.js +124 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +25 -53377
  10. package/dist/index.js.map +1 -7
  11. package/dist/logger.d.ts +1 -0
  12. package/dist/logger.d.ts.map +1 -0
  13. package/dist/logger.js +7 -0
  14. package/dist/logger.js.map +1 -0
  15. package/dist/rate-limiter.d.ts +2 -1
  16. package/dist/rate-limiter.d.ts.map +1 -0
  17. package/dist/rate-limiter.js +166 -0
  18. package/dist/rate-limiter.js.map +1 -0
  19. package/dist/server.d.ts +6 -5
  20. package/dist/server.d.ts.map +1 -0
  21. package/dist/server.js +472 -0
  22. package/dist/server.js.map +1 -0
  23. package/dist/stream/frames.d.ts +2 -1
  24. package/dist/stream/frames.d.ts.map +1 -0
  25. package/dist/stream/frames.js +141 -0
  26. package/dist/stream/frames.js.map +1 -0
  27. package/dist/stream/index.d.ts +1 -0
  28. package/dist/stream/index.d.ts.map +1 -0
  29. package/dist/stream/index.js +22 -0
  30. package/dist/stream/index.js.map +1 -0
  31. package/dist/stream/logger.d.ts +1 -0
  32. package/dist/stream/logger.d.ts.map +1 -0
  33. package/dist/stream/logger.js +7 -0
  34. package/dist/stream/logger.js.map +1 -0
  35. package/dist/stream/server.d.ts +3 -1
  36. package/dist/stream/server.d.ts.map +1 -0
  37. package/dist/stream/server.js +70 -0
  38. package/dist/stream/server.js.map +1 -0
  39. package/dist/stream/stream.d.ts +1 -0
  40. package/dist/stream/stream.d.ts.map +1 -0
  41. package/dist/stream/stream.js +44 -0
  42. package/dist/stream/stream.js.map +1 -0
  43. package/dist/stream/subscription.d.ts +2 -0
  44. package/dist/stream/subscription.d.ts.map +1 -0
  45. package/dist/stream/subscription.js +80 -0
  46. package/dist/stream/subscription.js.map +1 -0
  47. package/dist/stream/types.d.ts +5 -4
  48. package/dist/stream/types.d.ts.map +1 -0
  49. package/dist/stream/types.js +47 -0
  50. package/dist/stream/types.js.map +1 -0
  51. package/dist/stream/websocket-keepalive.d.ts +2 -0
  52. package/dist/stream/websocket-keepalive.d.ts.map +1 -0
  53. package/dist/stream/websocket-keepalive.js +160 -0
  54. package/dist/stream/websocket-keepalive.js.map +1 -0
  55. package/dist/types.d.ts +54 -34
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +163 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/util.d.ts +3 -2
  60. package/dist/util.d.ts.map +1 -0
  61. package/dist/util.js +263 -0
  62. package/dist/util.js.map +1 -0
  63. package/jest.config.js +4 -3
  64. package/package.json +10 -11
  65. package/src/rate-limiter.ts +3 -0
  66. package/src/server.ts +53 -14
  67. package/src/stream/frames.ts +1 -1
  68. package/src/stream/websocket-keepalive.ts +2 -1
  69. package/src/types.ts +22 -10
  70. package/src/util.ts +3 -3
  71. package/tests/bodies.test.ts +4 -4
  72. package/tests/errors.test.ts +1 -1
  73. package/tsconfig.build.json +6 -2
  74. package/tsconfig.json +3 -11
  75. package/tsconfig.tests.json +7 -0
  76. package/babel.config.js +0 -1
  77. package/build.js +0 -14
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./frames"), exports);
19
+ __exportStar(require("./stream"), exports);
20
+ __exportStar(require("./subscription"), exports);
21
+ __exportStar(require("./server"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stream/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB;AACvB,2CAAwB;AACxB,2CAAwB;AACxB,iDAA8B;AAC9B,2CAAwB"}
@@ -1,3 +1,4 @@
1
1
  import { subsystemLogger } from '@atproto/common';
2
2
  export declare const logger: ReturnType<typeof subsystemLogger>;
3
3
  export default logger;
4
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/stream/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CACtB,CAAA;AAEhC,eAAe,MAAM,CAAA"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ const common_1 = require("@atproto/common");
5
+ exports.logger = (0, common_1.subsystemLogger)('xrpc-stream');
6
+ exports.default = exports.logger;
7
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/stream/logger.ts"],"names":[],"mappings":";;;AAAA,4CAAiD;AAEpC,QAAA,MAAM,GACjB,IAAA,wBAAe,EAAC,aAAa,CAAC,CAAA;AAEhC,kBAAe,cAAM,CAAA"}
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { IncomingMessage } from 'http';
3
4
  import { WebSocketServer, ServerOptions, WebSocket } from 'ws';
4
5
  import { Frame } from './frames';
@@ -8,4 +9,5 @@ export declare class XrpcStreamServer {
8
9
  handler: Handler;
9
10
  });
10
11
  }
11
- export declare type Handler = (req: IncomingMessage, signal: AbortSignal, socket: WebSocket, server: XrpcStreamServer) => AsyncIterable<Frame>;
12
+ export type Handler = (req: IncomingMessage, signal: AbortSignal, socket: WebSocket, server: XrpcStreamServer) => AsyncIterable<Frame>;
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AAC9D,OAAO,EAAc,KAAK,EAAE,MAAM,UAAU,CAAA;AAI5C,qBAAa,gBAAgB;IAC3B,GAAG,EAAE,eAAe,CAAA;gBACR,IAAI,EAAE,aAAa,GAAG;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE;CAqCvD;AAED,MAAM,MAAM,OAAO,GAAG,CACpB,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,gBAAgB,KACrB,aAAa,CAAC,KAAK,CAAC,CAAA"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.XrpcStreamServer = void 0;
7
+ const ws_1 = require("ws");
8
+ const frames_1 = require("./frames");
9
+ const logger_1 = __importDefault(require("./logger"));
10
+ const types_1 = require("./types");
11
+ class XrpcStreamServer {
12
+ constructor(opts) {
13
+ Object.defineProperty(this, "wss", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: void 0
18
+ });
19
+ const { handler, ...serverOpts } = opts;
20
+ this.wss = new ws_1.WebSocketServer(serverOpts);
21
+ this.wss.on('connection', async (socket, req) => {
22
+ socket.on('error', (err) => logger_1.default.error(err, 'websocket error'));
23
+ try {
24
+ const ac = new AbortController();
25
+ const iterator = unwrapIterator(handler(req, ac.signal, socket, this));
26
+ socket.once('close', () => {
27
+ iterator.return?.();
28
+ ac.abort();
29
+ });
30
+ const safeFrames = wrapIterator(iterator);
31
+ for await (const frame of safeFrames) {
32
+ await new Promise((res, rej) => {
33
+ socket.send(frame.toBytes(), { binary: true }, (err) => {
34
+ // @TODO this callback may give more aggressive on backpressure than
35
+ // we ultimately want, but trying it out for the time being.
36
+ if (err)
37
+ return rej(err);
38
+ res(undefined);
39
+ });
40
+ });
41
+ if (frame instanceof frames_1.ErrorFrame) {
42
+ throw new types_1.DisconnectError(types_1.CloseCode.Policy, frame.body.error);
43
+ }
44
+ }
45
+ }
46
+ catch (err) {
47
+ if (err instanceof types_1.DisconnectError) {
48
+ return socket.close(err.wsCode, err.xrpcCode);
49
+ }
50
+ else {
51
+ logger_1.default.error(err, 'websocket server error');
52
+ return socket.terminate();
53
+ }
54
+ }
55
+ socket.close(types_1.CloseCode.Normal);
56
+ });
57
+ }
58
+ }
59
+ exports.XrpcStreamServer = XrpcStreamServer;
60
+ function unwrapIterator(iterable) {
61
+ return iterable[Symbol.asyncIterator]();
62
+ }
63
+ function wrapIterator(iterator) {
64
+ return {
65
+ [Symbol.asyncIterator]() {
66
+ return iterator;
67
+ },
68
+ };
69
+ }
70
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":";;;;;;AACA,2BAA8D;AAC9D,qCAA4C;AAC5C,sDAA6B;AAC7B,mCAAoD;AAEpD,MAAa,gBAAgB;IAE3B,YAAY,IAA0C;QADtD;;;;;WAAoB;QAElB,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,IAAI,CAAA;QACvC,IAAI,CAAC,GAAG,GAAG,IAAI,oBAAe,CAAC,UAAU,CAAC,CAAA;QAC1C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;YAC9C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAM,CAAC,KAAK,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAA;YACjE,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAA;gBAChC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;gBACtE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;oBACxB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAA;oBACnB,EAAE,CAAC,KAAK,EAAE,CAAA;gBACZ,CAAC,CAAC,CAAA;gBACF,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;gBACzC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;wBAC7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;4BACrD,oEAAoE;4BACpE,4DAA4D;4BAC5D,IAAI,GAAG;gCAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAA;4BACxB,GAAG,CAAC,SAAS,CAAC,CAAA;wBAChB,CAAC,CAAC,CAAA;oBACJ,CAAC,CAAC,CAAA;oBACF,IAAI,KAAK,YAAY,mBAAU,EAAE,CAAC;wBAChC,MAAM,IAAI,uBAAe,CAAC,iBAAS,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;oBAC/D,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,uBAAe,EAAE,CAAC;oBACnC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;gBAC/C,CAAC;qBAAM,CAAC;oBACN,gBAAM,CAAC,KAAK,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAA;oBAC3C,OAAO,MAAM,CAAC,SAAS,EAAE,CAAA;gBAC3B,CAAC;YACH,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,iBAAS,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAvCD,4CAuCC;AASD,SAAS,cAAc,CAAI,QAA0B;IACnD,OAAO,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAA;AACzC,CAAC;AAED,SAAS,YAAY,CAAI,QAA0B;IACjD,OAAO;QACL,CAAC,MAAM,CAAC,aAAa,CAAC;YACpB,OAAO,QAAQ,CAAA;QACjB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -6,3 +6,4 @@ export declare function streamByteChunks(ws: WebSocket, options?: DuplexOptions)
6
6
  export declare function byFrame(ws: WebSocket, options?: DuplexOptions): AsyncGenerator<MessageFrame<unknown> | import("./frames").ErrorFrame<string>, void, unknown>;
7
7
  export declare function byMessage(ws: WebSocket, options?: DuplexOptions): AsyncGenerator<MessageFrame<unknown>, void, unknown>;
8
8
  export declare function ensureChunkIsMessage(chunk: Uint8Array): MessageFrame<unknown>;
9
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAyB,SAAS,EAAE,MAAM,IAAI,CAAA;AACrD,OAAO,EAAS,YAAY,EAAE,MAAM,UAAU,CAAA;AAE9C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,2BAKtE;AAED,wBAAuB,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,gGAKpE;AAED,wBAAuB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,wDAMtE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,CAW7E"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureChunkIsMessage = exports.byMessage = exports.byFrame = exports.streamByteChunks = void 0;
4
+ const xrpc_1 = require("@atproto/xrpc");
5
+ const ws_1 = require("ws");
6
+ const frames_1 = require("./frames");
7
+ function streamByteChunks(ws, options) {
8
+ return (0, ws_1.createWebSocketStream)(ws, {
9
+ ...options,
10
+ readableObjectMode: true, // Ensures frame bytes don't get buffered/combined together
11
+ });
12
+ }
13
+ exports.streamByteChunks = streamByteChunks;
14
+ async function* byFrame(ws, options) {
15
+ const wsStream = streamByteChunks(ws, options);
16
+ for await (const chunk of wsStream) {
17
+ yield frames_1.Frame.fromBytes(chunk);
18
+ }
19
+ }
20
+ exports.byFrame = byFrame;
21
+ async function* byMessage(ws, options) {
22
+ const wsStream = streamByteChunks(ws, options);
23
+ for await (const chunk of wsStream) {
24
+ const msg = ensureChunkIsMessage(chunk);
25
+ yield msg;
26
+ }
27
+ }
28
+ exports.byMessage = byMessage;
29
+ function ensureChunkIsMessage(chunk) {
30
+ const frame = frames_1.Frame.fromBytes(chunk);
31
+ if (frame.isMessage()) {
32
+ return frame;
33
+ }
34
+ else if (frame.isError()) {
35
+ // @TODO work -1 error code into XRPCError
36
+ // @ts-ignore
37
+ throw new xrpc_1.XRPCError(-1, frame.code, frame.message);
38
+ }
39
+ else {
40
+ throw new xrpc_1.XRPCError(xrpc_1.ResponseType.Unknown, undefined, 'Unknown frame type');
41
+ }
42
+ }
43
+ exports.ensureChunkIsMessage = ensureChunkIsMessage;
44
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":";;;AAAA,wCAAuD;AAEvD,2BAAqD;AACrD,qCAA8C;AAE9C,SAAgB,gBAAgB,CAAC,EAAa,EAAE,OAAuB;IACrE,OAAO,IAAA,0BAAqB,EAAC,EAAE,EAAE;QAC/B,GAAG,OAAO;QACV,kBAAkB,EAAE,IAAI,EAAE,2DAA2D;KACtF,CAAC,CAAA;AACJ,CAAC;AALD,4CAKC;AAEM,KAAK,SAAS,CAAC,CAAC,OAAO,CAAC,EAAa,EAAE,OAAuB;IACnE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAC9C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QACnC,MAAM,cAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC;AALD,0BAKC;AAEM,KAAK,SAAS,CAAC,CAAC,SAAS,CAAC,EAAa,EAAE,OAAuB;IACrE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAC9C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;QACvC,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC;AAND,8BAMC;AAED,SAAgB,oBAAoB,CAAC,KAAiB;IACpD,MAAM,KAAK,GAAG,cAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACpC,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACtB,OAAO,KAAK,CAAA;IACd,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3B,0CAA0C;QAC1C,aAAa;QACb,MAAM,IAAI,gBAAS,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACpD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,gBAAS,CAAC,mBAAY,CAAC,OAAO,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAA;IAC5E,CAAC;AACH,CAAC;AAXD,oDAWC"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import { ClientOptions } from 'ws';
2
3
  export declare class Subscription<T = unknown> {
3
4
  opts: ClientOptions & {
@@ -23,3 +24,4 @@ export declare class Subscription<T = unknown> {
23
24
  [Symbol.asyncIterator](): AsyncGenerator<T>;
24
25
  }
25
26
  export default Subscription;
27
+ //# sourceMappingURL=subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAIlC,qBAAa,YAAY,CAAC,CAAC,GAAG,OAAO;IAE1B,IAAI,EAAE,aAAa,GAAG;QAC3B,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;QACd,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;QACpB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,SAAS,CAAA;QACzC,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,MAAM,EACT,YAAY,EAAE,OAAO,KAClB,IAAI,CAAA;QACT,SAAS,CAAC,EAAE,MACR,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAC5C,SAAS,CAAA;KACd;gBAhBM,IAAI,EAAE,aAAa,GAAG;QAC3B,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;QACd,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;QACpB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,SAAS,CAAA;QACzC,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,MAAM,EACT,YAAY,EAAE,OAAO,KAClB,IAAI,CAAA;QACT,SAAS,CAAC,EAAE,MACR,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAC5C,SAAS,CAAA;KACd;IAGI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC;CAsBnD;AAED,eAAe,YAAY,CAAA"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Subscription = void 0;
4
+ const websocket_keepalive_1 = require("./websocket-keepalive");
5
+ const stream_1 = require("./stream");
6
+ class Subscription {
7
+ constructor(opts) {
8
+ Object.defineProperty(this, "opts", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: opts
13
+ });
14
+ }
15
+ async *[Symbol.asyncIterator]() {
16
+ const ws = new websocket_keepalive_1.WebSocketKeepAlive({
17
+ ...this.opts,
18
+ getUrl: async () => {
19
+ const params = (await this.opts.getParams?.()) ?? {};
20
+ const query = encodeQueryParams(params);
21
+ return `${this.opts.service}/xrpc/${this.opts.method}?${query}`;
22
+ },
23
+ });
24
+ for await (const chunk of ws) {
25
+ const message = await (0, stream_1.ensureChunkIsMessage)(chunk);
26
+ const t = message.header.t;
27
+ const clone = message.body !== undefined ? { ...message.body } : undefined;
28
+ if (clone !== undefined && t !== undefined) {
29
+ clone['$type'] = t.startsWith('#') ? this.opts.method + t : t;
30
+ }
31
+ const result = this.opts.validate(clone);
32
+ if (result !== undefined) {
33
+ yield result;
34
+ }
35
+ }
36
+ }
37
+ }
38
+ exports.Subscription = Subscription;
39
+ exports.default = Subscription;
40
+ function encodeQueryParams(obj) {
41
+ const params = new URLSearchParams();
42
+ Object.entries(obj).forEach(([key, value]) => {
43
+ const encoded = encodeQueryParam(value);
44
+ if (Array.isArray(encoded)) {
45
+ encoded.forEach((enc) => params.append(key, enc));
46
+ }
47
+ else {
48
+ params.set(key, encoded);
49
+ }
50
+ });
51
+ return params.toString();
52
+ }
53
+ // Adapted from xrpc, but without any lex-specific knowledge
54
+ function encodeQueryParam(value) {
55
+ if (typeof value === 'string') {
56
+ return value;
57
+ }
58
+ if (typeof value === 'number') {
59
+ return value.toString();
60
+ }
61
+ if (typeof value === 'boolean') {
62
+ return value ? 'true' : 'false';
63
+ }
64
+ if (typeof value === 'undefined') {
65
+ return '';
66
+ }
67
+ if (typeof value === 'object') {
68
+ if (value instanceof Date) {
69
+ return value.toISOString();
70
+ }
71
+ else if (Array.isArray(value)) {
72
+ return value.flatMap(encodeQueryParam);
73
+ }
74
+ else if (!value) {
75
+ return '';
76
+ }
77
+ }
78
+ throw new Error(`Cannot encode ${typeof value}s into query params`);
79
+ }
80
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export declare const messageFrameHeader: z.ZodObject<{
13
13
  op: FrameType.Message;
14
14
  t?: string | undefined;
15
15
  }>;
16
- export declare type MessageFrameHeader = z.infer<typeof messageFrameHeader>;
16
+ export type MessageFrameHeader = z.infer<typeof messageFrameHeader>;
17
17
  export declare const errorFrameHeader: z.ZodObject<{
18
18
  op: z.ZodLiteral<FrameType.Error>;
19
19
  }, "strip", z.ZodTypeAny, {
@@ -31,8 +31,8 @@ export declare const errorFrameBody: z.ZodObject<{
31
31
  error: string;
32
32
  message?: string | undefined;
33
33
  }>;
34
- export declare type ErrorFrameHeader = z.infer<typeof errorFrameHeader>;
35
- export declare type ErrorFrameBody<T extends string = string> = {
34
+ export type ErrorFrameHeader = z.infer<typeof errorFrameHeader>;
35
+ export type ErrorFrameBody<T extends string = string> = {
36
36
  error: T;
37
37
  } & z.infer<typeof errorFrameBody>;
38
38
  export declare const frameHeader: z.ZodUnion<[z.ZodObject<{
@@ -51,7 +51,7 @@ export declare const frameHeader: z.ZodUnion<[z.ZodObject<{
51
51
  }, {
52
52
  op: FrameType.Error;
53
53
  }>]>;
54
- export declare type FrameHeader = z.infer<typeof frameHeader>;
54
+ export type FrameHeader = z.infer<typeof frameHeader>;
55
55
  export declare class DisconnectError extends Error {
56
56
  wsCode: CloseCode;
57
57
  xrpcCode?: string | undefined;
@@ -62,3 +62,4 @@ export declare enum CloseCode {
62
62
  Abnormal = 1006,
63
63
  Policy = 1008
64
64
  }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,oBAAY,SAAS;IACnB,OAAO,IAAI;IACX,KAAK,KAAK;CACX;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,gBAAgB;;;;;;EAE3B,CAAA;AACF,eAAO,MAAM,cAAc;;;;;;;;;EAGzB,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAC/D,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,CAAC,CAAC,KAAK,CAC5E,OAAO,cAAc,CACtB,CAAA;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;IAAkD,CAAA;AAC1E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAErD,qBAAa,eAAgB,SAAQ,KAAK;IAE/B,MAAM,EAAE,SAAS;IACjB,QAAQ,CAAC;gBADT,MAAM,GAAE,SAA4B,EACpC,QAAQ,CAAC,oBAAQ;CAI3B;AAGD,oBAAY,SAAS;IACnB,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,MAAM,OAAO;CACd"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CloseCode = exports.DisconnectError = exports.frameHeader = exports.errorFrameBody = exports.errorFrameHeader = exports.messageFrameHeader = exports.FrameType = void 0;
4
+ const zod_1 = require("zod");
5
+ var FrameType;
6
+ (function (FrameType) {
7
+ FrameType[FrameType["Message"] = 1] = "Message";
8
+ FrameType[FrameType["Error"] = -1] = "Error";
9
+ })(FrameType || (exports.FrameType = FrameType = {}));
10
+ exports.messageFrameHeader = zod_1.z.object({
11
+ op: zod_1.z.literal(FrameType.Message), // Frame op
12
+ t: zod_1.z.string().optional(), // Message body type discriminator
13
+ });
14
+ exports.errorFrameHeader = zod_1.z.object({
15
+ op: zod_1.z.literal(FrameType.Error),
16
+ });
17
+ exports.errorFrameBody = zod_1.z.object({
18
+ error: zod_1.z.string(), // Error code
19
+ message: zod_1.z.string().optional(), // Error message
20
+ });
21
+ exports.frameHeader = zod_1.z.union([exports.messageFrameHeader, exports.errorFrameHeader]);
22
+ class DisconnectError extends Error {
23
+ constructor(wsCode = CloseCode.Policy, xrpcCode) {
24
+ super();
25
+ Object.defineProperty(this, "wsCode", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: wsCode
30
+ });
31
+ Object.defineProperty(this, "xrpcCode", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: xrpcCode
36
+ });
37
+ }
38
+ }
39
+ exports.DisconnectError = DisconnectError;
40
+ // https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1
41
+ var CloseCode;
42
+ (function (CloseCode) {
43
+ CloseCode[CloseCode["Normal"] = 1000] = "Normal";
44
+ CloseCode[CloseCode["Abnormal"] = 1006] = "Abnormal";
45
+ CloseCode[CloseCode["Policy"] = 1008] = "Policy";
46
+ })(CloseCode || (exports.CloseCode = CloseCode = {}));
47
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEvB,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,+CAAW,CAAA;IACX,4CAAU,CAAA;AACZ,CAAC,EAHW,SAAS,yBAAT,SAAS,QAGpB;AAEY,QAAA,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,OAAC,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW;IAC7C,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,kCAAkC;CAC7D,CAAC,CAAA;AAGW,QAAA,gBAAgB,GAAG,OAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,OAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;CAC/B,CAAC,CAAA;AACW,QAAA,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,aAAa;IAChC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,gBAAgB;CACjD,CAAC,CAAA;AAMW,QAAA,WAAW,GAAG,OAAC,CAAC,KAAK,CAAC,CAAC,0BAAkB,EAAE,wBAAgB,CAAC,CAAC,CAAA;AAG1E,MAAa,eAAgB,SAAQ,KAAK;IACxC,YACS,SAAoB,SAAS,CAAC,MAAM,EACpC,QAAiB;QAExB,KAAK,EAAE,CAAA;QAHP;;;;mBAAO,MAAM;WAA8B;QAC3C;;;;mBAAO,QAAQ;WAAS;IAG1B,CAAC;CACF;AAPD,0CAOC;AAED,uDAAuD;AACvD,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,gDAAa,CAAA;IACb,oDAAe,CAAA;IACf,gDAAa,CAAA;AACf,CAAC,EAJW,SAAS,yBAAT,SAAS,QAIpB"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import { WebSocket, ClientOptions } from 'ws';
2
3
  export declare class WebSocketKeepAlive {
3
4
  opts: ClientOptions & {
@@ -21,3 +22,4 @@ export declare class WebSocketKeepAlive {
21
22
  startHeartbeat(ws: WebSocket): void;
22
23
  }
23
24
  export default WebSocketKeepAlive;
25
+ //# sourceMappingURL=websocket-keepalive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-keepalive.d.ts","sourceRoot":"","sources":["../../src/stream/websocket-keepalive.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAI7C,qBAAa,kBAAkB;IAMpB,IAAI,EAAE,aAAa,GAAG;QAC3B,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;QAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;QACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,MAAM,EACT,YAAY,EAAE,OAAO,KAClB,IAAI,CAAA;KACV;IAfI,EAAE,EAAE,SAAS,GAAG,IAAI,CAAO;IAC3B,YAAY,UAAO;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAO;gBAG9B,IAAI,EAAE,aAAa,GAAG;QAC3B,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;QAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;QACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,MAAM,EACT,YAAY,EAAE,OAAO,KAClB,IAAI,CAAA;KACV;IAGI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,UAAU,CAAC;IAwD3D,cAAc,CAAC,EAAE,EAAE,SAAS;CA4B7B;AAED,eAAe,kBAAkB,CAAA"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketKeepAlive = void 0;
4
+ const common_1 = require("@atproto/common");
5
+ const ws_1 = require("ws");
6
+ const stream_1 = require("./stream");
7
+ const types_1 = require("./types");
8
+ class WebSocketKeepAlive {
9
+ constructor(opts) {
10
+ Object.defineProperty(this, "opts", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: opts
15
+ });
16
+ Object.defineProperty(this, "ws", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: null
21
+ });
22
+ Object.defineProperty(this, "initialSetup", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: true
27
+ });
28
+ Object.defineProperty(this, "reconnects", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: null
33
+ });
34
+ }
35
+ async *[Symbol.asyncIterator]() {
36
+ const maxReconnectMs = 1000 * (this.opts.maxReconnectSeconds ?? 64);
37
+ while (true) {
38
+ if (this.reconnects !== null) {
39
+ const duration = this.initialSetup
40
+ ? Math.min(1000, maxReconnectMs)
41
+ : backoffMs(this.reconnects++, maxReconnectMs);
42
+ await (0, common_1.wait)(duration);
43
+ }
44
+ const url = await this.opts.getUrl();
45
+ this.ws = new ws_1.WebSocket(url, this.opts);
46
+ const ac = new AbortController();
47
+ if (this.opts.signal) {
48
+ forwardSignal(this.opts.signal, ac);
49
+ }
50
+ this.ws.once('open', () => {
51
+ this.initialSetup = false;
52
+ this.reconnects = 0;
53
+ if (this.ws) {
54
+ this.startHeartbeat(this.ws);
55
+ }
56
+ });
57
+ this.ws.once('close', (code, reason) => {
58
+ if (code === types_1.CloseCode.Abnormal) {
59
+ // Forward into an error to distinguish from a clean close
60
+ ac.abort(new AbnormalCloseError(`Abnormal ws close: ${reason.toString()}`));
61
+ }
62
+ });
63
+ try {
64
+ const wsStream = (0, stream_1.streamByteChunks)(this.ws, { signal: ac.signal });
65
+ for await (const chunk of wsStream) {
66
+ yield chunk;
67
+ }
68
+ }
69
+ catch (_err) {
70
+ const err = _err?.['code'] === 'ABORT_ERR' ? _err['cause'] : _err;
71
+ if (err instanceof types_1.DisconnectError) {
72
+ // We cleanly end the connection
73
+ this.ws?.close(err.wsCode);
74
+ break;
75
+ }
76
+ this.ws?.close(); // No-ops if already closed or closing
77
+ if (isReconnectable(err)) {
78
+ this.reconnects ?? (this.reconnects = 0); // Never reconnect with a null
79
+ this.opts.onReconnectError?.(err, this.reconnects, this.initialSetup);
80
+ continue;
81
+ }
82
+ else {
83
+ throw err;
84
+ }
85
+ }
86
+ break; // Other side cleanly ended stream and disconnected
87
+ }
88
+ }
89
+ startHeartbeat(ws) {
90
+ let isAlive = true;
91
+ let heartbeatInterval = null;
92
+ const checkAlive = () => {
93
+ if (!isAlive) {
94
+ return ws.terminate();
95
+ }
96
+ isAlive = false; // expect websocket to no longer be alive unless we receive a "pong" within the interval
97
+ ws.ping();
98
+ };
99
+ checkAlive();
100
+ heartbeatInterval = setInterval(checkAlive, this.opts.heartbeatIntervalMs ?? 10 * common_1.SECOND);
101
+ ws.on('pong', () => {
102
+ isAlive = true;
103
+ });
104
+ ws.once('close', () => {
105
+ if (heartbeatInterval) {
106
+ clearInterval(heartbeatInterval);
107
+ heartbeatInterval = null;
108
+ }
109
+ });
110
+ }
111
+ }
112
+ exports.WebSocketKeepAlive = WebSocketKeepAlive;
113
+ exports.default = WebSocketKeepAlive;
114
+ class AbnormalCloseError extends Error {
115
+ constructor() {
116
+ super(...arguments);
117
+ Object.defineProperty(this, "code", {
118
+ enumerable: true,
119
+ configurable: true,
120
+ writable: true,
121
+ value: 'EWSABNORMALCLOSE'
122
+ });
123
+ }
124
+ }
125
+ function isReconnectable(err) {
126
+ // Network errors are reconnectable.
127
+ // AuthenticationRequired and InvalidRequest XRPCErrors are not reconnectable.
128
+ // @TODO method-specific XRPCErrors may be reconnectable, need to consider. Receiving
129
+ // an invalid message is not current reconnectable, but the user can decide to skip them.
130
+ if (!err || typeof err['code'] !== 'string')
131
+ return false;
132
+ return networkErrorCodes.includes(err['code']);
133
+ }
134
+ const networkErrorCodes = [
135
+ 'EWSABNORMALCLOSE',
136
+ 'ECONNRESET',
137
+ 'ECONNREFUSED',
138
+ 'ECONNABORTED',
139
+ 'EPIPE',
140
+ 'ETIMEDOUT',
141
+ 'ECANCELED',
142
+ ];
143
+ function backoffMs(n, maxMs) {
144
+ const baseSec = Math.pow(2, n); // 1, 2, 4, ...
145
+ const randSec = Math.random() - 0.5; // Random jitter between -.5 and .5 seconds
146
+ const ms = 1000 * (baseSec + randSec);
147
+ return Math.min(ms, maxMs);
148
+ }
149
+ function forwardSignal(signal, ac) {
150
+ if (signal.aborted) {
151
+ return ac.abort(signal.reason);
152
+ }
153
+ else {
154
+ signal.addEventListener('abort', () => ac.abort(signal.reason), {
155
+ // @ts-ignore https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68625
156
+ signal: ac.signal,
157
+ });
158
+ }
159
+ }
160
+ //# sourceMappingURL=websocket-keepalive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-keepalive.js","sourceRoot":"","sources":["../../src/stream/websocket-keepalive.ts"],"names":[],"mappings":"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"}