@atproto/xrpc-server 0.10.20 → 0.11.0-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 (83) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/auth.js +25 -65
  3. package/dist/auth.js.map +1 -1
  4. package/dist/errors.d.ts.map +1 -1
  5. package/dist/errors.js +59 -85
  6. package/dist/errors.js.map +1 -1
  7. package/dist/index.d.ts +8 -8
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +7 -28
  10. package/dist/index.js.map +1 -1
  11. package/dist/logger.js +4 -7
  12. package/dist/logger.js.map +1 -1
  13. package/dist/rate-limiter.d.ts +1 -1
  14. package/dist/rate-limiter.d.ts.map +1 -1
  15. package/dist/rate-limiter.js +27 -91
  16. package/dist/rate-limiter.js.map +1 -1
  17. package/dist/server.d.ts +4 -4
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +94 -178
  20. package/dist/server.js.map +1 -1
  21. package/dist/stream/frames.d.ts +1 -1
  22. package/dist/stream/frames.d.ts.map +1 -1
  23. package/dist/stream/frames.js +20 -50
  24. package/dist/stream/frames.js.map +1 -1
  25. package/dist/stream/index.d.ts +5 -5
  26. package/dist/stream/index.d.ts.map +1 -1
  27. package/dist/stream/index.js +5 -21
  28. package/dist/stream/index.js.map +1 -1
  29. package/dist/stream/logger.js +3 -6
  30. package/dist/stream/logger.js.map +1 -1
  31. package/dist/stream/server.d.ts +3 -2
  32. package/dist/stream/server.d.ts.map +1 -1
  33. package/dist/stream/server.js +12 -22
  34. package/dist/stream/server.js.map +1 -1
  35. package/dist/stream/stream.d.ts +2 -2
  36. package/dist/stream/stream.d.ts.map +1 -1
  37. package/dist/stream/stream.js +12 -18
  38. package/dist/stream/stream.js.map +1 -1
  39. package/dist/stream/subscription.d.ts +1 -1
  40. package/dist/stream/subscription.d.ts.map +1 -1
  41. package/dist/stream/subscription.js +9 -18
  42. package/dist/stream/subscription.js.map +1 -1
  43. package/dist/stream/types.js +12 -15
  44. package/dist/stream/types.js.map +1 -1
  45. package/dist/types.d.ts +2 -2
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +22 -29
  48. package/dist/types.js.map +1 -1
  49. package/dist/util.d.ts +2 -2
  50. package/dist/util.d.ts.map +1 -1
  51. package/dist/util.js +75 -116
  52. package/dist/util.js.map +1 -1
  53. package/{jest.config.js → jest.config.cjs} +8 -2
  54. package/package.json +28 -22
  55. package/src/auth.ts +1 -1
  56. package/src/errors.ts +4 -1
  57. package/src/index.ts +8 -8
  58. package/src/rate-limiter.ts +2 -2
  59. package/src/server.ts +11 -6
  60. package/src/stream/frames.ts +2 -2
  61. package/src/stream/index.ts +5 -5
  62. package/src/stream/server.ts +4 -3
  63. package/src/stream/stream.ts +1 -1
  64. package/src/stream/subscription.ts +2 -2
  65. package/src/types.ts +2 -2
  66. package/src/util.ts +6 -3
  67. package/tests/_util.ts +1 -1
  68. package/tests/auth.test.ts +6 -3
  69. package/tests/bodies.test.ts +4 -3
  70. package/tests/errors.test.ts +2 -2
  71. package/tests/frames.test.ts +1 -1
  72. package/tests/ipld.test.ts +2 -2
  73. package/tests/parameters.test.ts +2 -2
  74. package/tests/parsing.test.ts +1 -1
  75. package/tests/procedures.test.ts +2 -2
  76. package/tests/queries.test.ts +2 -2
  77. package/tests/rate-limiter.test.ts +3 -3
  78. package/tests/responses.test.ts +2 -2
  79. package/tests/stream.test.ts +1 -1
  80. package/tests/subscriptions.test.ts +11 -5
  81. package/tsconfig.build.json +1 -1
  82. package/tsconfig.build.tsbuildinfo +1 -1
  83. package/tsconfig.tests.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAiB,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAGnB,MAAM,SAAS,CAAA;AAEhB,8BAAsB,KAAK,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IACvD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAEhB,IAAI,EAAE,IAAI,SAAS,CAElB;IACD,OAAO,IAAI,UAAU;IAGrB,SAAS,IAAI,IAAI,IAAI,YAAY;IAGjC,OAAO,IAAI,IAAI,IAAI,UAAU;IAG7B,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU;CA8BnC;AAED,qBAAa,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,CAAE,SAAQ,KAAK,CAAC,CAAC,CAAC;IACvE,MAAM,EAAE,kBAAkB,CAAA;IAC1B,IAAI,EAAE,CAAC,CAAA;gBAEK,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAQ7C,IAAI,IAAI,uBAEP;IAED,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM;;;CAsBjD;AAED,qBAAa,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,KAAK,CAC9D,cAAc,CAAC,CAAC,CAAC,CAClB;IACC,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;gBAEX,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAKnC,IAAI,IAAI,MAEP;IACD,IAAI,OAAO,uBAEV;IAED,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU;CAK3C"}
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAiB,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAGnB,MAAM,YAAY,CAAA;AAEnB,8BAAsB,KAAK,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IACvD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAEhB,IAAI,EAAE,IAAI,SAAS,CAElB;IACD,OAAO,IAAI,UAAU;IAGrB,SAAS,IAAI,IAAI,IAAI,YAAY;IAGjC,OAAO,IAAI,IAAI,IAAI,UAAU;IAG7B,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU;CA8BnC;AAED,qBAAa,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,CAAE,SAAQ,KAAK,CAAC,CAAC,CAAC;IACvE,MAAM,EAAE,kBAAkB,CAAA;IAC1B,IAAI,EAAE,CAAC,CAAA;gBAEK,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAQ7C,IAAI,IAAI,uBAEP;IAED,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM;;;CAsBjD;AAED,qBAAa,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,KAAK,CAC9D,cAAc,CAAC,CAAC,CAAC,CAClB;IACC,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;gBAEX,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAKnC,IAAI,IAAI,MAEP;IACD,IAAI,OAAO,uBAEV;IAED,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU;CAK3C"}
@@ -1,43 +1,40 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ErrorFrame = exports.MessageFrame = exports.Frame = void 0;
4
- const lex_cbor_1 = require("@atproto/lex-cbor");
5
- const lex_data_1 = require("@atproto/lex-data");
6
- const errors_1 = require("../errors");
7
- const types_1 = require("./types");
8
- class Frame {
1
+ import { decodeAll, encode } from '@atproto/lex-cbor';
2
+ import { isPlainObject } from '@atproto/lex-data';
3
+ import { XRPCError } from '../errors.js';
4
+ import { FrameType, errorFrameBody, frameHeader, } from './types.js';
5
+ export class Frame {
9
6
  get op() {
10
7
  return this.header.op;
11
8
  }
12
9
  toBytes() {
13
- return Buffer.concat([(0, lex_cbor_1.encode)(this.header), (0, lex_cbor_1.encode)(this.body)]);
10
+ return Buffer.concat([encode(this.header), encode(this.body)]);
14
11
  }
15
12
  isMessage() {
16
- return this.op === types_1.FrameType.Message;
13
+ return this.op === FrameType.Message;
17
14
  }
18
15
  isError() {
19
- return this.op === types_1.FrameType.Error;
16
+ return this.op === FrameType.Error;
20
17
  }
21
18
  static fromBytes(bytes) {
22
- const [header, body, ...rest] = (0, lex_cbor_1.decodeAll)(bytes);
19
+ const [header, body, ...rest] = decodeAll(bytes);
23
20
  if (rest.length) {
24
21
  throw new Error('Too many CBOR data items in frame');
25
22
  }
26
23
  else if (body === undefined) {
27
24
  throw new Error('Missing frame body');
28
25
  }
29
- const parsedHeader = types_1.frameHeader.safeParse(header);
26
+ const parsedHeader = frameHeader.safeParse(header);
30
27
  if (!parsedHeader.success) {
31
28
  throw new Error(`Invalid frame header: ${parsedHeader.reason.message}`);
32
29
  }
33
30
  const frameOp = parsedHeader.value.op;
34
- if (frameOp === types_1.FrameType.Message) {
31
+ if (frameOp === FrameType.Message) {
35
32
  return new MessageFrame(body, {
36
33
  type: parsedHeader.value.t,
37
34
  });
38
35
  }
39
- else if (frameOp === types_1.FrameType.Error) {
40
- const parsedBody = types_1.errorFrameBody.safeParse(body);
36
+ else if (frameOp === FrameType.Error) {
37
+ const parsedBody = errorFrameBody.safeParse(body);
41
38
  if (!parsedBody.success) {
42
39
  throw new Error(`Invalid error frame body: ${parsedBody.reason.message}`);
43
40
  }
@@ -49,33 +46,20 @@ class Frame {
49
46
  }
50
47
  }
51
48
  }
52
- exports.Frame = Frame;
53
- class MessageFrame extends Frame {
49
+ export class MessageFrame extends Frame {
54
50
  constructor(body, opts) {
55
51
  super();
56
- Object.defineProperty(this, "header", {
57
- enumerable: true,
58
- configurable: true,
59
- writable: true,
60
- value: void 0
61
- });
62
- Object.defineProperty(this, "body", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: void 0
67
- });
68
52
  this.header =
69
53
  opts?.type !== undefined
70
- ? { op: types_1.FrameType.Message, t: opts?.type }
71
- : { op: types_1.FrameType.Message };
54
+ ? { op: FrameType.Message, t: opts?.type }
55
+ : { op: FrameType.Message };
72
56
  this.body = body;
73
57
  }
74
58
  get type() {
75
59
  return this.header.t;
76
60
  }
77
61
  static fromLexValue(data, nsid) {
78
- if (!(0, lex_data_1.isPlainObject)(data)) {
62
+ if (!isPlainObject(data)) {
79
63
  return new MessageFrame(data);
80
64
  }
81
65
  const $type = data?.['$type'];
@@ -94,23 +78,10 @@ class MessageFrame extends Frame {
94
78
  return new MessageFrame(clone, { type });
95
79
  }
96
80
  }
97
- exports.MessageFrame = MessageFrame;
98
- class ErrorFrame extends Frame {
81
+ export class ErrorFrame extends Frame {
99
82
  constructor(body) {
100
83
  super();
101
- Object.defineProperty(this, "header", {
102
- enumerable: true,
103
- configurable: true,
104
- writable: true,
105
- value: void 0
106
- });
107
- Object.defineProperty(this, "body", {
108
- enumerable: true,
109
- configurable: true,
110
- writable: true,
111
- value: void 0
112
- });
113
- this.header = { op: types_1.FrameType.Error };
84
+ this.header = { op: FrameType.Error };
114
85
  this.body = body;
115
86
  }
116
87
  get code() {
@@ -122,9 +93,8 @@ class ErrorFrame extends Frame {
122
93
  static fromError(err) {
123
94
  if (err instanceof ErrorFrame)
124
95
  return err;
125
- const { error = 'Unknown', message } = errors_1.XRPCError.fromError(err).payload;
96
+ const { error = 'Unknown', message } = XRPCError.fromError(err).payload;
126
97
  return new ErrorFrame({ error, message });
127
98
  }
128
99
  }
129
- exports.ErrorFrame = ErrorFrame;
130
100
  //# sourceMappingURL=frames.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodeAll, encode } from '@atproto/lex-cbor'\nimport { LexValue, isPlainObject } from '@atproto/lex-data'\nimport { XRPCError } from '../errors'\nimport {\n ErrorFrameBody,\n ErrorFrameHeader,\n FrameHeader,\n FrameType,\n MessageFrameHeader,\n errorFrameBody,\n frameHeader,\n} from './types'\n\nexport abstract class Frame<T extends LexValue = LexValue> {\n abstract header: FrameHeader\n abstract body: T\n\n get op(): FrameType {\n return this.header.op\n }\n toBytes(): Uint8Array {\n return Buffer.concat([encode(this.header), encode(this.body)])\n }\n isMessage(): this is MessageFrame {\n return this.op === FrameType.Message\n }\n isError(): this is ErrorFrame {\n return this.op === FrameType.Error\n }\n static fromBytes(bytes: Uint8Array) {\n const [header, body, ...rest] = decodeAll(bytes)\n if (rest.length) {\n throw new Error('Too many CBOR data items in frame')\n } else if (body === undefined) {\n throw new Error('Missing frame body')\n }\n\n const parsedHeader = frameHeader.safeParse(header)\n if (!parsedHeader.success) {\n throw new Error(`Invalid frame header: ${parsedHeader.reason.message}`)\n }\n const frameOp = parsedHeader.value.op\n if (frameOp === FrameType.Message) {\n return new MessageFrame(body, {\n type: parsedHeader.value.t,\n })\n } else if (frameOp === FrameType.Error) {\n const parsedBody = errorFrameBody.safeParse(body)\n if (!parsedBody.success) {\n throw new Error(\n `Invalid error frame body: ${parsedBody.reason.message}`,\n )\n }\n return new ErrorFrame(parsedBody.value)\n } else {\n const exhaustiveCheck: never = frameOp\n throw new Error(`Unknown frame op: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport class MessageFrame<T extends LexValue = LexValue> extends Frame<T> {\n header: MessageFrameHeader\n body: T\n\n constructor(body: T, opts?: { type?: string }) {\n super()\n this.header =\n opts?.type !== undefined\n ? { op: FrameType.Message, t: opts?.type }\n : { op: FrameType.Message }\n this.body = body\n }\n get type() {\n return this.header.t\n }\n\n static fromLexValue(data: LexValue, nsid: string) {\n if (!isPlainObject(data)) {\n return new MessageFrame(data)\n }\n\n const $type = data?.['$type']\n if (typeof $type !== 'string') {\n return new MessageFrame(data)\n }\n\n let type: string\n\n const split = $type.split('#')\n if (split.length === 2 && (split[0] === '' || split[0] === nsid)) {\n type = `#${split[1]}`\n } else {\n type = $type\n }\n\n const { $type: _, ...clone } = data\n return new MessageFrame(clone, { type })\n }\n}\n\nexport class ErrorFrame<T extends string = string> extends Frame<\n ErrorFrameBody<T>\n> {\n header: ErrorFrameHeader\n body: ErrorFrameBody<T>\n\n constructor(body: ErrorFrameBody<T>) {\n super()\n this.header = { op: FrameType.Error }\n this.body = body\n }\n get code() {\n return this.body.error\n }\n get message() {\n return this.body.message\n }\n\n static fromError(err: unknown): ErrorFrame {\n if (err instanceof ErrorFrame) return err\n const { error = 'Unknown', message } = XRPCError.fromError(err).payload\n return new ErrorFrame({ error, message })\n }\n}\n"]}
1
+ {"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodeAll, encode } from '@atproto/lex-cbor'\nimport { LexValue, isPlainObject } from '@atproto/lex-data'\nimport { XRPCError } from '../errors.js'\nimport {\n ErrorFrameBody,\n ErrorFrameHeader,\n FrameHeader,\n FrameType,\n MessageFrameHeader,\n errorFrameBody,\n frameHeader,\n} from './types.js'\n\nexport abstract class Frame<T extends LexValue = LexValue> {\n abstract header: FrameHeader\n abstract body: T\n\n get op(): FrameType {\n return this.header.op\n }\n toBytes(): Uint8Array {\n return Buffer.concat([encode(this.header), encode(this.body)])\n }\n isMessage(): this is MessageFrame {\n return this.op === FrameType.Message\n }\n isError(): this is ErrorFrame {\n return this.op === FrameType.Error\n }\n static fromBytes(bytes: Uint8Array) {\n const [header, body, ...rest] = decodeAll(bytes)\n if (rest.length) {\n throw new Error('Too many CBOR data items in frame')\n } else if (body === undefined) {\n throw new Error('Missing frame body')\n }\n\n const parsedHeader = frameHeader.safeParse(header)\n if (!parsedHeader.success) {\n throw new Error(`Invalid frame header: ${parsedHeader.reason.message}`)\n }\n const frameOp = parsedHeader.value.op\n if (frameOp === FrameType.Message) {\n return new MessageFrame(body, {\n type: parsedHeader.value.t,\n })\n } else if (frameOp === FrameType.Error) {\n const parsedBody = errorFrameBody.safeParse(body)\n if (!parsedBody.success) {\n throw new Error(\n `Invalid error frame body: ${parsedBody.reason.message}`,\n )\n }\n return new ErrorFrame(parsedBody.value)\n } else {\n const exhaustiveCheck: never = frameOp\n throw new Error(`Unknown frame op: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport class MessageFrame<T extends LexValue = LexValue> extends Frame<T> {\n header: MessageFrameHeader\n body: T\n\n constructor(body: T, opts?: { type?: string }) {\n super()\n this.header =\n opts?.type !== undefined\n ? { op: FrameType.Message, t: opts?.type }\n : { op: FrameType.Message }\n this.body = body\n }\n get type() {\n return this.header.t\n }\n\n static fromLexValue(data: LexValue, nsid: string) {\n if (!isPlainObject(data)) {\n return new MessageFrame(data)\n }\n\n const $type = data?.['$type']\n if (typeof $type !== 'string') {\n return new MessageFrame(data)\n }\n\n let type: string\n\n const split = $type.split('#')\n if (split.length === 2 && (split[0] === '' || split[0] === nsid)) {\n type = `#${split[1]}`\n } else {\n type = $type\n }\n\n const { $type: _, ...clone } = data\n return new MessageFrame(clone, { type })\n }\n}\n\nexport class ErrorFrame<T extends string = string> extends Frame<\n ErrorFrameBody<T>\n> {\n header: ErrorFrameHeader\n body: ErrorFrameBody<T>\n\n constructor(body: ErrorFrameBody<T>) {\n super()\n this.header = { op: FrameType.Error }\n this.body = body\n }\n get code() {\n return this.body.error\n }\n get message() {\n return this.body.message\n }\n\n static fromError(err: unknown): ErrorFrame {\n if (err instanceof ErrorFrame) return err\n const { error = 'Unknown', message } = XRPCError.fromError(err).payload\n return new ErrorFrame({ error, message })\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- export * from './types';
2
- export * from './frames';
3
- export * from './stream';
4
- export * from './subscription';
5
- export * from './server';
1
+ export * from './types.js';
2
+ export * from './frames.js';
3
+ export * from './stream.js';
4
+ export * from './subscription.js';
5
+ export * from './server.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stream/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stream/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA"}
@@ -1,22 +1,6 @@
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);
1
+ export * from './types.js';
2
+ export * from './frames.js';
3
+ export * from './stream.js';
4
+ export * from './subscription.js';
5
+ export * from './server.js';
22
6
  //# sourceMappingURL=index.js.map
@@ -1 +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","sourcesContent":["export * from './types'\nexport * from './frames'\nexport * from './stream'\nexport * from './subscription'\nexport * from './server'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stream/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA","sourcesContent":["export * from './types.js'\nexport * from './frames.js'\nexport * from './stream.js'\nexport * from './subscription.js'\nexport * from './server.js'\n"]}
@@ -1,7 +1,4 @@
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;
1
+ import { subsystemLogger } from '@atproto/common';
2
+ export const logger = subsystemLogger('xrpc-stream');
3
+ export default logger;
7
4
  //# sourceMappingURL=logger.js.map
@@ -1 +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","sourcesContent":["import { subsystemLogger } from '@atproto/common'\n\nexport const logger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('xrpc-stream')\n\nexport default logger\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/stream/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,CAAC,MAAM,MAAM,GACjB,eAAe,CAAC,aAAa,CAAC,CAAA;AAEhC,eAAe,MAAM,CAAA","sourcesContent":["import { subsystemLogger } from '@atproto/common'\n\nexport const logger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('xrpc-stream')\n\nexport default logger\n"]}
@@ -1,6 +1,7 @@
1
1
  import { IncomingMessage } from 'node:http';
2
- import { ServerOptions, WebSocket, WebSocketServer } from 'ws';
3
- import { Frame } from './frames';
2
+ import type { ServerOptions } from 'ws';
3
+ import { WebSocket, WebSocketServer } from 'ws';
4
+ import { Frame } from './frames.js';
4
5
  export declare class XrpcStreamServer {
5
6
  wss: WebSocketServer;
6
7
  constructor(opts: ServerOptions & {
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAE9D,OAAO,EAAc,KAAK,EAAE,MAAM,UAAU,CAAA;AAG5C,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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAE/C,OAAO,EAAc,KAAK,EAAE,MAAM,aAAa,CAAA;AAG/C,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"}
@@ -1,22 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.XrpcStreamServer = void 0;
4
- const ws_1 = require("ws");
5
- const ws_client_1 = require("@atproto/ws-client");
6
- const frames_1 = require("./frames");
7
- const logger_1 = require("./logger");
8
- class XrpcStreamServer {
1
+ import { WebSocketServer } from 'ws';
2
+ import { CloseCode, DisconnectError } from '@atproto/ws-client';
3
+ import { ErrorFrame } from './frames.js';
4
+ import { logger } from './logger.js';
5
+ export class XrpcStreamServer {
9
6
  constructor(opts) {
10
- Object.defineProperty(this, "wss", {
11
- enumerable: true,
12
- configurable: true,
13
- writable: true,
14
- value: void 0
15
- });
16
7
  const { handler, ...serverOpts } = opts;
17
- this.wss = new ws_1.WebSocketServer(serverOpts);
8
+ this.wss = new WebSocketServer(serverOpts);
18
9
  this.wss.on('connection', async (socket, req) => {
19
- socket.on('error', (err) => logger_1.logger.error(err, 'websocket error'));
10
+ socket.on('error', (err) => logger.error(err, 'websocket error'));
20
11
  try {
21
12
  const ac = new AbortController();
22
13
  const iterator = unwrapIterator(handler(req, ac.signal, socket, this));
@@ -35,25 +26,24 @@ class XrpcStreamServer {
35
26
  res(undefined);
36
27
  });
37
28
  });
38
- if (frame instanceof frames_1.ErrorFrame) {
39
- throw new ws_client_1.DisconnectError(ws_client_1.CloseCode.Policy, frame.body.error);
29
+ if (frame instanceof ErrorFrame) {
30
+ throw new DisconnectError(CloseCode.Policy, frame.body.error);
40
31
  }
41
32
  }
42
33
  }
43
34
  catch (err) {
44
- if (err instanceof ws_client_1.DisconnectError) {
35
+ if (err instanceof DisconnectError) {
45
36
  return socket.close(err.wsCode, err.xrpcCode);
46
37
  }
47
38
  else {
48
- logger_1.logger.error({ err }, 'websocket server error');
39
+ logger.error({ err }, 'websocket server error');
49
40
  return socket.terminate();
50
41
  }
51
42
  }
52
- socket.close(ws_client_1.CloseCode.Normal);
43
+ socket.close(CloseCode.Normal);
53
44
  });
54
45
  }
55
46
  }
56
- exports.XrpcStreamServer = XrpcStreamServer;
57
47
  function unwrapIterator(iterable) {
58
48
  return iterable[Symbol.asyncIterator]();
59
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":";;;AACA,2BAA8D;AAC9D,kDAA+D;AAC/D,qCAA4C;AAC5C,qCAAiC;AAEjC,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,eAAM,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,2BAAe,CAAC,qBAAS,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,2BAAe,EAAE,CAAC;oBACnC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;gBAC/C,CAAC;qBAAM,CAAC;oBACN,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,wBAAwB,CAAC,CAAA;oBAC/C,OAAO,MAAM,CAAC,SAAS,EAAE,CAAA;gBAC3B,CAAC;YACH,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,qBAAS,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","sourcesContent":["import { IncomingMessage } from 'node:http'\nimport { ServerOptions, WebSocket, WebSocketServer } from 'ws'\nimport { CloseCode, DisconnectError } from '@atproto/ws-client'\nimport { ErrorFrame, Frame } from './frames'\nimport { logger } from './logger'\n\nexport class XrpcStreamServer {\n wss: WebSocketServer\n constructor(opts: ServerOptions & { handler: Handler }) {\n const { handler, ...serverOpts } = opts\n this.wss = new WebSocketServer(serverOpts)\n this.wss.on('connection', async (socket, req) => {\n socket.on('error', (err) => logger.error(err, 'websocket error'))\n try {\n const ac = new AbortController()\n const iterator = unwrapIterator(handler(req, ac.signal, socket, this))\n socket.once('close', () => {\n iterator.return?.()\n ac.abort()\n })\n const safeFrames = wrapIterator(iterator)\n for await (const frame of safeFrames) {\n await new Promise((res, rej) => {\n socket.send(frame.toBytes(), { binary: true }, (err) => {\n // @TODO this callback may give more aggressive on backpressure than\n // we ultimately want, but trying it out for the time being.\n if (err) return rej(err)\n res(undefined)\n })\n })\n if (frame instanceof ErrorFrame) {\n throw new DisconnectError(CloseCode.Policy, frame.body.error)\n }\n }\n } catch (err) {\n if (err instanceof DisconnectError) {\n return socket.close(err.wsCode, err.xrpcCode)\n } else {\n logger.error({ err }, 'websocket server error')\n return socket.terminate()\n }\n }\n socket.close(CloseCode.Normal)\n })\n }\n}\n\nexport type Handler = (\n req: IncomingMessage,\n signal: AbortSignal,\n socket: WebSocket,\n server: XrpcStreamServer,\n) => AsyncIterable<Frame>\n\nfunction unwrapIterator<T>(iterable: AsyncIterable<T>): AsyncIterator<T> {\n return iterable[Symbol.asyncIterator]()\n}\n\nfunction wrapIterator<T>(iterator: AsyncIterator<T>): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return iterator\n },\n }\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/stream/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,eAAe,EAAE,MAAM,IAAI,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAS,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,OAAO,gBAAgB;IAE3B,YAAY,IAA0C;QACpD,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,IAAI,CAAA;QACvC,IAAI,CAAC,GAAG,GAAG,IAAI,eAAe,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,MAAM,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,UAAU,EAAE,CAAC;wBAChC,MAAM,IAAI,eAAe,CAAC,SAAS,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,eAAe,EAAE,CAAC;oBACnC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;gBAC/C,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,wBAAwB,CAAC,CAAA;oBAC/C,OAAO,MAAM,CAAC,SAAS,EAAE,CAAA;gBAC3B,CAAC;YACH,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;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","sourcesContent":["import { IncomingMessage } from 'node:http'\nimport type { ServerOptions } from 'ws'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport { CloseCode, DisconnectError } from '@atproto/ws-client'\nimport { ErrorFrame, Frame } from './frames.js'\nimport { logger } from './logger.js'\n\nexport class XrpcStreamServer {\n wss: WebSocketServer\n constructor(opts: ServerOptions & { handler: Handler }) {\n const { handler, ...serverOpts } = opts\n this.wss = new WebSocketServer(serverOpts)\n this.wss.on('connection', async (socket, req) => {\n socket.on('error', (err) => logger.error(err, 'websocket error'))\n try {\n const ac = new AbortController()\n const iterator = unwrapIterator(handler(req, ac.signal, socket, this))\n socket.once('close', () => {\n iterator.return?.()\n ac.abort()\n })\n const safeFrames = wrapIterator(iterator)\n for await (const frame of safeFrames) {\n await new Promise((res, rej) => {\n socket.send(frame.toBytes(), { binary: true }, (err) => {\n // @TODO this callback may give more aggressive on backpressure than\n // we ultimately want, but trying it out for the time being.\n if (err) return rej(err)\n res(undefined)\n })\n })\n if (frame instanceof ErrorFrame) {\n throw new DisconnectError(CloseCode.Policy, frame.body.error)\n }\n }\n } catch (err) {\n if (err instanceof DisconnectError) {\n return socket.close(err.wsCode, err.xrpcCode)\n } else {\n logger.error({ err }, 'websocket server error')\n return socket.terminate()\n }\n }\n socket.close(CloseCode.Normal)\n })\n }\n}\n\nexport type Handler = (\n req: IncomingMessage,\n signal: AbortSignal,\n socket: WebSocket,\n server: XrpcStreamServer,\n) => AsyncIterable<Frame>\n\nfunction unwrapIterator<T>(iterable: AsyncIterable<T>): AsyncIterator<T> {\n return iterable[Symbol.asyncIterator]()\n}\n\nfunction wrapIterator<T>(iterator: AsyncIterator<T>): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return iterator\n },\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { DuplexOptions } from 'node:stream';
2
2
  import { WebSocket } from 'ws';
3
- import { MessageFrame } from './frames';
3
+ import { MessageFrame } from './frames.js';
4
4
  export declare function streamByteChunks(ws: WebSocket, options?: DuplexOptions): import("stream").Duplex;
5
- export declare function byFrame(ws: WebSocket, options?: DuplexOptions): AsyncGenerator<MessageFrame<import("@atproto/lex-data").LexValue> | import("./frames").ErrorFrame<string>, void, unknown>;
5
+ export declare function byFrame(ws: WebSocket, options?: DuplexOptions): AsyncGenerator<MessageFrame<import("@atproto/lex-data").LexValue> | import("./frames.js").ErrorFrame<string>, void, unknown>;
6
6
  export declare function byMessage(ws: WebSocket, options?: DuplexOptions): AsyncGenerator<MessageFrame<import("@atproto/lex-data").LexValue>, void, unknown>;
7
7
  export declare function ensureChunkIsMessage(chunk: Uint8Array): MessageFrame;
8
8
  //# sourceMappingURL=stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAyB,MAAM,IAAI,CAAA;AAErD,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,6HAKpE;AAED,wBAAuB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,qFAMtE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAWpE"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAyB,MAAM,IAAI,CAAA;AAErD,OAAO,EAAS,YAAY,EAAE,MAAM,aAAa,CAAA;AAEjD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,2BAKtE;AAED,wBAAuB,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,gIAKpE;AAED,wBAAuB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,qFAMtE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAWpE"}
@@ -1,43 +1,37 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.streamByteChunks = streamByteChunks;
4
- exports.byFrame = byFrame;
5
- exports.byMessage = byMessage;
6
- exports.ensureChunkIsMessage = ensureChunkIsMessage;
7
- const ws_1 = require("ws");
8
- const xrpc_1 = require("@atproto/xrpc");
9
- const frames_1 = require("./frames");
10
- function streamByteChunks(ws, options) {
11
- return (0, ws_1.createWebSocketStream)(ws, {
1
+ import { createWebSocketStream } from 'ws';
2
+ import { ResponseType, XRPCError } from '@atproto/xrpc';
3
+ import { Frame } from './frames.js';
4
+ export function streamByteChunks(ws, options) {
5
+ return createWebSocketStream(ws, {
12
6
  ...options,
13
7
  readableObjectMode: true, // Ensures frame bytes don't get buffered/combined together
14
8
  });
15
9
  }
16
- async function* byFrame(ws, options) {
10
+ export async function* byFrame(ws, options) {
17
11
  const wsStream = streamByteChunks(ws, options);
18
12
  for await (const chunk of wsStream) {
19
- yield frames_1.Frame.fromBytes(chunk);
13
+ yield Frame.fromBytes(chunk);
20
14
  }
21
15
  }
22
- async function* byMessage(ws, options) {
16
+ export async function* byMessage(ws, options) {
23
17
  const wsStream = streamByteChunks(ws, options);
24
18
  for await (const chunk of wsStream) {
25
19
  const msg = ensureChunkIsMessage(chunk);
26
20
  yield msg;
27
21
  }
28
22
  }
29
- function ensureChunkIsMessage(chunk) {
30
- const frame = frames_1.Frame.fromBytes(chunk);
23
+ export function ensureChunkIsMessage(chunk) {
24
+ const frame = Frame.fromBytes(chunk);
31
25
  if (frame.isMessage()) {
32
26
  return frame;
33
27
  }
34
28
  else if (frame.isError()) {
35
29
  // @TODO work -1 error code into XRPCError
36
30
  // @ts-ignore
37
- throw new xrpc_1.XRPCError(-1, frame.code, frame.message);
31
+ throw new XRPCError(-1, frame.code, frame.message);
38
32
  }
39
33
  else {
40
- throw new xrpc_1.XRPCError(xrpc_1.ResponseType.Unknown, undefined, 'Unknown frame type');
34
+ throw new XRPCError(ResponseType.Unknown, undefined, 'Unknown frame type');
41
35
  }
42
36
  }
43
37
  //# sourceMappingURL=stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":";;AAKA,4CAKC;AAED,0BAKC;AAED,8BAMC;AAED,oDAWC;AArCD,2BAAqD;AACrD,wCAAuD;AACvD,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;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;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;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","sourcesContent":["import { DuplexOptions } from 'node:stream'\nimport { WebSocket, createWebSocketStream } from 'ws'\nimport { ResponseType, XRPCError } from '@atproto/xrpc'\nimport { Frame, MessageFrame } from './frames'\n\nexport function streamByteChunks(ws: WebSocket, options?: DuplexOptions) {\n return createWebSocketStream(ws, {\n ...options,\n readableObjectMode: true, // Ensures frame bytes don't get buffered/combined together\n })\n}\n\nexport async function* byFrame(ws: WebSocket, options?: DuplexOptions) {\n const wsStream = streamByteChunks(ws, options)\n for await (const chunk of wsStream) {\n yield Frame.fromBytes(chunk)\n }\n}\n\nexport async function* byMessage(ws: WebSocket, options?: DuplexOptions) {\n const wsStream = streamByteChunks(ws, options)\n for await (const chunk of wsStream) {\n const msg = ensureChunkIsMessage(chunk)\n yield msg\n }\n}\n\nexport function ensureChunkIsMessage(chunk: Uint8Array): MessageFrame {\n const frame = Frame.fromBytes(chunk)\n if (frame.isMessage()) {\n return frame\n } else if (frame.isError()) {\n // @TODO work -1 error code into XRPCError\n // @ts-ignore\n throw new XRPCError(-1, frame.code, frame.message)\n } else {\n throw new XRPCError(ResponseType.Unknown, undefined, 'Unknown frame type')\n }\n}\n"]}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream/stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,qBAAqB,EAAE,MAAM,IAAI,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAA;AAEjD,MAAM,UAAU,gBAAgB,CAAC,EAAa,EAAE,OAAuB;IACrE,OAAO,qBAAqB,CAAC,EAAE,EAAE;QAC/B,GAAG,OAAO;QACV,kBAAkB,EAAE,IAAI,EAAE,2DAA2D;KACtF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,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,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,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;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAiB;IACpD,MAAM,KAAK,GAAG,KAAK,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,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACpD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAA;IAC5E,CAAC;AACH,CAAC","sourcesContent":["import { DuplexOptions } from 'node:stream'\nimport { WebSocket, createWebSocketStream } from 'ws'\nimport { ResponseType, XRPCError } from '@atproto/xrpc'\nimport { Frame, MessageFrame } from './frames.js'\n\nexport function streamByteChunks(ws: WebSocket, options?: DuplexOptions) {\n return createWebSocketStream(ws, {\n ...options,\n readableObjectMode: true, // Ensures frame bytes don't get buffered/combined together\n })\n}\n\nexport async function* byFrame(ws: WebSocket, options?: DuplexOptions) {\n const wsStream = streamByteChunks(ws, options)\n for await (const chunk of wsStream) {\n yield Frame.fromBytes(chunk)\n }\n}\n\nexport async function* byMessage(ws: WebSocket, options?: DuplexOptions) {\n const wsStream = streamByteChunks(ws, options)\n for await (const chunk of wsStream) {\n const msg = ensureChunkIsMessage(chunk)\n yield msg\n }\n}\n\nexport function ensureChunkIsMessage(chunk: Uint8Array): MessageFrame {\n const frame = Frame.fromBytes(chunk)\n if (frame.isMessage()) {\n return frame\n } else if (frame.isError()) {\n // @TODO work -1 error code into XRPCError\n // @ts-ignore\n throw new XRPCError(-1, frame.code, frame.message)\n } else {\n throw new XRPCError(ResponseType.Unknown, undefined, 'Unknown frame type')\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { ClientOptions } from 'ws';
1
+ import type { ClientOptions } from 'ws';
2
2
  export declare class Subscription<T = unknown> {
3
3
  opts: ClientOptions & {
4
4
  service: string;
@@ -1 +1 @@
1
- {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAKlC,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;CA4BnD;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAKvC,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;CA4BnD;AAED,eAAe,YAAY,CAAA"}
@@ -1,20 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Subscription = void 0;
4
- const lex_data_1 = require("@atproto/lex-data");
5
- const ws_client_1 = require("@atproto/ws-client");
6
- const stream_1 = require("./stream");
7
- class Subscription {
1
+ import { isPlainObject } from '@atproto/lex-data';
2
+ import { WebSocketKeepAlive } from '@atproto/ws-client';
3
+ import { ensureChunkIsMessage } from './stream.js';
4
+ export class Subscription {
8
5
  constructor(opts) {
9
- Object.defineProperty(this, "opts", {
10
- enumerable: true,
11
- configurable: true,
12
- writable: true,
13
- value: opts
14
- });
6
+ this.opts = opts;
15
7
  }
16
8
  async *[Symbol.asyncIterator]() {
17
- const ws = new ws_client_1.WebSocketKeepAlive({
9
+ const ws = new WebSocketKeepAlive({
18
10
  ...this.opts,
19
11
  getUrl: async () => {
20
12
  const params = (await this.opts.getParams?.()) ?? {};
@@ -23,9 +15,9 @@ class Subscription {
23
15
  },
24
16
  });
25
17
  for await (const chunk of ws) {
26
- const message = (0, stream_1.ensureChunkIsMessage)(chunk);
18
+ const message = ensureChunkIsMessage(chunk);
27
19
  const t = message.header.t;
28
- const typedBody = (0, lex_data_1.isPlainObject)(message.body)
20
+ const typedBody = isPlainObject(message.body)
29
21
  ? t !== undefined
30
22
  ? {
31
23
  ...message.body,
@@ -40,8 +32,7 @@ class Subscription {
40
32
  }
41
33
  }
42
34
  }
43
- exports.Subscription = Subscription;
44
- exports.default = Subscription;
35
+ export default Subscription;
45
36
  function encodeQueryParams(obj) {
46
37
  const params = new URLSearchParams();
47
38
  Object.entries(obj).forEach(([key, value]) => {
@@ -1 +1 @@
1
- {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":"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","sourcesContent":["import { ClientOptions } from 'ws'\nimport { isPlainObject } from '@atproto/lex-data'\nimport { WebSocketKeepAlive } from '@atproto/ws-client'\nimport { ensureChunkIsMessage } from './stream'\n\nexport class Subscription<T = unknown> {\n constructor(\n public opts: ClientOptions & {\n service: string\n method: string\n maxReconnectSeconds?: number\n heartbeatIntervalMs?: number\n signal?: AbortSignal\n validate: (obj: unknown) => T | undefined\n onReconnectError?: (\n error: unknown,\n n: number,\n initialSetup: boolean,\n ) => void\n getParams?: () =>\n | Record<string, unknown>\n | Promise<Record<string, unknown> | undefined>\n | undefined\n },\n ) {}\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T> {\n const ws = new WebSocketKeepAlive({\n ...this.opts,\n getUrl: async () => {\n const params = (await this.opts.getParams?.()) ?? {}\n const query = encodeQueryParams(params)\n return `${this.opts.service}/xrpc/${this.opts.method}?${query}`\n },\n })\n for await (const chunk of ws) {\n const message = ensureChunkIsMessage(chunk)\n const t = message.header.t\n\n const typedBody = isPlainObject(message.body)\n ? t !== undefined\n ? {\n ...message.body,\n $type: t.startsWith('#') ? this.opts.method + t : t,\n }\n : message.body\n : undefined\n\n const result = this.opts.validate(typedBody)\n if (result !== undefined) {\n yield result\n }\n }\n }\n}\n\nexport default Subscription\n\nfunction encodeQueryParams(obj: Record<string, unknown>): string {\n const params = new URLSearchParams()\n Object.entries(obj).forEach(([key, value]) => {\n const encoded = encodeQueryParam(value)\n if (Array.isArray(encoded)) {\n encoded.forEach((enc) => params.append(key, enc))\n } else {\n params.set(key, encoded)\n }\n })\n return params.toString()\n}\n\n// Adapted from xrpc, but without any lex-specific knowledge\nfunction encodeQueryParam(value: unknown): string | string[] {\n if (typeof value === 'string') {\n return value\n }\n if (typeof value === 'number') {\n return value.toString()\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false'\n }\n if (typeof value === 'undefined') {\n return ''\n }\n if (typeof value === 'object') {\n if (value instanceof Date) {\n return value.toISOString()\n } else if (Array.isArray(value)) {\n return value.flatMap(encodeQueryParam)\n } else if (!value) {\n return ''\n }\n }\n throw new Error(`Cannot encode ${typeof value}s into query params`)\n}\n"]}
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/stream/subscription.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientOptions } from 'ws'\nimport { isPlainObject } from '@atproto/lex-data'\nimport { WebSocketKeepAlive } from '@atproto/ws-client'\nimport { ensureChunkIsMessage } from './stream.js'\n\nexport class Subscription<T = unknown> {\n constructor(\n public opts: ClientOptions & {\n service: string\n method: string\n maxReconnectSeconds?: number\n heartbeatIntervalMs?: number\n signal?: AbortSignal\n validate: (obj: unknown) => T | undefined\n onReconnectError?: (\n error: unknown,\n n: number,\n initialSetup: boolean,\n ) => void\n getParams?: () =>\n | Record<string, unknown>\n | Promise<Record<string, unknown> | undefined>\n | undefined\n },\n ) {}\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T> {\n const ws = new WebSocketKeepAlive({\n ...this.opts,\n getUrl: async () => {\n const params = (await this.opts.getParams?.()) ?? {}\n const query = encodeQueryParams(params)\n return `${this.opts.service}/xrpc/${this.opts.method}?${query}`\n },\n })\n for await (const chunk of ws) {\n const message = ensureChunkIsMessage(chunk)\n const t = message.header.t\n\n const typedBody = isPlainObject(message.body)\n ? t !== undefined\n ? {\n ...message.body,\n $type: t.startsWith('#') ? this.opts.method + t : t,\n }\n : message.body\n : undefined\n\n const result = this.opts.validate(typedBody)\n if (result !== undefined) {\n yield result\n }\n }\n }\n}\n\nexport default Subscription\n\nfunction encodeQueryParams(obj: Record<string, unknown>): string {\n const params = new URLSearchParams()\n Object.entries(obj).forEach(([key, value]) => {\n const encoded = encodeQueryParam(value)\n if (Array.isArray(encoded)) {\n encoded.forEach((enc) => params.append(key, enc))\n } else {\n params.set(key, encoded)\n }\n })\n return params.toString()\n}\n\n// Adapted from xrpc, but without any lex-specific knowledge\nfunction encodeQueryParam(value: unknown): string | string[] {\n if (typeof value === 'string') {\n return value\n }\n if (typeof value === 'number') {\n return value.toString()\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false'\n }\n if (typeof value === 'undefined') {\n return ''\n }\n if (typeof value === 'object') {\n if (value instanceof Date) {\n return value.toISOString()\n } else if (Array.isArray(value)) {\n return value.flatMap(encodeQueryParam)\n } else if (!value) {\n return ''\n }\n }\n throw new Error(`Cannot encode ${typeof value}s into query params`)\n}\n"]}
@@ -1,22 +1,19 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.frameHeader = exports.errorFrameBody = exports.errorFrameHeader = exports.messageFrameHeader = exports.FrameType = void 0;
4
- const lex_schema_1 = require("@atproto/lex-schema");
5
- var FrameType;
1
+ import { l } from '@atproto/lex-schema';
2
+ export var FrameType;
6
3
  (function (FrameType) {
7
4
  FrameType[FrameType["Message"] = 1] = "Message";
8
5
  FrameType[FrameType["Error"] = -1] = "Error";
9
- })(FrameType || (exports.FrameType = FrameType = {}));
10
- exports.messageFrameHeader = lex_schema_1.l.object({
11
- op: lex_schema_1.l.literal(FrameType.Message), // Frame op
12
- t: lex_schema_1.l.optional(lex_schema_1.l.string()), // Message body type discriminator
6
+ })(FrameType || (FrameType = {}));
7
+ export const messageFrameHeader = l.object({
8
+ op: l.literal(FrameType.Message), // Frame op
9
+ t: l.optional(l.string()), // Message body type discriminator
13
10
  });
14
- exports.errorFrameHeader = lex_schema_1.l.object({
15
- op: lex_schema_1.l.literal(FrameType.Error),
11
+ export const errorFrameHeader = l.object({
12
+ op: l.literal(FrameType.Error),
16
13
  });
17
- exports.errorFrameBody = lex_schema_1.l.object({
18
- error: lex_schema_1.l.string(), // Error code
19
- message: lex_schema_1.l.optional(lex_schema_1.l.string()), // Error message
14
+ export const errorFrameBody = l.object({
15
+ error: l.string(), // Error code
16
+ message: l.optional(l.string()), // Error message
20
17
  });
21
- exports.frameHeader = lex_schema_1.l.union([exports.messageFrameHeader, exports.errorFrameHeader]);
18
+ export const frameHeader = l.union([messageFrameHeader, errorFrameHeader]);
22
19
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":";;;AAAA,oDAAuC;AAEvC,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,+CAAW,CAAA;IACX,4CAAU,CAAA;AACZ,CAAC,EAHW,SAAS,yBAAT,SAAS,QAGpB;AAEY,QAAA,kBAAkB,GAAG,cAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,cAAC,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW;IAC7C,CAAC,EAAE,cAAC,CAAC,QAAQ,CAAC,cAAC,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC;CAC9D,CAAC,CAAA;AAGW,QAAA,gBAAgB,GAAG,cAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,cAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;CAC/B,CAAC,CAAA;AACW,QAAA,cAAc,GAAG,cAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,cAAC,CAAC,MAAM,EAAE,EAAE,aAAa;IAChC,OAAO,EAAE,cAAC,CAAC,QAAQ,CAAC,cAAC,CAAC,MAAM,EAAE,CAAC,EAAE,gBAAgB;CAClD,CAAC,CAAA;AAMW,QAAA,WAAW,GAAG,cAAC,CAAC,KAAK,CAAC,CAAC,0BAAkB,EAAE,wBAAgB,CAAC,CAAC,CAAA","sourcesContent":["import { l } from '@atproto/lex-schema'\n\nexport enum FrameType {\n Message = 1,\n Error = -1,\n}\n\nexport const messageFrameHeader = l.object({\n op: l.literal(FrameType.Message), // Frame op\n t: l.optional(l.string()), // Message body type discriminator\n})\nexport type MessageFrameHeader = l.Infer<typeof messageFrameHeader>\n\nexport const errorFrameHeader = l.object({\n op: l.literal(FrameType.Error),\n})\nexport const errorFrameBody = l.object({\n error: l.string(), // Error code\n message: l.optional(l.string()), // Error message\n})\nexport type ErrorFrameHeader = l.Infer<typeof errorFrameHeader>\nexport type ErrorFrameBody<T extends string = string> = { error: T } & l.Infer<\n typeof errorFrameBody\n>\n\nexport const frameHeader = l.union([messageFrameHeader, errorFrameHeader])\nexport type FrameHeader = l.Infer<typeof frameHeader>\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAA;AAEvC,MAAM,CAAN,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,+CAAW,CAAA;IACX,4CAAU,CAAA;AACZ,CAAC,EAHW,SAAS,KAAT,SAAS,QAGpB;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW;IAC7C,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC;CAC9D,CAAC,CAAA;AAGF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;CAC/B,CAAC,CAAA;AACF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,aAAa;IAChC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,gBAAgB;CAClD,CAAC,CAAA;AAMF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC,CAAA","sourcesContent":["import { l } from '@atproto/lex-schema'\n\nexport enum FrameType {\n Message = 1,\n Error = -1,\n}\n\nexport const messageFrameHeader = l.object({\n op: l.literal(FrameType.Message), // Frame op\n t: l.optional(l.string()), // Message body type discriminator\n})\nexport type MessageFrameHeader = l.Infer<typeof messageFrameHeader>\n\nexport const errorFrameHeader = l.object({\n op: l.literal(FrameType.Error),\n})\nexport const errorFrameBody = l.object({\n error: l.string(), // Error code\n message: l.optional(l.string()), // Error message\n})\nexport type ErrorFrameHeader = l.Infer<typeof errorFrameHeader>\nexport type ErrorFrameBody<T extends string = string> = { error: T } & l.Infer<\n typeof errorFrameBody\n>\n\nexport const frameHeader = l.union([messageFrameHeader, errorFrameHeader])\nexport type FrameHeader = l.Infer<typeof frameHeader>\n"]}
package/dist/types.d.ts CHANGED
@@ -2,8 +2,8 @@ import { IncomingMessage } from 'node:http';
2
2
  import { Readable } from 'node:stream';
3
3
  import { NextFunction, Request, Response } from 'express';
4
4
  import { l } from '@atproto/lex-schema';
5
- import { ErrorResult, XRPCError } from './errors';
6
- import { CalcKeyFn, CalcPointsFn, RateLimiterI } from './rate-limiter';
5
+ import { ErrorResult, XRPCError } from './errors.js';
6
+ import { CalcKeyFn, CalcPointsFn, RateLimiterI } from './rate-limiter.js';
7
7
  export type Awaitable<T> = T | Promise<T>;
8
8
  export type CatchallHandler = (req: Request, res: Response, next: NextFunction) => unknown;
9
9
  export type Options = {