@atproto/xrpc-server 0.4.3 → 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 (73) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/auth.d.ts +1 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +124 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +25 -53682
  9. package/dist/index.js.map +1 -7
  10. package/dist/logger.d.ts +1 -0
  11. package/dist/logger.d.ts.map +1 -0
  12. package/dist/logger.js +7 -0
  13. package/dist/logger.js.map +1 -0
  14. package/dist/rate-limiter.d.ts +1 -0
  15. package/dist/rate-limiter.d.ts.map +1 -0
  16. package/dist/rate-limiter.js +166 -0
  17. package/dist/rate-limiter.js.map +1 -0
  18. package/dist/server.d.ts +5 -4
  19. package/dist/server.d.ts.map +1 -0
  20. package/dist/server.js +472 -0
  21. package/dist/server.js.map +1 -0
  22. package/dist/stream/frames.d.ts +2 -1
  23. package/dist/stream/frames.d.ts.map +1 -0
  24. package/dist/stream/frames.js +141 -0
  25. package/dist/stream/frames.js.map +1 -0
  26. package/dist/stream/index.d.ts +1 -0
  27. package/dist/stream/index.d.ts.map +1 -0
  28. package/dist/stream/index.js +22 -0
  29. package/dist/stream/index.js.map +1 -0
  30. package/dist/stream/logger.d.ts +1 -0
  31. package/dist/stream/logger.d.ts.map +1 -0
  32. package/dist/stream/logger.js +7 -0
  33. package/dist/stream/logger.js.map +1 -0
  34. package/dist/stream/server.d.ts +2 -0
  35. package/dist/stream/server.d.ts.map +1 -0
  36. package/dist/stream/server.js +70 -0
  37. package/dist/stream/server.js.map +1 -0
  38. package/dist/stream/stream.d.ts +1 -0
  39. package/dist/stream/stream.d.ts.map +1 -0
  40. package/dist/stream/stream.js +44 -0
  41. package/dist/stream/stream.js.map +1 -0
  42. package/dist/stream/subscription.d.ts +2 -0
  43. package/dist/stream/subscription.d.ts.map +1 -0
  44. package/dist/stream/subscription.js +80 -0
  45. package/dist/stream/subscription.js.map +1 -0
  46. package/dist/stream/types.d.ts +1 -0
  47. package/dist/stream/types.d.ts.map +1 -0
  48. package/dist/stream/types.js +47 -0
  49. package/dist/stream/types.js.map +1 -0
  50. package/dist/stream/websocket-keepalive.d.ts +2 -0
  51. package/dist/stream/websocket-keepalive.d.ts.map +1 -0
  52. package/dist/stream/websocket-keepalive.js +160 -0
  53. package/dist/stream/websocket-keepalive.js.map +1 -0
  54. package/dist/types.d.ts +2 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +163 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/util.d.ts +1 -0
  59. package/dist/util.d.ts.map +1 -0
  60. package/dist/util.js +263 -0
  61. package/dist/util.js.map +1 -0
  62. package/jest.config.js +4 -3
  63. package/package.json +10 -11
  64. package/src/server.ts +11 -11
  65. package/src/stream/frames.ts +1 -1
  66. package/src/stream/websocket-keepalive.ts +2 -1
  67. package/tests/bodies.test.ts +4 -4
  68. package/tests/errors.test.ts +1 -1
  69. package/tsconfig.build.json +6 -2
  70. package/tsconfig.json +3 -11
  71. package/tsconfig.tests.json +7 -0
  72. package/babel.config.js +0 -1
  73. package/build.js +0 -14
package/dist/types.js ADDED
@@ -0,0 +1,163 @@
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.MethodNotImplementedError = exports.UpstreamTimeoutError = exports.NotEnoughResourcesError = exports.UpstreamFailureError = exports.InternalServerError = exports.RateLimitExceededError = exports.ForbiddenError = exports.AuthRequiredError = exports.InvalidRequestError = exports.isHandlerError = exports.XRPCError = exports.isShared = exports.handlerError = exports.handlerPipeThrough = exports.handlerSuccess = exports.handlerAuth = exports.handlerInput = void 0;
7
+ const http_errors_1 = require("http-errors");
8
+ const zod_1 = __importDefault(require("zod"));
9
+ const xrpc_1 = require("@atproto/xrpc");
10
+ exports.handlerInput = zod_1.default.object({
11
+ encoding: zod_1.default.string(),
12
+ body: zod_1.default.any(),
13
+ });
14
+ exports.handlerAuth = zod_1.default.object({
15
+ credentials: zod_1.default.any(),
16
+ artifacts: zod_1.default.any(),
17
+ });
18
+ exports.handlerSuccess = zod_1.default.object({
19
+ encoding: zod_1.default.string(),
20
+ body: zod_1.default.any(),
21
+ headers: zod_1.default.record(zod_1.default.string()).optional(),
22
+ });
23
+ exports.handlerPipeThrough = zod_1.default.object({
24
+ encoding: zod_1.default.string(),
25
+ buffer: zod_1.default.instanceof(ArrayBuffer),
26
+ headers: zod_1.default.record(zod_1.default.string()).optional(),
27
+ });
28
+ exports.handlerError = zod_1.default.object({
29
+ status: zod_1.default.number(),
30
+ error: zod_1.default.string().optional(),
31
+ message: zod_1.default.string().optional(),
32
+ });
33
+ const isShared = (opts) => {
34
+ return typeof opts['name'] === 'string';
35
+ };
36
+ exports.isShared = isShared;
37
+ class XRPCError extends Error {
38
+ constructor(type, errorMessage, customErrorName) {
39
+ super(errorMessage);
40
+ Object.defineProperty(this, "type", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: type
45
+ });
46
+ Object.defineProperty(this, "errorMessage", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: errorMessage
51
+ });
52
+ Object.defineProperty(this, "customErrorName", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: customErrorName
57
+ });
58
+ }
59
+ get payload() {
60
+ return {
61
+ error: this.customErrorName ?? this.typeName,
62
+ message: this.type === xrpc_1.ResponseType.InternalServerError
63
+ ? this.typeStr // Do not respond with error details for 500s
64
+ : this.errorMessage || this.typeStr,
65
+ };
66
+ }
67
+ get typeName() {
68
+ return xrpc_1.ResponseTypeNames[this.type];
69
+ }
70
+ get typeStr() {
71
+ return xrpc_1.ResponseTypeStrings[this.type];
72
+ }
73
+ static fromError(error) {
74
+ if (error instanceof XRPCError) {
75
+ return error;
76
+ }
77
+ let resultErr;
78
+ if ((0, http_errors_1.isHttpError)(error)) {
79
+ resultErr = new XRPCError(error.status, error.message, error.name);
80
+ }
81
+ else if (isHandlerError(error)) {
82
+ resultErr = new XRPCError(error.status, error.message, error.error);
83
+ }
84
+ else if (error instanceof Error) {
85
+ resultErr = new InternalServerError(error.message);
86
+ }
87
+ else {
88
+ resultErr = new InternalServerError('Unexpected internal server error');
89
+ }
90
+ resultErr.cause = error;
91
+ return resultErr;
92
+ }
93
+ }
94
+ exports.XRPCError = XRPCError;
95
+ function isHandlerError(v) {
96
+ return (!!v &&
97
+ typeof v === 'object' &&
98
+ typeof v['status'] === 'number' &&
99
+ (v['error'] === undefined || typeof v['error'] === 'string') &&
100
+ (v['message'] === undefined || typeof v['message'] === 'string'));
101
+ }
102
+ exports.isHandlerError = isHandlerError;
103
+ class InvalidRequestError extends XRPCError {
104
+ constructor(errorMessage, customErrorName) {
105
+ super(xrpc_1.ResponseType.InvalidRequest, errorMessage, customErrorName);
106
+ }
107
+ }
108
+ exports.InvalidRequestError = InvalidRequestError;
109
+ class AuthRequiredError extends XRPCError {
110
+ constructor(errorMessage, customErrorName) {
111
+ super(xrpc_1.ResponseType.AuthRequired, errorMessage, customErrorName);
112
+ }
113
+ }
114
+ exports.AuthRequiredError = AuthRequiredError;
115
+ class ForbiddenError extends XRPCError {
116
+ constructor(errorMessage, customErrorName) {
117
+ super(xrpc_1.ResponseType.Forbidden, errorMessage, customErrorName);
118
+ }
119
+ }
120
+ exports.ForbiddenError = ForbiddenError;
121
+ class RateLimitExceededError extends XRPCError {
122
+ constructor(status, errorMessage, customErrorName) {
123
+ super(xrpc_1.ResponseType.RateLimitExceeded, errorMessage, customErrorName);
124
+ Object.defineProperty(this, "status", {
125
+ enumerable: true,
126
+ configurable: true,
127
+ writable: true,
128
+ value: status
129
+ });
130
+ }
131
+ }
132
+ exports.RateLimitExceededError = RateLimitExceededError;
133
+ class InternalServerError extends XRPCError {
134
+ constructor(errorMessage, customErrorName) {
135
+ super(xrpc_1.ResponseType.InternalServerError, errorMessage, customErrorName);
136
+ }
137
+ }
138
+ exports.InternalServerError = InternalServerError;
139
+ class UpstreamFailureError extends XRPCError {
140
+ constructor(errorMessage, customErrorName) {
141
+ super(xrpc_1.ResponseType.UpstreamFailure, errorMessage, customErrorName);
142
+ }
143
+ }
144
+ exports.UpstreamFailureError = UpstreamFailureError;
145
+ class NotEnoughResourcesError extends XRPCError {
146
+ constructor(errorMessage, customErrorName) {
147
+ super(xrpc_1.ResponseType.NotEnoughResources, errorMessage, customErrorName);
148
+ }
149
+ }
150
+ exports.NotEnoughResourcesError = NotEnoughResourcesError;
151
+ class UpstreamTimeoutError extends XRPCError {
152
+ constructor(errorMessage, customErrorName) {
153
+ super(xrpc_1.ResponseType.UpstreamTimeout, errorMessage, customErrorName);
154
+ }
155
+ }
156
+ exports.UpstreamTimeoutError = UpstreamTimeoutError;
157
+ class MethodNotImplementedError extends XRPCError {
158
+ constructor(errorMessage, customErrorName) {
159
+ super(xrpc_1.ResponseType.MethodNotImplemented, errorMessage, customErrorName);
160
+ }
161
+ }
162
+ exports.MethodNotImplementedError = MethodNotImplementedError;
163
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/util.d.ts CHANGED
@@ -24,3 +24,4 @@ export interface ServerTiming {
24
24
  duration?: number;
25
25
  description?: string;
26
26
  }
27
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,EAEL,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,eAAe,EACf,MAAM,EACN,YAAY,EACZ,cAAc,EAKd,SAAS,EACV,MAAM,SAAS,CAAA;AAEhB,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,gBAAgB,GAAG,YAAY,GAAG,mBAAmB,EAC1D,MAAM,EAAE,eAAe,GACtB,MAAM,CAmBR;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAcvC;AAED,wBAAgB,cAAc,CAAC,GAAG,SAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAU1E;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,GAAG,YAAY,EACpC,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,QAAQ,GACjB,YAAY,GAAG,SAAS,CA8D1B;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,GAAG,YAAY,EACpC,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,QAAQ,EAAE,QAAQ,GACjB,cAAc,GAAG,SAAS,CA0C5B;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,OAOtC;AAUD,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,6BAI3C;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAM5E;AA0CD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,UASzD;AAED,qBAAa,WAAY,YAAW,YAAY;IAG3B,IAAI,EAAE,MAAM;IAAS,WAAW,CAAC;IAF7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,OAAO,CAAC,CAAQ;gBACL,IAAI,EAAE,MAAM,EAAS,WAAW,CAAC,oBAAQ;IAC5D,KAAK;IAIL,IAAI;CAKL;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB"}
package/dist/util.js ADDED
@@ -0,0 +1,263 @@
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.ServerTimer = exports.serverTimingHeader = exports.processBodyAsBytes = exports.hasBody = exports.normalizeMime = exports.validateOutput = exports.validateInput = exports.getQueryParams = exports.decodeQueryParam = exports.decodeQueryParams = void 0;
7
+ const assert_1 = __importDefault(require("assert"));
8
+ const zlib_1 = require("zlib");
9
+ const mime_types_1 = __importDefault(require("mime-types"));
10
+ const lexicon_1 = require("@atproto/lexicon");
11
+ const common_1 = require("@atproto/common");
12
+ const types_1 = require("./types");
13
+ function decodeQueryParams(def, params) {
14
+ const decoded = {};
15
+ for (const k in params) {
16
+ const val = params[k];
17
+ const property = def.parameters?.properties?.[k];
18
+ if (property) {
19
+ if (property.type === 'array') {
20
+ const vals = [];
21
+ decoded[k] = val
22
+ ? vals
23
+ .concat(val) // Cast to array
24
+ .flatMap((v) => decodeQueryParam(property.items.type, v) ?? [])
25
+ : undefined;
26
+ }
27
+ else {
28
+ decoded[k] = decodeQueryParam(property.type, val);
29
+ }
30
+ }
31
+ }
32
+ return decoded;
33
+ }
34
+ exports.decodeQueryParams = decodeQueryParams;
35
+ function decodeQueryParam(type, value) {
36
+ if (!value) {
37
+ return undefined;
38
+ }
39
+ if (type === 'string' || type === 'datetime') {
40
+ return String(value);
41
+ }
42
+ if (type === 'float') {
43
+ return Number(String(value));
44
+ }
45
+ else if (type === 'integer') {
46
+ return parseInt(String(value), 10) || 0;
47
+ }
48
+ else if (type === 'boolean') {
49
+ return value === 'true';
50
+ }
51
+ }
52
+ exports.decodeQueryParam = decodeQueryParam;
53
+ function getQueryParams(url = '') {
54
+ const { searchParams } = new URL(url ?? '', 'http://x');
55
+ const result = {};
56
+ for (const key of searchParams.keys()) {
57
+ result[key] = searchParams.getAll(key);
58
+ if (result[key].length === 1) {
59
+ result[key] = result[key][0];
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ exports.getQueryParams = getQueryParams;
65
+ function validateInput(nsid, def, req, opts, lexicons) {
66
+ // request expectation
67
+ const reqHasBody = hasBody(req);
68
+ if (reqHasBody && (def.type !== 'procedure' || !def.input)) {
69
+ throw new types_1.InvalidRequestError(`A request body was provided when none was expected`);
70
+ }
71
+ if (def.type === 'query') {
72
+ return;
73
+ }
74
+ if (!reqHasBody && def.input) {
75
+ throw new types_1.InvalidRequestError(`A request body is expected but none was provided`);
76
+ }
77
+ // mimetype
78
+ const inputEncoding = normalizeMime(req.headers['content-type'] || '');
79
+ if (def.input?.encoding &&
80
+ (!inputEncoding || !isValidEncoding(def.input?.encoding, inputEncoding))) {
81
+ if (!inputEncoding) {
82
+ throw new types_1.InvalidRequestError(`Request encoding (Content-Type) required but not provided`);
83
+ }
84
+ else {
85
+ throw new types_1.InvalidRequestError(`Wrong request encoding (Content-Type): ${inputEncoding}`);
86
+ }
87
+ }
88
+ if (!inputEncoding) {
89
+ // no input body
90
+ return undefined;
91
+ }
92
+ // if input schema, validate
93
+ if (def.input?.schema) {
94
+ try {
95
+ const lexBody = req.body ? (0, lexicon_1.jsonToLex)(req.body) : req.body;
96
+ req.body = lexicons.assertValidXrpcInput(nsid, lexBody);
97
+ }
98
+ catch (e) {
99
+ throw new types_1.InvalidRequestError(e instanceof Error ? e.message : String(e));
100
+ }
101
+ }
102
+ // if middleware already got the body, we pass that along as input
103
+ // otherwise, we pass along a decoded readable stream
104
+ let body;
105
+ if (req.readableEnded) {
106
+ body = req.body;
107
+ }
108
+ else {
109
+ body = decodeBodyStream(req, opts.blobLimit);
110
+ }
111
+ return {
112
+ encoding: inputEncoding,
113
+ body,
114
+ };
115
+ }
116
+ exports.validateInput = validateInput;
117
+ function validateOutput(nsid, def, output, lexicons) {
118
+ // initial validation
119
+ if (output) {
120
+ types_1.handlerSuccess.parse(output);
121
+ }
122
+ // response expectation
123
+ if (output?.body && !def.output) {
124
+ throw new types_1.InternalServerError(`A response body was provided when none was expected`);
125
+ }
126
+ if (!output?.body && def.output) {
127
+ throw new types_1.InternalServerError(`A response body is expected but none was provided`);
128
+ }
129
+ // mimetype
130
+ if (def.output?.encoding &&
131
+ (!output?.encoding ||
132
+ !isValidEncoding(def.output?.encoding, output?.encoding))) {
133
+ throw new types_1.InternalServerError(`Invalid response encoding: ${output?.encoding}`);
134
+ }
135
+ // output schema
136
+ if (def.output?.schema) {
137
+ try {
138
+ const result = lexicons.assertValidXrpcOutput(nsid, output?.body);
139
+ if (output) {
140
+ output.body = result;
141
+ }
142
+ }
143
+ catch (e) {
144
+ throw new types_1.InternalServerError(e instanceof Error ? e.message : String(e));
145
+ }
146
+ }
147
+ return output;
148
+ }
149
+ exports.validateOutput = validateOutput;
150
+ function normalizeMime(v) {
151
+ if (!v)
152
+ return false;
153
+ const fullType = mime_types_1.default.contentType(v);
154
+ if (!fullType)
155
+ return false;
156
+ const shortType = fullType.split(';')[0];
157
+ if (!shortType)
158
+ return false;
159
+ return shortType;
160
+ }
161
+ exports.normalizeMime = normalizeMime;
162
+ function isValidEncoding(possibleStr, value) {
163
+ const possible = possibleStr.split(',').map((v) => v.trim());
164
+ const normalized = normalizeMime(value);
165
+ if (!normalized)
166
+ return false;
167
+ if (possible.includes('*/*'))
168
+ return true;
169
+ return possible.includes(normalized);
170
+ }
171
+ function hasBody(req) {
172
+ const contentLength = req.headers['content-length'];
173
+ const transferEncoding = req.headers['transfer-encoding'];
174
+ return (contentLength && parseInt(contentLength, 10) > 0) || transferEncoding;
175
+ }
176
+ exports.hasBody = hasBody;
177
+ function processBodyAsBytes(req) {
178
+ return new Promise((resolve) => {
179
+ const chunks = [];
180
+ req.on('data', (chunk) => chunks.push(chunk));
181
+ req.on('end', () => resolve(new Uint8Array(Buffer.concat(chunks))));
182
+ });
183
+ }
184
+ exports.processBodyAsBytes = processBodyAsBytes;
185
+ function decodeBodyStream(req, maxSize) {
186
+ let stream = req;
187
+ const contentEncoding = req.headers['content-encoding'];
188
+ const contentLength = req.headers['content-length'];
189
+ if (maxSize !== undefined &&
190
+ contentLength &&
191
+ parseInt(contentLength, 10) > maxSize) {
192
+ throw new types_1.XRPCError(413, 'request entity too large');
193
+ }
194
+ let decoder;
195
+ if (contentEncoding === 'gzip') {
196
+ decoder = (0, zlib_1.createGunzip)();
197
+ }
198
+ else if (contentEncoding === 'deflate') {
199
+ decoder = (0, zlib_1.createDeflate)();
200
+ }
201
+ if (decoder) {
202
+ (0, common_1.forwardStreamErrors)(stream, decoder);
203
+ stream = stream.pipe(decoder);
204
+ }
205
+ if (maxSize !== undefined) {
206
+ const maxSizeChecker = new common_1.MaxSizeChecker(maxSize, () => new types_1.XRPCError(413, 'request entity too large'));
207
+ (0, common_1.forwardStreamErrors)(stream, maxSizeChecker);
208
+ stream = stream.pipe(maxSizeChecker);
209
+ }
210
+ return stream;
211
+ }
212
+ function serverTimingHeader(timings) {
213
+ return timings
214
+ .map((timing) => {
215
+ let header = timing.name;
216
+ if (timing.duration)
217
+ header += `;dur=${timing.duration}`;
218
+ if (timing.description)
219
+ header += `;desc="${timing.description}"`;
220
+ return header;
221
+ })
222
+ .join(', ');
223
+ }
224
+ exports.serverTimingHeader = serverTimingHeader;
225
+ class ServerTimer {
226
+ constructor(name, description) {
227
+ Object.defineProperty(this, "name", {
228
+ enumerable: true,
229
+ configurable: true,
230
+ writable: true,
231
+ value: name
232
+ });
233
+ Object.defineProperty(this, "description", {
234
+ enumerable: true,
235
+ configurable: true,
236
+ writable: true,
237
+ value: description
238
+ });
239
+ Object.defineProperty(this, "duration", {
240
+ enumerable: true,
241
+ configurable: true,
242
+ writable: true,
243
+ value: void 0
244
+ });
245
+ Object.defineProperty(this, "startMs", {
246
+ enumerable: true,
247
+ configurable: true,
248
+ writable: true,
249
+ value: void 0
250
+ });
251
+ }
252
+ start() {
253
+ this.startMs = Date.now();
254
+ return this;
255
+ }
256
+ stop() {
257
+ (0, assert_1.default)(this.startMs, "timer hasn't been started");
258
+ this.duration = Date.now() - this.startMs;
259
+ return this;
260
+ }
261
+ }
262
+ exports.ServerTimer = ServerTimer;
263
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
package/jest.config.js CHANGED
@@ -1,6 +1,7 @@
1
- const base = require('../../jest.config.base.js')
2
-
1
+ /** @type {import('jest').Config} */
3
2
  module.exports = {
4
- ...base,
5
3
  displayName: 'XRPC Server',
4
+ transform: { '^.+\\.(t|j)s$': '@swc/jest' },
5
+ transformIgnorePatterns: [`<rootDir>/node_modules/(?!get-port)`],
6
+ setupFiles: ['<rootDir>/../../jest.setup.ts'],
6
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/xrpc-server",
3
- "version": "0.4.3",
3
+ "version": "0.4.4-next.0",
4
4
  "license": "MIT",
5
5
  "description": "atproto HTTP API (XRPC) server library",
6
6
  "keywords": [
@@ -14,6 +14,7 @@
14
14
  "directory": "packages/xrpc-server"
15
15
  },
16
16
  "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
17
18
  "dependencies": {
18
19
  "cbor-x": "^1.5.1",
19
20
  "express": "^4.17.2",
@@ -23,9 +24,9 @@
23
24
  "uint8arrays": "3.0.0",
24
25
  "ws": "^8.12.0",
25
26
  "zod": "^3.21.4",
26
- "@atproto/common": "^0.3.3",
27
- "@atproto/crypto": "^0.3.0",
28
- "@atproto/lexicon": "^0.3.2"
27
+ "@atproto/common": "^0.3.4-next.0",
28
+ "@atproto/lexicon": "^0.3.3-next.0",
29
+ "@atproto/crypto": "^0.3.1-next.0"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@types/express": "^4.17.13",
@@ -34,16 +35,14 @@
34
35
  "@types/ws": "^8.5.4",
35
36
  "get-port": "^6.1.2",
36
37
  "jose": "^4.15.4",
38
+ "jest": "^28.1.2",
37
39
  "key-encoder": "^2.0.3",
38
40
  "multiformats": "^9.9.0",
39
- "@atproto/xrpc": "^0.4.2",
40
- "@atproto/crypto": "^0.3.0"
41
+ "@atproto/crypto": "^0.3.1-next.0",
42
+ "@atproto/xrpc": "^0.4.3-next.0"
41
43
  },
42
44
  "scripts": {
43
45
  "test": "jest",
44
- "build": "node ./build.js",
45
- "postbuild": "tsc --build tsconfig.build.json",
46
- "update-main-to-dist": "node ../../update-main-to-dist.js packages/xrpc-server"
47
- },
48
- "types": "dist/index.d.ts"
46
+ "build": "tsc --build tsconfig.build.json"
47
+ }
49
48
  }
package/src/server.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { Readable } from 'stream'
2
2
  import express, {
3
+ Application,
4
+ Express,
5
+ Router,
6
+ Request,
7
+ Response,
3
8
  ErrorRequestHandler,
4
9
  NextFunction,
5
10
  RequestHandler,
@@ -37,7 +42,6 @@ import {
37
42
  isShared,
38
43
  RateLimitExceededError,
39
44
  HandlerPipeThrough,
40
- handlerPipeThrough,
41
45
  } from './types'
42
46
  import {
43
47
  decodeQueryParams,
@@ -53,8 +57,8 @@ export function createServer(lexicons?: LexiconDoc[], options?: Options) {
53
57
  }
54
58
 
55
59
  export class Server {
56
- router = express()
57
- routes = express.Router()
60
+ router: Express = express()
61
+ routes: Router = express.Router()
58
62
  subscriptions = new Map<string, XrpcStreamServer>()
59
63
  lex = new Lexicons()
60
64
  options: Options
@@ -70,7 +74,7 @@ export class Server {
70
74
  this.router.use(this.routes)
71
75
  this.router.use('/xrpc/:methodId', this.catchall.bind(this))
72
76
  this.router.use(errorMiddleware)
73
- this.router.once('mount', (app: express.Application) => {
77
+ this.router.once('mount', (app: Application) => {
74
78
  this.enableStreamingOnListen(app)
75
79
  })
76
80
  this.options = opts ?? {}
@@ -179,11 +183,7 @@ export class Server {
179
183
  )
180
184
  }
181
185
 
182
- async catchall(
183
- req: express.Request,
184
- _res: express.Response,
185
- next: NextFunction,
186
- ) {
186
+ async catchall(req: Request, _res: Response, next: NextFunction) {
187
187
  const def = this.lex.getDef(req.params.methodId)
188
188
  if (!def) {
189
189
  return next(new MethodNotImplementedError())
@@ -213,7 +213,7 @@ export class Server {
213
213
  const routeOpts = {
214
214
  blobLimit: routeCfg.opts?.blobLimit ?? this.options.payload?.blobLimit,
215
215
  }
216
- const validateReqInput = (req: express.Request) =>
216
+ const validateReqInput = (req: Request) =>
217
217
  validateInput(nsid, def, req, routeOpts, this.lex)
218
218
  const validateResOutput =
219
219
  this.options.validateResponse === false
@@ -390,7 +390,7 @@ export class Server {
390
390
  )
391
391
  }
392
392
 
393
- private enableStreamingOnListen(app: express.Application) {
393
+ private enableStreamingOnListen(app: Application) {
394
394
  const _listen = app.listen
395
395
  app.listen = (...args) => {
396
396
  // @ts-ignore the args spread
@@ -11,7 +11,7 @@ import {
11
11
  } from './types'
12
12
 
13
13
  export abstract class Frame {
14
- header: FrameHeader
14
+ abstract header: FrameHeader
15
15
  body: unknown
16
16
  get op(): FrameType {
17
17
  return this.header.op
@@ -80,7 +80,7 @@ export class WebSocketKeepAlive {
80
80
 
81
81
  startHeartbeat(ws: WebSocket) {
82
82
  let isAlive = true
83
- let heartbeatInterval: NodeJS.Timer | null = null
83
+ let heartbeatInterval: NodeJS.Timeout | null = null
84
84
 
85
85
  const checkAlive = () => {
86
86
  if (!isAlive) {
@@ -145,6 +145,7 @@ function forwardSignal(signal: AbortSignal, ac: AbortController) {
145
145
  return ac.abort(signal.reason)
146
146
  } else {
147
147
  signal.addEventListener('abort', () => ac.abort(signal.reason), {
148
+ // @ts-ignore https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68625
148
149
  signal: ac.signal,
149
150
  })
150
151
  }
@@ -274,9 +274,9 @@ describe('Bodies', () => {
274
274
  const resBody = await res.json()
275
275
  const status = res.status
276
276
  expect(status).toBe(400)
277
- expect(resBody.error).toBe('InvalidRequest')
278
- expect(resBody.message).toBe(
279
- 'Request encoding (Content-Type) required but not provided',
280
- )
277
+ expect(resBody).toMatchObject({
278
+ error: 'InvalidRequest',
279
+ message: 'Request encoding (Content-Type) required but not provided',
280
+ })
281
281
  })
282
282
  })
@@ -75,7 +75,7 @@ const LEXICONS: LexiconDoc[] = [
75
75
  },
76
76
  ]
77
77
 
78
- const MISMATCHED_LEXICONS = [
78
+ const MISMATCHED_LEXICONS: LexiconDoc[] = [
79
79
  {
80
80
  lexicon: 1,
81
81
  id: 'io.example.query',
@@ -1,4 +1,8 @@
1
1
  {
2
- "extends": "./tsconfig.json",
3
- "exclude": ["**/*.spec.ts", "**/*.test.ts"]
2
+ "extends": "../../tsconfig/node.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./dist"
6
+ },
7
+ "include": ["./src"]
4
8
  }