@atproto/xrpc-server 0.10.14 → 0.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/auth.d.ts +3 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +18 -0
- package/dist/auth.js.map +1 -1
- package/dist/errors.d.ts +7 -14
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +19 -6
- package/dist/errors.js.map +1 -1
- package/dist/server.d.ts +27 -11
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +115 -78
- package/dist/server.js.map +1 -1
- package/dist/stream/frames.d.ts +5 -1
- package/dist/stream/frames.d.ts.map +1 -1
- package/dist/stream/frames.js +32 -5
- package/dist/stream/frames.js.map +1 -1
- package/dist/stream/types.d.ts +18 -44
- package/dist/stream/types.d.ts.map +1 -1
- package/dist/stream/types.js +10 -10
- package/dist/stream/types.js.map +1 -1
- package/dist/types.d.ts +47 -70
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +28 -15
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +18 -9
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +180 -37
- package/dist/util.js.map +1 -1
- package/package.json +11 -7
- package/src/auth.ts +28 -2
- package/src/errors.ts +23 -7
- package/src/server.ts +307 -111
- package/src/stream/frames.ts +39 -6
- package/src/stream/types.ts +14 -14
- package/src/types.ts +106 -25
- package/src/util.ts +272 -60
- package/tests/_util.ts +62 -5
- package/tests/bodies.test.ts +442 -387
- package/tests/procedures.test.ts +71 -52
- package/tests/queries.test.ts +56 -39
- package/tests/subscriptions.test.ts +234 -221
package/dist/server.js
CHANGED
|
@@ -42,7 +42,7 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
42
42
|
const node_stream_1 = require("node:stream");
|
|
43
43
|
const promises_1 = require("node:stream/promises");
|
|
44
44
|
const express_1 = __importStar(require("express"));
|
|
45
|
-
const
|
|
45
|
+
const lex_schema_1 = require("@atproto/lex-schema");
|
|
46
46
|
const lexicon_1 = require("@atproto/lexicon");
|
|
47
47
|
const errors_1 = require("./errors");
|
|
48
48
|
const logger_1 = __importStar(require("./logger"));
|
|
@@ -168,8 +168,53 @@ class Server {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
listen(port, callback) {
|
|
172
|
+
return this.router.listen(port, callback);
|
|
173
|
+
}
|
|
174
|
+
add(ns, configOfHandler) {
|
|
175
|
+
const schema = lex_schema_1.l.getMain(ns);
|
|
176
|
+
const config = typeof configOfHandler === 'function'
|
|
177
|
+
? { handler: configOfHandler }
|
|
178
|
+
: configOfHandler;
|
|
179
|
+
switch (schema.type) {
|
|
180
|
+
case 'procedure':
|
|
181
|
+
return this.addProcedureSchema(schema, config);
|
|
182
|
+
case 'query':
|
|
183
|
+
return this.addQuerySchema(schema, config);
|
|
184
|
+
case 'subscription':
|
|
185
|
+
return this.addSubscriptionSchema(schema, config);
|
|
186
|
+
default:
|
|
187
|
+
throw new TypeError(
|
|
188
|
+
// @ts-expect-error should never happen
|
|
189
|
+
`Unsupported schema ${schema.nsid} of type ${schema.type}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
addProcedureSchema(schema, config) {
|
|
193
|
+
this.routes.post(`/xrpc/${schema.nsid}`, this.createHandlerInternal(this.createAuthVerifier(config), this.createSchemaParamsVerifier(schema), this.createSchemaInputVerifier(schema, config.opts), this.createRouteRateLimiter(schema.nsid, config), config.handler, this.createSchemaOutputVerifier(schema)));
|
|
194
|
+
}
|
|
195
|
+
addQuerySchema(schema, config) {
|
|
196
|
+
this.routes.get(`/xrpc/${schema.nsid}`, this.createHandlerInternal(this.createAuthVerifier(config), this.createSchemaParamsVerifier(schema), this.createSchemaInputVerifier(schema, config.opts), this.createRouteRateLimiter(schema.nsid, config), config.handler, this.createSchemaOutputVerifier(schema)));
|
|
197
|
+
}
|
|
198
|
+
addSubscriptionSchema(schema, config) {
|
|
199
|
+
const { handler } = config;
|
|
200
|
+
const messageSchema = this.options.validateResponse === false ? undefined : schema.message;
|
|
201
|
+
return this.addSubscriptionInternal(schema.nsid, this.createSchemaParamsVerifier(schema), this.createAuthVerifier(config),
|
|
202
|
+
// Wrap the handler to validate outgoing messages if a message schema
|
|
203
|
+
// is available
|
|
204
|
+
messageSchema
|
|
205
|
+
? async function* (ctx) {
|
|
206
|
+
for await (const item of handler(ctx)) {
|
|
207
|
+
if (item instanceof stream_1.Frame) {
|
|
208
|
+
messageSchema.validate(item.body);
|
|
209
|
+
yield item;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
yield messageSchema.validate(item);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
: handler);
|
|
217
|
+
}
|
|
173
218
|
method(nsid, configOrFn) {
|
|
174
219
|
this.addMethod(nsid, configOrFn);
|
|
175
220
|
}
|
|
@@ -218,42 +263,10 @@ class Server {
|
|
|
218
263
|
this.routes.get(path, handler);
|
|
219
264
|
}
|
|
220
265
|
}
|
|
221
|
-
createParamsVerifier(nsid, def) {
|
|
222
|
-
return (req) => {
|
|
223
|
-
const queryParams = 'query' in req ? req.query : (0, util_1.getQueryParams)(req.url);
|
|
224
|
-
const params = (0, util_1.decodeQueryParams)(def, queryParams);
|
|
225
|
-
try {
|
|
226
|
-
return this.lex.assertValidXrpcParams(nsid, params);
|
|
227
|
-
}
|
|
228
|
-
catch (e) {
|
|
229
|
-
throw new errors_1.InvalidRequestError(String(e));
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
createInputVerifier(nsid, def, routeOpts) {
|
|
234
|
-
return (0, util_1.createInputVerifier)(nsid, def, routeOpts, this.lex);
|
|
235
|
-
}
|
|
236
|
-
createAuthVerifier(cfg) {
|
|
237
|
-
const { auth } = cfg;
|
|
238
|
-
if (!auth)
|
|
239
|
-
return null;
|
|
240
|
-
return async (ctx) => {
|
|
241
|
-
const result = await auth(ctx);
|
|
242
|
-
return (0, errors_1.excludeErrorResult)(result);
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
266
|
createHandler(nsid, def, cfg) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
blobLimit: cfg.opts?.blobLimit ?? this.options.payload?.blobLimit,
|
|
250
|
-
jsonLimit: cfg.opts?.jsonLimit ?? this.options.payload?.jsonLimit,
|
|
251
|
-
textLimit: cfg.opts?.textLimit ?? this.options.payload?.textLimit,
|
|
252
|
-
});
|
|
253
|
-
const validateResOutput = this.options.validateResponse === false
|
|
254
|
-
? null
|
|
255
|
-
: (output) => (0, util_1.validateOutput)(nsid, def, output, this.lex);
|
|
256
|
-
const routeLimiter = this.createRouteRateLimiter(nsid, cfg);
|
|
267
|
+
return this.createHandlerInternal(this.createAuthVerifier(cfg), this.createLexiconParamsVerifier(nsid, def), this.createLexiconInputVerifier(nsid, def, cfg.opts), this.createRouteRateLimiter(nsid, cfg), cfg.handler, this.createLexiconOutputVerifier(nsid, def));
|
|
268
|
+
}
|
|
269
|
+
createHandlerInternal(authVerifier, paramsVerifier, inputVerifier, routeLimiter, handler, validateResOutput) {
|
|
257
270
|
return async function (req, res, next) {
|
|
258
271
|
try {
|
|
259
272
|
// parse & validate params
|
|
@@ -276,7 +289,7 @@ class Server {
|
|
|
276
289
|
if (routeLimiter)
|
|
277
290
|
await routeLimiter.handle(ctx);
|
|
278
291
|
// run the handler
|
|
279
|
-
const output = await
|
|
292
|
+
const output = (await handler(ctx));
|
|
280
293
|
if (!output) {
|
|
281
294
|
validateResOutput?.(output);
|
|
282
295
|
res.status(200);
|
|
@@ -294,24 +307,22 @@ class Server {
|
|
|
294
307
|
res.header('Content-Type', output.encoding);
|
|
295
308
|
res.end(output.buffer);
|
|
296
309
|
}
|
|
297
|
-
else if ((0,
|
|
298
|
-
next(errors_1.XRPCError.fromError(output));
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
310
|
+
else if ((0, types_1.isHandlerSuccess)(output)) {
|
|
301
311
|
validateResOutput?.(output);
|
|
302
312
|
res.status(200);
|
|
303
313
|
(0, util_1.setHeaders)(res, output.headers);
|
|
304
|
-
|
|
305
|
-
|
|
314
|
+
const encoding = output.encoding === 'json' ? 'application/json' : output.encoding;
|
|
315
|
+
res.header('Content-Type', encoding);
|
|
316
|
+
if (output.body instanceof node_stream_1.Readable) {
|
|
317
|
+
// The "Readable" check comes first to avoid calling "lexToJson" on
|
|
318
|
+
// a stream, which would be a bug.
|
|
319
|
+
await (0, promises_1.pipeline)(output.body, res);
|
|
320
|
+
}
|
|
321
|
+
else if (encoding === 'application/json') {
|
|
306
322
|
const json = (0, lexicon_1.lexToJson)(output.body);
|
|
307
323
|
res.json(json);
|
|
308
324
|
}
|
|
309
|
-
else if (output.body instanceof node_stream_1.Readable) {
|
|
310
|
-
res.header('Content-Type', output.encoding);
|
|
311
|
-
await (0, promises_1.pipeline)(output.body, res);
|
|
312
|
-
}
|
|
313
325
|
else {
|
|
314
|
-
res.header('Content-Type', output.encoding);
|
|
315
326
|
res.send(Buffer.isBuffer(output.body)
|
|
316
327
|
? output.body
|
|
317
328
|
: output.body instanceof Uint8Array
|
|
@@ -319,6 +330,9 @@ class Server {
|
|
|
319
330
|
: output.body);
|
|
320
331
|
}
|
|
321
332
|
}
|
|
333
|
+
else {
|
|
334
|
+
next(errors_1.XRPCError.fromError(output));
|
|
335
|
+
}
|
|
322
336
|
}
|
|
323
337
|
catch (err) {
|
|
324
338
|
// Express will not call the next middleware (errorMiddleware in this case)
|
|
@@ -334,9 +348,12 @@ class Server {
|
|
|
334
348
|
};
|
|
335
349
|
}
|
|
336
350
|
async addSubscription(nsid, def, cfg) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
351
|
+
this.addSubscriptionInternal(nsid, this.createLexiconParamsVerifier(nsid, def), this.createAuthVerifier(cfg),
|
|
352
|
+
// @NOTE outgoing messages are not validated against the lexicon schema
|
|
353
|
+
// (unlike the handlers for @atproto/lex based subscriptions)
|
|
354
|
+
cfg.handler);
|
|
355
|
+
}
|
|
356
|
+
addSubscriptionInternal(nsid, paramsVerifier, authVerifier, handler) {
|
|
340
357
|
this.subscriptions.set(nsid, new stream_1.XrpcStreamServer({
|
|
341
358
|
noServer: true,
|
|
342
359
|
handler: async function* (req, signal) {
|
|
@@ -349,38 +366,58 @@ class Server {
|
|
|
349
366
|
: undefined;
|
|
350
367
|
// stream
|
|
351
368
|
for await (const item of handler({ req, params, auth, signal })) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
const type = item?.['$type'];
|
|
357
|
-
if (!common_1.check.is(item, common_1.schema.map) || typeof type !== 'string') {
|
|
358
|
-
yield new stream_1.MessageFrame(item);
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
const split = type.split('#');
|
|
362
|
-
let t;
|
|
363
|
-
if (split.length === 2 &&
|
|
364
|
-
(split[0] === '' || split[0] === nsid)) {
|
|
365
|
-
t = `#${split[1]}`;
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
t = type;
|
|
369
|
-
}
|
|
370
|
-
const { $type: _, ...clone } = item;
|
|
371
|
-
yield new stream_1.MessageFrame(clone, { type: t });
|
|
369
|
+
yield item instanceof stream_1.Frame
|
|
370
|
+
? item
|
|
371
|
+
: stream_1.MessageFrame.fromLexValue(item, nsid);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
374
|
catch (err) {
|
|
375
|
-
|
|
376
|
-
yield new stream_1.ErrorFrame({
|
|
377
|
-
error: xrpcErrPayload.error ?? 'Unknown',
|
|
378
|
-
message: xrpcErrPayload.message,
|
|
379
|
-
});
|
|
375
|
+
yield stream_1.ErrorFrame.fromError(err);
|
|
380
376
|
}
|
|
381
377
|
},
|
|
382
378
|
}));
|
|
383
379
|
}
|
|
380
|
+
createAuthVerifier(cfg) {
|
|
381
|
+
const { auth } = cfg;
|
|
382
|
+
if (!auth)
|
|
383
|
+
return null;
|
|
384
|
+
return async (ctx) => {
|
|
385
|
+
const result = await auth(ctx);
|
|
386
|
+
return (0, errors_1.excludeErrorResult)(result);
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
createLexiconParamsVerifier(nsid, def) {
|
|
390
|
+
return (0, util_1.createLexiconParamsVerifier)(nsid, def, this.lex);
|
|
391
|
+
}
|
|
392
|
+
createLexiconInputVerifier(nsid, def, opts) {
|
|
393
|
+
return (0, util_1.createLexiconInputVerifier)(nsid, def, {
|
|
394
|
+
blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,
|
|
395
|
+
jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,
|
|
396
|
+
textLimit: opts?.textLimit ?? this.options.payload?.textLimit,
|
|
397
|
+
}, this.lex);
|
|
398
|
+
}
|
|
399
|
+
createLexiconOutputVerifier(nsid, def) {
|
|
400
|
+
if (this.options.validateResponse === false) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
return (0, util_1.createLexiconOutputVerifier)(nsid, def, this.lex);
|
|
404
|
+
}
|
|
405
|
+
createSchemaParamsVerifier(ns) {
|
|
406
|
+
return (0, util_1.createSchemaParamsVerifier)(ns);
|
|
407
|
+
}
|
|
408
|
+
createSchemaInputVerifier(ns, opts) {
|
|
409
|
+
return (0, util_1.createSchemaInputVerifier)(ns, {
|
|
410
|
+
blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,
|
|
411
|
+
jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,
|
|
412
|
+
textLimit: opts?.textLimit ?? this.options.payload?.textLimit,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
createSchemaOutputVerifier(ns) {
|
|
416
|
+
if (this.options.validateResponse === false) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
return (0, util_1.createSchemaOutputVerifier)(ns);
|
|
420
|
+
}
|
|
384
421
|
enableStreamingOnListen(app) {
|
|
385
422
|
const _listen = app.listen;
|
|
386
423
|
app.listen = (...args) => {
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport express, {\n Application,\n ErrorRequestHandler,\n Express,\n Request,\n RequestHandler,\n Router,\n} from 'express'\nimport { check, schema } from '@atproto/common'\nimport { LexMap, LexValue } from '@atproto/lex-data'\nimport {\n LexXrpcProcedure,\n LexXrpcQuery,\n LexXrpcSubscription,\n LexiconDoc,\n Lexicons,\n lexToJson,\n} from '@atproto/lexicon'\nimport {\n InternalServerError,\n InvalidRequestError,\n MethodNotImplementedError,\n XRPCError,\n excludeErrorResult,\n isErrorResult,\n} from './errors'\nimport log, { LOGGER_NAME } from './logger'\nimport {\n CalcKeyFn,\n CalcPointsFn,\n RateLimiterI,\n RateLimiterOptions,\n RouteRateLimiter,\n WrappedRateLimiter,\n} from './rate-limiter'\nimport { ErrorFrame, Frame, MessageFrame, XrpcStreamServer } from './stream'\nimport {\n Auth,\n AuthResult,\n AuthVerifier,\n CatchallHandler,\n HandlerContext,\n HandlerSuccess,\n Input,\n MethodConfig,\n MethodConfigOrHandler,\n Options,\n Params,\n RouteOptions,\n ServerRateLimitDescription,\n StreamConfig,\n StreamConfigOrHandler,\n isHandlerPipeThroughBuffer,\n isHandlerPipeThroughStream,\n isSharedRateLimitOpts,\n} from './types'\nimport {\n asArray,\n createInputVerifier,\n decodeQueryParams,\n extractUrlNsid,\n getQueryParams,\n setHeaders,\n validateOutput,\n} from './util'\n\nexport function createServer(lexicons?: LexiconDoc[], options?: Options) {\n return new Server(lexicons, options)\n}\n\nexport class Server {\n router: Express = express()\n routes: Router = Router()\n subscriptions = new Map<string, XrpcStreamServer>()\n lex = new Lexicons()\n options: Options\n globalRateLimiter?: RouteRateLimiter<HandlerContext>\n sharedRateLimiters?: Map<string, RateLimiterI<HandlerContext>>\n\n constructor(lexicons?: LexiconDoc[], opts: Options = {}) {\n if (lexicons) {\n this.addLexicons(lexicons)\n }\n this.router.use(this.routes)\n this.router.use(this.catchall)\n this.router.use(createErrorMiddleware(opts))\n this.router.once('mount', (app: Application) => {\n this.enableStreamingOnListen(app)\n })\n this.options = opts\n\n if (opts.rateLimits) {\n const { global, shared, creator, bypass } = opts.rateLimits\n\n if (global) {\n this.globalRateLimiter = RouteRateLimiter.from(\n global.map((options) => creator(buildRateLimiterOptions(options))),\n { bypass },\n )\n }\n\n if (shared) {\n this.sharedRateLimiters = new Map(\n shared.map((options) => [\n options.name,\n creator(buildRateLimiterOptions(options)),\n ]),\n )\n }\n }\n }\n\n // handlers\n // =\n\n method<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ) {\n this.addMethod(nsid, configOrFn)\n }\n\n addMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'query' || def?.type === 'procedure') {\n this.addRoute(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a query or a procedure`)\n }\n }\n\n streamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A>,\n ) {\n this.addStreamMethod(nsid, configOrFn)\n }\n\n addStreamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'subscription') {\n this.addSubscription(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a subscription`)\n }\n }\n\n // schemas\n // =\n\n addLexicon(doc: LexiconDoc) {\n this.lex.add(doc)\n }\n\n addLexicons(docs: LexiconDoc[]) {\n for (const doc of docs) {\n this.addLexicon(doc)\n }\n }\n\n // http\n // =\n\n protected async addRoute<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n config: MethodConfig<A>,\n ) {\n const path = `/xrpc/${nsid}`\n const handler = this.createHandler(nsid, def, config)\n\n if (def.type === 'procedure') {\n this.routes.post(path, handler)\n } else {\n this.routes.get(path, handler)\n }\n }\n\n catchall: CatchallHandler = async (req, res, next) => {\n // catchall handler only applies to XRPC routes\n if (!req.url.startsWith('/xrpc/')) return next()\n\n // Validate the NSID\n const nsid = extractUrlNsid(req.url)\n if (!nsid) {\n return next(new InvalidRequestError('invalid xrpc path'))\n }\n\n if (this.globalRateLimiter) {\n try {\n await this.globalRateLimiter.handle({\n req,\n res,\n auth: undefined,\n params: {},\n input: undefined,\n async resetRouteRateLimits() {},\n })\n } catch (err) {\n return next(err)\n }\n }\n\n // Ensure that known XRPC methods are only called with the correct HTTP\n // method.\n const def = this.lex.getDef(nsid)\n if (def) {\n const expectedMethod =\n def.type === 'procedure' ? 'POST' : def.type === 'query' ? 'GET' : null\n if (expectedMethod != null && expectedMethod !== req.method) {\n return next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected ${expectedMethod}`,\n ),\n )\n }\n }\n\n if (this.options.catchall) {\n this.options.catchall.call(null, req, res, next)\n } else if (!def) {\n next(new MethodNotImplementedError())\n } else {\n next()\n }\n }\n\n protected createParamsVerifier(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n ) {\n return (req: Request | IncomingMessage): Params => {\n const queryParams = 'query' in req ? req.query : getQueryParams(req.url)\n const params: Params = decodeQueryParams(def, queryParams)\n try {\n return this.lex.assertValidXrpcParams(nsid, params) as Params\n } catch (e) {\n throw new InvalidRequestError(String(e))\n }\n }\n }\n\n protected createInputVerifier(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n routeOpts: RouteOptions,\n ) {\n return createInputVerifier(nsid, def, routeOpts, this.lex)\n }\n\n protected createAuthVerifier<C, A extends Auth>(cfg: {\n auth?: AuthVerifier<C, A & AuthResult>\n }): null | ((ctx: C) => Promise<A>) {\n const { auth } = cfg\n if (!auth) return null\n\n return async (ctx: C) => {\n const result = await auth(ctx)\n return excludeErrorResult(result)\n }\n }\n\n createHandler<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n cfg: MethodConfig<A>,\n ): RequestHandler {\n const authVerifier = this.createAuthVerifier(cfg)\n const paramsVerifier = this.createParamsVerifier(nsid, def)\n const inputVerifier = this.createInputVerifier(nsid, def, {\n blobLimit: cfg.opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: cfg.opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: cfg.opts?.textLimit ?? this.options.payload?.textLimit,\n })\n\n const validateResOutput =\n this.options.validateResponse === false\n ? null\n : (output: void | HandlerSuccess) =>\n validateOutput(nsid, def, output, this.lex)\n\n const routeLimiter = this.createRouteRateLimiter(nsid, cfg)\n\n return async function (req, res, next) {\n try {\n // parse & validate params\n const params: Params = paramsVerifier(req)\n\n // authenticate request\n const auth: A = authVerifier\n ? await authVerifier({ req, res, params })\n : (undefined as A)\n\n // parse & validate input\n const input: Input = await inputVerifier(req, res)\n\n const ctx: HandlerContext<A> = {\n params,\n input,\n auth,\n req,\n res,\n resetRouteRateLimits: async () => routeLimiter?.reset(ctx),\n }\n\n // handle rate limits\n if (routeLimiter) await routeLimiter.handle(ctx)\n\n // run the handler\n const output = await cfg.handler(ctx)\n\n if (!output) {\n validateResOutput?.(output)\n res.status(200)\n res.end()\n } else if (isHandlerPipeThroughStream(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n await pipeline(output.stream, res)\n } else if (isHandlerPipeThroughBuffer(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n res.end(output.buffer)\n } else if (isErrorResult(output)) {\n next(XRPCError.fromError(output))\n } else {\n validateResOutput?.(output)\n\n res.status(200)\n setHeaders(res, output.headers)\n\n if (\n output.encoding === 'application/json' ||\n output.encoding === 'json'\n ) {\n const json = lexToJson(output.body)\n res.json(json)\n } else if (output.body instanceof Readable) {\n res.header('Content-Type', output.encoding)\n await pipeline(output.body, res)\n } else {\n res.header('Content-Type', output.encoding)\n res.send(\n Buffer.isBuffer(output.body)\n ? output.body\n : output.body instanceof Uint8Array\n ? Buffer.from(output.body)\n : output.body,\n )\n }\n }\n } catch (err: unknown) {\n // Express will not call the next middleware (errorMiddleware in this case)\n // if the value passed to next is false-y (e.g. null, undefined, 0).\n // Hence we replace it with an InternalServerError.\n if (!err) {\n next(new InternalServerError())\n } else {\n next(err)\n }\n }\n }\n }\n\n protected async addSubscription<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcSubscription,\n cfg: StreamConfig<A>,\n ) {\n const paramsVerifier = this.createParamsVerifier(nsid, def)\n const authVerifier = this.createAuthVerifier(cfg)\n\n const { handler } = cfg\n this.subscriptions.set(\n nsid,\n new XrpcStreamServer({\n noServer: true,\n handler: async function* (req, signal) {\n try {\n // validate request\n const params = paramsVerifier(req)\n // authenticate request\n const auth = authVerifier\n ? await authVerifier({ req, params })\n : (undefined as A)\n // stream\n for await (const item of handler({ req, params, auth, signal })) {\n if (item instanceof Frame) {\n yield item\n continue\n }\n const type = item?.['$type']\n if (!check.is(item, schema.map) || typeof type !== 'string') {\n yield new MessageFrame(item as LexValue)\n continue\n }\n const split = type.split('#')\n let t: string\n if (\n split.length === 2 &&\n (split[0] === '' || split[0] === nsid)\n ) {\n t = `#${split[1]}`\n } else {\n t = type\n }\n const { $type: _, ...clone } = item as LexMap\n yield new MessageFrame(clone, { type: t })\n }\n } catch (err) {\n const xrpcErrPayload = XRPCError.fromError(err).payload\n yield new ErrorFrame({\n error: xrpcErrPayload.error ?? 'Unknown',\n message: xrpcErrPayload.message,\n })\n }\n },\n }),\n )\n }\n\n private enableStreamingOnListen(app: Application) {\n const _listen = app.listen\n app.listen = (...args) => {\n // @ts-ignore the args spread\n const httpServer = _listen.call(app, ...args)\n httpServer.on('upgrade', (req, socket, head) => {\n const nsid = req.url ? extractUrlNsid(req.url) : undefined\n const sub = nsid ? this.subscriptions.get(nsid) : undefined\n if (!sub) return socket.destroy()\n sub.wss.handleUpgrade(req, socket, head, (ws) =>\n sub.wss.emit('connection', ws, req),\n )\n })\n return httpServer\n }\n }\n\n private createRouteRateLimiter<A extends Auth, C extends HandlerContext>(\n nsid: string,\n config: MethodConfig<A>,\n ): RouteRateLimiter<C> | undefined {\n // @NOTE global & shared rate limiters are instantiated with a context of\n // HandlerContext which is compatible (more generic) with the context of\n // this route specific rate limiters (C). For this reason, it's safe to\n // cast these with an `any` context\n\n const globalRateLimiter = this.globalRateLimiter as\n | RouteRateLimiter<any>\n | undefined\n\n // No route specific rate limiting configured, use the global rate limiter.\n if (!config.rateLimit) return globalRateLimiter\n\n const { rateLimits } = this.options\n\n // @NOTE Silently ignore creation of route specific rate limiter if the\n // `rateLimits` options was not provided to the constructor.\n if (!rateLimits) return globalRateLimiter\n\n const { creator, bypass } = rateLimits\n\n const rateLimiters = asArray(config.rateLimit).map((options, i) => {\n if (isSharedRateLimitOpts(options)) {\n const rateLimiter = this.sharedRateLimiters?.get(options.name)\n\n // The route config references a shared rate limiter that does not\n // exist. This is a configuration error.\n assert(rateLimiter, `Shared rate limiter \"${options.name}\" not defined`)\n\n return WrappedRateLimiter.from<any>(rateLimiter, options)\n } else {\n return creator({\n ...options,\n calcKey: options.calcKey ?? defaultKey,\n calcPoints: options.calcPoints ?? defaultPoints,\n keyPrefix: `${nsid}-${i}`,\n })\n }\n })\n\n // If the route config contains an empty array, use global rate limiter.\n if (!rateLimiters.length) return globalRateLimiter\n\n // The global rate limiter (if present) should be applied in addition to\n // the route specific rate limiters.\n if (globalRateLimiter) rateLimiters.push(globalRateLimiter)\n\n return RouteRateLimiter.from<any>(rateLimiters, { bypass })\n }\n}\n\nfunction createErrorMiddleware({\n errorParser = (err) => XRPCError.fromError(err),\n}: Options): ErrorRequestHandler {\n return (err, req, res, next) => {\n const nsid = extractUrlNsid(req.originalUrl)\n const xrpcError = errorParser(err)\n\n // Use the request's logger (if available) to benefit from request context\n // (id, timing) and logging configuration (serialization, etc.).\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n const isInternalError = xrpcError instanceof InternalServerError\n\n const msgPrefix = isInternalError ? 'unhandled exception' : 'error'\n const msgSuffix = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`\n const msg = `${msgPrefix} in ${msgSuffix}`\n\n logger.error(\n {\n // @NOTE Computation of error stack is an expensive operation, so\n // we strip it for expected errors.\n err:\n isInternalError || process.env.NODE_ENV === 'development'\n ? err\n : toSimplifiedErrorLike(err),\n\n // XRPC specific properties, for easier browsing of logs\n nsid,\n type: xrpcError.type,\n status: xrpcError.statusCode,\n payload: xrpcError.payload,\n\n // Ensure that the logged item's name is set to LOGGER_NAME, instead of\n // the name of the pino-http logger, to ensure consistency across logs.\n name: LOGGER_NAME,\n },\n msg,\n )\n\n if (res.headersSent) {\n return next(err)\n }\n\n return res.status(xrpcError.statusCode).json(xrpcError.payload)\n }\n}\n\nfunction isPinoHttpRequest(req: IncomingMessage): req is IncomingMessage & {\n log: { error: (obj: unknown, msg: string) => void }\n} {\n return typeof (req as { log?: any }).log?.error === 'function'\n}\n\nfunction toSimplifiedErrorLike(err: unknown): unknown {\n if (err instanceof Error) {\n // Transform into an \"ErrorLike\" for pino's std \"err\" serializer\n return {\n ...err,\n // Carry over non-enumerable properties\n message: err.message,\n name:\n !Object.hasOwn(err, 'name') &&\n Object.prototype.toString.call(err.constructor) === '[object Function]'\n ? err.constructor.name // extract the class name for sub-classes of Error\n : err.name,\n // @NOTE Error.stack, Error.cause and AggregateError.error are non\n // enumerable properties so they won't be spread to the ErrorLike\n }\n }\n\n return err\n}\n\nfunction buildRateLimiterOptions<C extends HandlerContext = HandlerContext>({\n name,\n calcKey = defaultKey,\n calcPoints = defaultPoints,\n ...desc\n}: ServerRateLimitDescription<C>): RateLimiterOptions<C> {\n return { ...desc, calcKey, calcPoints, keyPrefix: `rl-${name}` }\n}\n\nconst defaultPoints: CalcPointsFn = () => 1\n\n/**\n * @note when using a proxy, ensure headers are getting forwarded correctly:\n * `app.set('trust proxy', true)`\n *\n * @see {@link https://expressjs.com/en/guide/behind-proxies.html}\n */\nconst defaultKey: CalcKeyFn<HandlerContext> = ({ req }) => req.ip\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport express, {\n Application,\n ErrorRequestHandler,\n Express,\n RequestHandler,\n Router,\n} from 'express'\nimport { LexValue } from '@atproto/lex-data'\nimport { l } from '@atproto/lex-schema'\nimport {\n LexXrpcProcedure,\n LexXrpcQuery,\n LexXrpcSubscription,\n LexiconDoc,\n Lexicons,\n lexToJson,\n} from '@atproto/lexicon'\nimport {\n InternalServerError,\n InvalidRequestError,\n MethodNotImplementedError,\n XRPCError,\n excludeErrorResult,\n} from './errors'\nimport log, { LOGGER_NAME } from './logger'\nimport {\n CalcKeyFn,\n CalcPointsFn,\n RateLimiterI,\n RateLimiterOptions,\n RouteRateLimiter,\n WrappedRateLimiter,\n} from './rate-limiter'\nimport { ErrorFrame, Frame, MessageFrame, XrpcStreamServer } from './stream'\nimport {\n Auth,\n AuthResult,\n AuthVerifier,\n CatchallHandler,\n HandlerContext,\n Input,\n LexMethodConfig,\n LexMethodHandler,\n LexMethodInput,\n LexMethodOutput,\n LexMethodParams,\n LexSubscriptionConfig,\n LexSubscriptionHandler,\n MethodAuthContext,\n MethodConfig,\n MethodConfigOrHandler,\n MethodHandler,\n Options,\n Output,\n Params,\n RouteOptions,\n ServerRateLimitDescription,\n StreamAuthContext,\n StreamConfig,\n StreamConfigOrHandler,\n StreamContext,\n isHandlerPipeThroughBuffer,\n isHandlerPipeThroughStream,\n isHandlerSuccess,\n isSharedRateLimitOpts,\n} from './types'\nimport {\n AuthVerifierInternal,\n InputVerifierInternal,\n OutputVerifierInternal,\n ParamsVerifierInternal,\n asArray,\n createLexiconInputVerifier,\n createLexiconOutputVerifier,\n createLexiconParamsVerifier,\n createSchemaInputVerifier,\n createSchemaOutputVerifier,\n createSchemaParamsVerifier,\n extractUrlNsid,\n setHeaders,\n} from './util'\n\nexport function createServer(lexicons?: LexiconDoc[], options?: Options) {\n return new Server(lexicons, options)\n}\n\nexport class Server {\n router: Express = express()\n routes: Router = Router()\n subscriptions = new Map<string, XrpcStreamServer>()\n lex = new Lexicons()\n options: Options\n globalRateLimiter?: RouteRateLimiter<HandlerContext>\n sharedRateLimiters?: Map<string, RateLimiterI<HandlerContext>>\n\n constructor(lexicons?: LexiconDoc[], opts: Options = {}) {\n if (lexicons) {\n this.addLexicons(lexicons)\n }\n this.router.use(this.routes)\n this.router.use(this.catchall)\n this.router.use(createErrorMiddleware(opts))\n this.router.once('mount', (app: Application) => {\n this.enableStreamingOnListen(app)\n })\n this.options = opts\n\n if (opts.rateLimits) {\n const { global, shared, creator, bypass } = opts.rateLimits\n\n if (global) {\n this.globalRateLimiter = RouteRateLimiter.from(\n global.map((options) => creator(buildRateLimiterOptions(options))),\n { bypass },\n )\n }\n\n if (shared) {\n this.sharedRateLimiters = new Map(\n shared.map((options) => [\n options.name,\n creator(buildRateLimiterOptions(options)),\n ]),\n )\n }\n }\n }\n\n listen(port: number, callback?: () => void) {\n return this.router.listen(port, callback)\n }\n\n // handlers\n // =\n\n // Routes with auth\n add<M extends l.Procedure | l.Query | l.Subscription, A extends AuthResult>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> & { auth: Exclude<unknown, void> }\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> & { auth: Exclude<unknown, void> }\n : never,\n ): void\n // Routes without auth\n add<M extends l.Procedure | l.Query | l.Subscription>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, void> | LexMethodHandler<M, void>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, void> | LexSubscriptionHandler<M, void>\n : never,\n ): void\n add<M extends l.Procedure | l.Query | l.Subscription, A extends Auth>(\n ns: l.Main<M>,\n configOfHandler: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> | LexMethodHandler<M, A>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> | LexSubscriptionHandler<M, A>\n : never,\n ): void {\n const schema = l.getMain(ns)\n const config =\n typeof configOfHandler === 'function'\n ? { handler: configOfHandler }\n : configOfHandler\n switch (schema.type) {\n case 'procedure':\n return this.addProcedureSchema(\n schema,\n config as LexMethodConfig<l.Procedure, A>,\n )\n case 'query':\n return this.addQuerySchema(\n schema,\n config as LexMethodConfig<l.Query, A>,\n )\n case 'subscription':\n return this.addSubscriptionSchema(\n schema,\n config as LexSubscriptionConfig<l.Subscription, A>,\n )\n default:\n throw new TypeError(\n // @ts-expect-error should never happen\n `Unsupported schema ${schema.nsid} of type ${schema.type}`,\n )\n }\n }\n\n protected addProcedureSchema<M extends l.Procedure, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.post(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addQuerySchema<M extends l.Query, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.get(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addSubscriptionSchema<\n M extends l.Subscription,\n A extends Auth = void,\n >(schema: M, config: LexSubscriptionConfig<M, A>): void {\n const { handler } = config\n const messageSchema =\n this.options.validateResponse === false ? undefined : schema.message\n\n return this.addSubscriptionInternal(\n schema.nsid,\n this.createSchemaParamsVerifier(schema),\n this.createAuthVerifier(config),\n // Wrap the handler to validate outgoing messages if a message schema\n // is available\n messageSchema\n ? async function* (ctx) {\n for await (const item of handler(ctx)) {\n if (item instanceof Frame) {\n messageSchema.validate(item.body)\n yield item\n } else {\n yield messageSchema.validate(item)\n }\n }\n }\n : handler,\n )\n }\n\n method<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ): void {\n this.addMethod(nsid, configOrFn)\n }\n\n addMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'query' || def?.type === 'procedure') {\n this.addRoute(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a query or a procedure`)\n }\n }\n\n streamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n this.addStreamMethod(nsid, configOrFn)\n }\n\n addStreamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'subscription') {\n this.addSubscription(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a subscription`)\n }\n }\n\n // schemas\n // =\n\n addLexicon(doc: LexiconDoc) {\n this.lex.add(doc)\n }\n\n addLexicons(docs: LexiconDoc[]) {\n for (const doc of docs) {\n this.addLexicon(doc)\n }\n }\n\n // http\n // =\n\n protected async addRoute<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n config: MethodConfig<A>,\n ) {\n const path = `/xrpc/${nsid}`\n const handler = this.createHandler(nsid, def, config)\n\n if (def.type === 'procedure') {\n this.routes.post(path, handler)\n } else {\n this.routes.get(path, handler)\n }\n }\n\n catchall: CatchallHandler = async (req, res, next) => {\n // catchall handler only applies to XRPC routes\n if (!req.url.startsWith('/xrpc/')) return next()\n\n // Validate the NSID\n const nsid = extractUrlNsid(req.url)\n if (!nsid) {\n return next(new InvalidRequestError('invalid xrpc path'))\n }\n\n if (this.globalRateLimiter) {\n try {\n await this.globalRateLimiter.handle({\n req,\n res,\n auth: undefined,\n params: {},\n input: undefined,\n async resetRouteRateLimits() {},\n })\n } catch (err) {\n return next(err)\n }\n }\n\n // Ensure that known XRPC methods are only called with the correct HTTP\n // method.\n const def = this.lex.getDef(nsid)\n if (def) {\n const expectedMethod =\n def.type === 'procedure' ? 'POST' : def.type === 'query' ? 'GET' : null\n if (expectedMethod != null && expectedMethod !== req.method) {\n return next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected ${expectedMethod}`,\n ),\n )\n }\n }\n\n if (this.options.catchall) {\n this.options.catchall.call(null, req, res, next)\n } else if (!def) {\n next(new MethodNotImplementedError())\n } else {\n next()\n }\n }\n\n createHandler<\n A extends Auth = Auth,\n P extends Params = Params,\n I extends Input = Input,\n O extends Output = Output,\n >(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n cfg: MethodConfig<A, P, I, O>,\n ): RequestHandler {\n return this.createHandlerInternal<A, P, I, O>(\n this.createAuthVerifier(cfg),\n this.createLexiconParamsVerifier<P>(nsid, def),\n this.createLexiconInputVerifier<I>(nsid, def, cfg.opts),\n this.createRouteRateLimiter(nsid, cfg),\n cfg.handler,\n this.createLexiconOutputVerifier<O>(nsid, def),\n )\n }\n\n protected createHandlerInternal<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n authVerifier: AuthVerifierInternal<MethodAuthContext<P>, A> | null,\n paramsVerifier: ParamsVerifierInternal<P>,\n inputVerifier: InputVerifierInternal<I>,\n routeLimiter: RouteRateLimiter<HandlerContext<A, P, I>> | undefined,\n handler: MethodHandler<A, P, I, O>,\n validateResOutput: null | OutputVerifierInternal<O>,\n ): RequestHandler {\n return async function (req, res, next) {\n try {\n // parse & validate params\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth: A = authVerifier\n ? await authVerifier({ req, res, params })\n : (undefined as A)\n\n // parse & validate input\n const input: I = await inputVerifier(req, res)\n\n const ctx: HandlerContext<A, P, I> = {\n params,\n input,\n auth,\n req,\n res,\n resetRouteRateLimits: async () => routeLimiter?.reset(ctx),\n }\n\n // handle rate limits\n if (routeLimiter) await routeLimiter.handle(ctx)\n\n // run the handler\n const output = (await handler(ctx)) as O\n\n if (!output) {\n validateResOutput?.(output)\n res.status(200)\n res.end()\n } else if (isHandlerPipeThroughStream(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n await pipeline(output.stream, res)\n } else if (isHandlerPipeThroughBuffer(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n res.end(output.buffer)\n } else if (isHandlerSuccess(output)) {\n validateResOutput?.(output)\n\n res.status(200)\n setHeaders(res, output.headers)\n\n const encoding =\n output.encoding === 'json' ? 'application/json' : output.encoding\n\n res.header('Content-Type', encoding)\n\n if (output.body instanceof Readable) {\n // The \"Readable\" check comes first to avoid calling \"lexToJson\" on\n // a stream, which would be a bug.\n await pipeline(output.body, res)\n } else if (encoding === 'application/json') {\n const json = lexToJson(output.body)\n res.json(json)\n } else {\n res.send(\n Buffer.isBuffer(output.body)\n ? output.body\n : output.body instanceof Uint8Array\n ? Buffer.from(output.body)\n : output.body,\n )\n }\n } else {\n next(XRPCError.fromError(output))\n }\n } catch (err: unknown) {\n // Express will not call the next middleware (errorMiddleware in this case)\n // if the value passed to next is false-y (e.g. null, undefined, 0).\n // Hence we replace it with an InternalServerError.\n if (!err) {\n next(new InternalServerError())\n } else {\n next(err)\n }\n }\n }\n }\n\n protected async addSubscription<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcSubscription,\n cfg: StreamConfig<A, Params>,\n ) {\n this.addSubscriptionInternal(\n nsid,\n this.createLexiconParamsVerifier(nsid, def),\n this.createAuthVerifier(cfg),\n // @NOTE outgoing messages are not validated against the lexicon schema\n // (unlike the handlers for @atproto/lex based subscriptions)\n cfg.handler,\n )\n }\n\n protected addSubscriptionInternal<A extends Auth, P extends Params>(\n nsid: string,\n paramsVerifier: ParamsVerifierInternal<P>,\n authVerifier: AuthVerifierInternal<StreamAuthContext<P>, A> | null,\n handler: (ctx: StreamContext<A, P>) => AsyncIterable<unknown>,\n ) {\n this.subscriptions.set(\n nsid,\n new XrpcStreamServer({\n noServer: true,\n handler: async function* (req, signal) {\n try {\n // validate request\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth = authVerifier\n ? await authVerifier({ req, params })\n : (undefined as A)\n\n // stream\n for await (const item of handler({ req, params, auth, signal })) {\n yield item instanceof Frame\n ? item\n : MessageFrame.fromLexValue(item as LexValue, nsid)\n }\n } catch (err) {\n yield ErrorFrame.fromError(err)\n }\n },\n }),\n )\n }\n\n private createAuthVerifier<C, A extends AuthResult>(cfg: {\n auth?: AuthVerifier<C, A>\n }): null | AuthVerifierInternal<C, A> {\n const { auth } = cfg\n if (!auth) return null\n\n return async (ctx) => {\n const result = await auth(ctx)\n return excludeErrorResult(result)\n }\n }\n\n private createLexiconParamsVerifier<P extends Params = Params>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n ) {\n return createLexiconParamsVerifier<P>(nsid, def, this.lex)\n }\n\n private createLexiconInputVerifier<I extends Input = Input>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n opts?: RouteOptions,\n ): InputVerifierInternal<I> {\n return createLexiconInputVerifier(\n nsid,\n def,\n {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n },\n this.lex,\n )\n }\n\n private createLexiconOutputVerifier<O extends Output = Output>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n ): null | OutputVerifierInternal<O> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createLexiconOutputVerifier(nsid, def, this.lex)\n }\n\n private createSchemaParamsVerifier<\n M extends l.Procedure | l.Query | l.Subscription,\n >(ns: l.Main<M>): ParamsVerifierInternal<LexMethodParams<M>> {\n return createSchemaParamsVerifier<M>(ns)\n }\n\n private createSchemaInputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n opts?: RouteOptions,\n ): InputVerifierInternal<LexMethodInput<M>> {\n return createSchemaInputVerifier<M>(ns, {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n })\n }\n\n private createSchemaOutputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n ): null | OutputVerifierInternal<LexMethodOutput<M>> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createSchemaOutputVerifier<M>(ns)\n }\n\n private enableStreamingOnListen(app: Application) {\n const _listen = app.listen\n app.listen = (...args) => {\n // @ts-ignore the args spread\n const httpServer = _listen.call(app, ...args)\n httpServer.on('upgrade', (req, socket, head) => {\n const nsid = req.url ? extractUrlNsid(req.url) : undefined\n const sub = nsid ? this.subscriptions.get(nsid) : undefined\n if (!sub) return socket.destroy()\n sub.wss.handleUpgrade(req, socket, head, (ws) =>\n sub.wss.emit('connection', ws, req),\n )\n })\n return httpServer\n }\n }\n\n private createRouteRateLimiter<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n nsid: string,\n config: MethodConfig<A, P, I, O>,\n ): RouteRateLimiter<HandlerContext<A, P, I>> | undefined {\n // @NOTE global & shared rate limiters are instantiated with a context of\n // HandlerContext which is compatible (more generic) with the context of\n // this route specific rate limiters (C). For this reason, it's safe to\n // cast these with an `any` context\n\n const globalRateLimiter = this.globalRateLimiter as\n | RouteRateLimiter<any>\n | undefined\n\n // No route specific rate limiting configured, use the global rate limiter.\n if (!config.rateLimit) return globalRateLimiter\n\n const { rateLimits } = this.options\n\n // @NOTE Silently ignore creation of route specific rate limiter if the\n // `rateLimits` options was not provided to the constructor.\n if (!rateLimits) return globalRateLimiter\n\n const { creator, bypass } = rateLimits\n\n const rateLimiters = asArray(config.rateLimit).map((options, i) => {\n if (isSharedRateLimitOpts(options)) {\n const rateLimiter = this.sharedRateLimiters?.get(options.name)\n\n // The route config references a shared rate limiter that does not\n // exist. This is a configuration error.\n assert(rateLimiter, `Shared rate limiter \"${options.name}\" not defined`)\n\n return WrappedRateLimiter.from<any>(rateLimiter, options)\n } else {\n return creator({\n ...options,\n calcKey: options.calcKey ?? defaultKey,\n calcPoints: options.calcPoints ?? defaultPoints,\n keyPrefix: `${nsid}-${i}`,\n })\n }\n })\n\n // If the route config contains an empty array, use global rate limiter.\n if (!rateLimiters.length) return globalRateLimiter\n\n // The global rate limiter (if present) should be applied in addition to\n // the route specific rate limiters.\n if (globalRateLimiter) rateLimiters.push(globalRateLimiter)\n\n return RouteRateLimiter.from<any>(rateLimiters, { bypass })\n }\n}\n\nfunction createErrorMiddleware({\n errorParser = (err) => XRPCError.fromError(err),\n}: Options): ErrorRequestHandler {\n return (err, req, res, next) => {\n const nsid = extractUrlNsid(req.originalUrl)\n const xrpcError = errorParser(err)\n\n // Use the request's logger (if available) to benefit from request context\n // (id, timing) and logging configuration (serialization, etc.).\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n const isInternalError = xrpcError instanceof InternalServerError\n\n const msgPrefix = isInternalError ? 'unhandled exception' : 'error'\n const msgSuffix = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`\n const msg = `${msgPrefix} in ${msgSuffix}`\n\n logger.error(\n {\n // @NOTE Computation of error stack is an expensive operation, so\n // we strip it for expected errors.\n err:\n isInternalError || process.env.NODE_ENV === 'development'\n ? err\n : toSimplifiedErrorLike(err),\n\n // XRPC specific properties, for easier browsing of logs\n nsid,\n type: xrpcError.type,\n status: xrpcError.statusCode,\n payload: xrpcError.payload,\n\n // Ensure that the logged item's name is set to LOGGER_NAME, instead of\n // the name of the pino-http logger, to ensure consistency across logs.\n name: LOGGER_NAME,\n },\n msg,\n )\n\n if (res.headersSent) {\n return next(err)\n }\n\n return res.status(xrpcError.statusCode).json(xrpcError.payload)\n }\n}\n\nfunction isPinoHttpRequest(req: IncomingMessage): req is IncomingMessage & {\n log: { error: (obj: unknown, msg: string) => void }\n} {\n return typeof (req as { log?: any }).log?.error === 'function'\n}\n\nfunction toSimplifiedErrorLike(err: unknown): unknown {\n if (err instanceof Error) {\n // Transform into an \"ErrorLike\" for pino's std \"err\" serializer\n return {\n ...err,\n // Carry over non-enumerable properties\n message: err.message,\n name:\n !Object.hasOwn(err, 'name') &&\n Object.prototype.toString.call(err.constructor) === '[object Function]'\n ? err.constructor.name // extract the class name for sub-classes of Error\n : err.name,\n // @NOTE Error.stack, Error.cause and AggregateError.error are non\n // enumerable properties so they won't be spread to the ErrorLike\n }\n }\n\n return err\n}\n\nfunction buildRateLimiterOptions<C extends HandlerContext = HandlerContext>({\n name,\n calcKey = defaultKey,\n calcPoints = defaultPoints,\n ...desc\n}: ServerRateLimitDescription<C>): RateLimiterOptions<C> {\n return { ...desc, calcKey, calcPoints, keyPrefix: `rl-${name}` }\n}\n\nconst defaultPoints: CalcPointsFn = () => 1\n\n/**\n * @note when using a proxy, ensure headers are getting forwarded correctly:\n * `app.set('trust proxy', true)`\n *\n * @see {@link https://expressjs.com/en/guide/behind-proxies.html}\n */\nconst defaultKey: CalcKeyFn<HandlerContext> = ({ req }) => req.ip\n"]}
|
package/dist/stream/frames.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LexValue } from '@atproto/lex-
|
|
1
|
+
import { LexValue } from '@atproto/lex-data';
|
|
2
2
|
import { ErrorFrameBody, ErrorFrameHeader, FrameHeader, FrameType, MessageFrameHeader } from './types';
|
|
3
3
|
export declare abstract class Frame<T extends LexValue = LexValue> {
|
|
4
4
|
abstract header: FrameHeader;
|
|
@@ -16,6 +16,9 @@ export declare class MessageFrame<T extends LexValue = LexValue> extends Frame<T
|
|
|
16
16
|
type?: string;
|
|
17
17
|
});
|
|
18
18
|
get type(): string | undefined;
|
|
19
|
+
static fromLexValue(data: LexValue, nsid: string): MessageFrame<import("@atproto/lex-data").LexScalar | LexValue[]> | MessageFrame<{
|
|
20
|
+
[x: string]: LexValue | undefined;
|
|
21
|
+
}>;
|
|
19
22
|
}
|
|
20
23
|
export declare class ErrorFrame<T extends string = string> extends Frame<ErrorFrameBody<T>> {
|
|
21
24
|
header: ErrorFrameHeader;
|
|
@@ -23,5 +26,6 @@ export declare class ErrorFrame<T extends string = string> extends Frame<ErrorFr
|
|
|
23
26
|
constructor(body: ErrorFrameBody<T>);
|
|
24
27
|
get code(): T;
|
|
25
28
|
get message(): string | undefined;
|
|
29
|
+
static fromError(err: unknown): ErrorFrame;
|
|
26
30
|
}
|
|
27
31
|
//# sourceMappingURL=frames.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/stream/frames.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ErrorFrame = exports.MessageFrame = exports.Frame = void 0;
|
|
4
4
|
const lex_cbor_1 = require("@atproto/lex-cbor");
|
|
5
|
+
const lex_data_1 = require("@atproto/lex-data");
|
|
6
|
+
const errors_1 = require("../errors");
|
|
5
7
|
const types_1 = require("./types");
|
|
6
8
|
class Frame {
|
|
7
9
|
get op() {
|
|
@@ -26,20 +28,20 @@ class Frame {
|
|
|
26
28
|
}
|
|
27
29
|
const parsedHeader = types_1.frameHeader.safeParse(header);
|
|
28
30
|
if (!parsedHeader.success) {
|
|
29
|
-
throw new Error(`Invalid frame header: ${parsedHeader.
|
|
31
|
+
throw new Error(`Invalid frame header: ${parsedHeader.reason.message}`);
|
|
30
32
|
}
|
|
31
|
-
const frameOp = parsedHeader.
|
|
33
|
+
const frameOp = parsedHeader.value.op;
|
|
32
34
|
if (frameOp === types_1.FrameType.Message) {
|
|
33
35
|
return new MessageFrame(body, {
|
|
34
|
-
type: parsedHeader.
|
|
36
|
+
type: parsedHeader.value.t,
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
39
|
else if (frameOp === types_1.FrameType.Error) {
|
|
38
40
|
const parsedBody = types_1.errorFrameBody.safeParse(body);
|
|
39
41
|
if (!parsedBody.success) {
|
|
40
|
-
throw new Error(`Invalid error frame body: ${parsedBody.
|
|
42
|
+
throw new Error(`Invalid error frame body: ${parsedBody.reason.message}`);
|
|
41
43
|
}
|
|
42
|
-
return new ErrorFrame(parsedBody.
|
|
44
|
+
return new ErrorFrame(parsedBody.value);
|
|
43
45
|
}
|
|
44
46
|
else {
|
|
45
47
|
const exhaustiveCheck = frameOp;
|
|
@@ -72,6 +74,25 @@ class MessageFrame extends Frame {
|
|
|
72
74
|
get type() {
|
|
73
75
|
return this.header.t;
|
|
74
76
|
}
|
|
77
|
+
static fromLexValue(data, nsid) {
|
|
78
|
+
if (!(0, lex_data_1.isPlainObject)(data)) {
|
|
79
|
+
return new MessageFrame(data);
|
|
80
|
+
}
|
|
81
|
+
const $type = data?.['$type'];
|
|
82
|
+
if (typeof $type !== 'string') {
|
|
83
|
+
return new MessageFrame(data);
|
|
84
|
+
}
|
|
85
|
+
let type;
|
|
86
|
+
const split = $type.split('#');
|
|
87
|
+
if (split.length === 2 && (split[0] === '' || split[0] === nsid)) {
|
|
88
|
+
type = `#${split[1]}`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
type = $type;
|
|
92
|
+
}
|
|
93
|
+
const { $type: _, ...clone } = data;
|
|
94
|
+
return new MessageFrame(clone, { type });
|
|
95
|
+
}
|
|
75
96
|
}
|
|
76
97
|
exports.MessageFrame = MessageFrame;
|
|
77
98
|
class ErrorFrame extends Frame {
|
|
@@ -98,6 +119,12 @@ class ErrorFrame extends Frame {
|
|
|
98
119
|
get message() {
|
|
99
120
|
return this.body.message;
|
|
100
121
|
}
|
|
122
|
+
static fromError(err) {
|
|
123
|
+
if (err instanceof ErrorFrame)
|
|
124
|
+
return err;
|
|
125
|
+
const { error = 'Unknown', message } = errors_1.XRPCError.fromError(err).payload;
|
|
126
|
+
return new ErrorFrame({ error, message });
|
|
127
|
+
}
|
|
101
128
|
}
|
|
102
129
|
exports.ErrorFrame = ErrorFrame;
|
|
103
130
|
//# sourceMappingURL=frames.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/stream/frames.ts"],"names":[],"mappings":";;;AAAA,gDAAqD;AACrD,gDAA2D;AAC3D,sCAAqC;AACrC,mCAQgB;AAEhB,MAAsB,KAAK;IAIzB,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAA;IACvB,CAAC;IACD,OAAO;QACL,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAA,iBAAM,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChE,CAAC;IACD,SAAS;QACP,OAAO,IAAI,CAAC,EAAE,KAAK,iBAAS,CAAC,OAAO,CAAA;IACtC,CAAC;IACD,OAAO;QACL,OAAO,IAAI,CAAC,EAAE,KAAK,iBAAS,CAAC,KAAK,CAAA;IACpC,CAAC;IACD,MAAM,CAAC,SAAS,CAAC,KAAiB;QAChC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAA,oBAAS,EAAC,KAAK,CAAC,CAAA;QAChD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;QACtD,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;QACvC,CAAC;QAED,MAAM,YAAY,GAAG,mBAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAClD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,yBAAyB,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;QACzE,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;QACrC,IAAI,OAAO,KAAK,iBAAS,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,IAAI,YAAY,CAAC,IAAI,EAAE;gBAC5B,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;aAC3B,CAAC,CAAA;QACJ,CAAC;aAAM,IAAI,OAAO,KAAK,iBAAS,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,sBAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;YACjD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,6BAA6B,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CACzD,CAAA;YACH,CAAC;YACD,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,eAAe,GAAU,OAAO,CAAA;YACtC,MAAM,IAAI,KAAK,CAAC,qBAAqB,eAAe,EAAE,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;CACF;AA9CD,sBA8CC;AAED,MAAa,YAA4C,SAAQ,KAAQ;IAIvE,YAAY,IAAO,EAAE,IAAwB;QAC3C,KAAK,EAAE,CAAA;QAJT;;;;;WAA0B;QAC1B;;;;;WAAO;QAIL,IAAI,CAAC,MAAM;YACT,IAAI,EAAE,IAAI,KAAK,SAAS;gBACtB,CAAC,CAAC,EAAE,EAAE,EAAE,iBAAS,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;gBAC1C,CAAC,CAAC,EAAE,EAAE,EAAE,iBAAS,CAAC,OAAO,EAAE,CAAA;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IACtB,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,IAAc,EAAE,IAAY;QAC9C,IAAI,CAAC,IAAA,wBAAa,EAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,CAAA;QAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,IAAI,IAAY,CAAA;QAEhB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YACjE,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,KAAK,CAAA;QACd,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAA;QACnC,OAAO,IAAI,YAAY,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,CAAC;CACF;AAtCD,oCAsCC;AAED,MAAa,UAAsC,SAAQ,KAE1D;IAIC,YAAY,IAAuB;QACjC,KAAK,EAAE,CAAA;QAJT;;;;;WAAwB;QACxB;;;;;WAAuB;QAIrB,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,EAAE,iBAAS,CAAC,KAAK,EAAE,CAAA;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;IACxB,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAA;IAC1B,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,GAAY;QAC3B,IAAI,GAAG,YAAY,UAAU;YAAE,OAAO,GAAG,CAAA;QACzC,MAAM,EAAE,KAAK,GAAG,SAAS,EAAE,OAAO,EAAE,GAAG,kBAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,CAAA;QACvE,OAAO,IAAI,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3C,CAAC;CACF;AAvBD,gCAuBC","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"]}
|