@atproto/lex-server 0.1.1 → 0.1.3

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 CHANGED
@@ -1,5 +1,37 @@
1
1
  # @atproto/lex-server
2
2
 
3
+ ## 0.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5151](https://github.com/bluesky-social/atproto/pull/5151) [`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update dependencies
8
+
9
+ - Updated dependencies [[`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7)]:
10
+ - @atproto/crypto@0.5.2
11
+ - @atproto/did@0.5.2
12
+ - @atproto-labs/did-resolver@0.3.3
13
+ - @atproto/lex-cbor@0.1.2
14
+ - @atproto/lex-client@0.1.5
15
+ - @atproto/lex-data@0.1.3
16
+ - @atproto/lex-json@0.1.2
17
+ - @atproto/lex-schema@0.1.5
18
+
19
+ ## 0.1.2
20
+
21
+ ### Patch Changes
22
+
23
+ - [#4967](https://github.com/bluesky-social/atproto/pull/4967) [`9fc720c`](https://github.com/bluesky-social/atproto/commit/9fc720ce75f3ee88a5e48a9be919b07c7647f6f5) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use TypeScript 7 to build package
24
+
25
+ - Updated dependencies [[`9fc720c`](https://github.com/bluesky-social/atproto/commit/9fc720ce75f3ee88a5e48a9be919b07c7647f6f5)]:
26
+ - @atproto-labs/did-resolver@0.3.2
27
+ - @atproto/lex-client@0.1.4
28
+ - @atproto/lex-schema@0.1.4
29
+ - @atproto/lex-cbor@0.1.1
30
+ - @atproto/lex-data@0.1.2
31
+ - @atproto/lex-json@0.1.1
32
+ - @atproto/crypto@0.5.1
33
+ - @atproto/did@0.5.1
34
+
3
35
  ## 0.1.1
4
36
 
5
37
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAExE,OAAO,EACL,eAAe,EAEhB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,QAAQ,EAAE,CAAA;AACnB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,CAAA;AAE3D;;;GAGG;AACH,qBAAa,cAAc,CACzB,CAAC,SAAS,YAAY,GAAG,YAAY,CACrC,SAAQ,QAAQ,CAAC,CAAC,CAAC;IAMjB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;IANhC,IAAI,SAAmB;IAEvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;gBAGf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,YAAY;IAMf,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC;IAI3B,UAAU,IAAI,QAAQ;IAM7B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc;CAgC5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,kBAAkB,CAC7B,CAAC,SAAS,YAAY,GAAG,YAAY,CACrC,SAAQ,cAAc,CAAC,CAAC,CAAC;IAcvB,QAAQ,CAAC,eAAe,EAAE,eAAe;IAb3C,IAAI,SAAuB;IAE3B;;;;;;;OAOG;gBAED,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,MAAM,EACN,eAAe,GAAE,eAAoB,EAC9C,OAAO,CAAC,EAAE,YAAY;IAWxB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,IAAI,CACT,KAAK,EAAE,OAAO,EACd,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB;CAqBtB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAExE,OAAO,EACL,eAAe,EAEhB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,QAAQ,EAAE,CAAA;AACnB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,CAAA;AAE3D;;;GAGG;AACH,qBAAa,cAAc,CACzB,CAAC,SAAS,YAAY,GAAG,YAAY,CACrC,SAAQ,QAAQ,CAAC,CAAC,CAAC;IAMjB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;IANhC,IAAI,SAAmB;IAEvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAE1B,YACW,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,YAAY,EAIvB;IAEQ,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC,CAEjC;IAEM,UAAU,IAAI,QAAQ,CAI5B;IAED,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA+B1C;CACF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,kBAAkB,CAC7B,CAAC,SAAS,YAAY,GAAG,YAAY,CACrC,SAAQ,cAAc,CAAC,CAAC,CAAC;IAcvB,QAAQ,CAAC,eAAe,EAAE,eAAe;IAb3C,IAAI,SAAuB;IAE3B;;;;;;;OAOG;IACH,YACE,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,MAAM,EACN,eAAe,GAAE,eAAoB,EAC9C,OAAO,CAAC,EAAE,YAAY,EASvB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,IAAI,CACT,KAAK,EAAE,OAAO,EACd,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,CAoBpB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { XrpcError } from '@atproto/lex-client'\nimport { LexError, LexErrorCode, LexErrorData } from '@atproto/lex-data'\nimport { LexValidationError } from '@atproto/lex-schema'\nimport {\n WWWAuthenticate,\n formatWWWAuthenticateHeader,\n} from './lib/www-authenticate.js'\n\nexport { LexError }\nexport type { LexErrorCode, LexErrorData, WWWAuthenticate }\n\n/**\n * Base error class for representing errors that should be converted to XRPC\n * error responses.\n */\nexport class LexServerError<\n N extends LexErrorCode = LexErrorCode,\n> extends LexError<N> {\n name = 'LexServerError'\n\n readonly headers?: Headers\n\n constructor(\n readonly status: number,\n readonly body: LexErrorData<N>,\n headers?: HeadersInit,\n options?: ErrorOptions,\n ) {\n super(body.error, body.message, options)\n this.headers = headers ? new Headers(headers) : undefined\n }\n\n override toJSON(): LexErrorData<N> {\n return this.body\n }\n\n public toResponse(): Response {\n const { status, headers } = this\n // @NOTE using this.toJSON() instead of this.body to allow overrides in subclasses\n return Response.json(this.toJSON(), { status, headers })\n }\n\n static from(cause: unknown): LexServerError {\n if (cause instanceof LexServerError) {\n return cause\n }\n\n // Convert @atproto/lex-client errors to downstream LexServerError\n if (cause instanceof XrpcError) {\n const { status, body, headers } = cause.toDownstreamError()\n return new LexServerError(status, body, headers, { cause })\n }\n\n // Convert @atproto/lex-schema validation errors to 400 Bad Request\n if (cause instanceof LexValidationError) {\n return new LexServerError(400, cause.toJSON(), undefined, {\n cause,\n })\n }\n\n // Any other error is treated as a generic 500 Internal Server Error\n if (cause instanceof LexError) {\n return new LexServerError(500, cause.toJSON(), undefined, {\n cause,\n })\n }\n\n return new LexServerError(\n 500,\n { error: 'InternalServerError', message: 'An internal error occurred' },\n undefined,\n { cause },\n )\n }\n}\n\n/**\n * Error class for authentication failures in XRPC server handlers.\n *\n * Extends {@link LexError} to include WWW-Authenticate header support,\n * which is required by HTTP authentication standards (RFC 7235).\n * The error automatically generates the appropriate 401 response with\n * the WWW-Authenticate header when converted to a Response.\n *\n * @typeParam N - The Lexicon error code type\n *\n * @example Throwing an auth error\n * ```typescript\n * import { LexServerAuthError } from '@atproto/lex-server'\n *\n * throw new LexServerAuthError(\n * 'AuthenticationRequired',\n * 'Invalid or expired token',\n * { Bearer: { error: 'InvalidToken', realm: 'api.example.com' } }\n * )\n * ```\n */\nexport class LexServerAuthError<\n N extends LexErrorCode = LexErrorCode,\n> extends LexServerError<N> {\n name = 'LexServerAuthError'\n\n /**\n * Creates a new authentication error.\n *\n * @param error - The Lexicon error code (e.g., 'AuthenticationRequired')\n * @param message - Human-readable error message\n * @param wwwAuthenticate - WWW-Authenticate header parameters\n * @param options - Standard Error options including `cause`\n */\n constructor(\n error: N,\n message: string,\n readonly wwwAuthenticate: WWWAuthenticate = {},\n options?: ErrorOptions,\n ) {\n const headers = Object.keys(wwwAuthenticate).length\n ? new Headers({\n 'WWW-Authenticate': formatWWWAuthenticateHeader(wwwAuthenticate),\n 'Access-Control-Expose-Headers': 'WWW-Authenticate', // CORS\n })\n : undefined\n super(401, { error, message }, headers, options)\n }\n\n /**\n * Creates a LexServerAuthError from an existing LexError.\n *\n * If the input is already a LexServerAuthError, returns it unchanged.\n * Otherwise, wraps the error with the provided WWW-Authenticate parameters.\n *\n * @param cause - The original LexError to wrap\n * @param wwwAuthenticate - WWW-Authenticate header parameters\n * @returns A LexServerAuthError instance\n *\n * @example\n * ```typescript\n * function authenticate(token: string): Promise<User> {\n * try {\n * return await validateToken(token)\n * } catch (cause) {\n * throw LexServerAuthError.from(cause, {\n * Bearer: { error: 'InvalidToken' }\n * })\n * }\n * }\n * ```\n */\n static from(\n cause: unknown,\n wwwAuthenticate?: WWWAuthenticate,\n ): LexServerAuthError {\n if (cause instanceof LexServerAuthError) {\n return cause\n }\n\n if (cause instanceof LexError) {\n return new LexServerAuthError(\n cause.error,\n cause.message,\n wwwAuthenticate,\n { cause },\n )\n }\n\n return new LexServerAuthError(\n 'AuthenticationRequired',\n 'Authentication failed',\n wwwAuthenticate,\n { cause },\n )\n }\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { XrpcError } from '@atproto/lex-client'\nimport { LexError, LexErrorCode, LexErrorData } from '@atproto/lex-data'\nimport { LexValidationError } from '@atproto/lex-schema'\nimport {\n WWWAuthenticate,\n formatWWWAuthenticateHeader,\n} from './lib/www-authenticate.js'\n\nexport { LexError }\nexport type { LexErrorCode, LexErrorData, WWWAuthenticate }\n\n/**\n * Base error class for representing errors that should be converted to XRPC\n * error responses.\n */\nexport class LexServerError<\n N extends LexErrorCode = LexErrorCode,\n> extends LexError<N> {\n name = 'LexServerError'\n\n readonly headers?: Headers\n\n constructor(\n readonly status: number,\n readonly body: LexErrorData<N>,\n headers?: HeadersInit,\n options?: ErrorOptions,\n ) {\n super(body.error, body.message, options)\n this.headers = headers ? new Headers(headers) : undefined\n }\n\n override toJSON(): LexErrorData<N> {\n return this.body\n }\n\n public toResponse(): Response {\n const { status, headers } = this\n // @NOTE using this.toJSON() instead of this.body to allow overrides in subclasses\n return Response.json(this.toJSON(), { status, headers })\n }\n\n static from(cause: unknown): LexServerError {\n if (cause instanceof LexServerError) {\n return cause\n }\n\n // Convert @atproto/lex-client errors to downstream LexServerError\n if (cause instanceof XrpcError) {\n const { status, body, headers } = cause.toDownstreamError()\n return new LexServerError(status, body, headers, { cause })\n }\n\n // Convert @atproto/lex-schema validation errors to 400 Bad Request\n if (cause instanceof LexValidationError) {\n return new LexServerError(400, cause.toJSON(), undefined, {\n cause,\n })\n }\n\n // Any other error is treated as a generic 500 Internal Server Error\n if (cause instanceof LexError) {\n return new LexServerError(500, cause.toJSON(), undefined, {\n cause,\n })\n }\n\n return new LexServerError(\n 500,\n { error: 'InternalServerError', message: 'An internal error occurred' },\n undefined,\n { cause },\n )\n }\n}\n\n/**\n * Error class for authentication failures in XRPC server handlers.\n *\n * Extends {@link LexError} to include WWW-Authenticate header support,\n * which is required by HTTP authentication standards (RFC 7235).\n * The error automatically generates the appropriate 401 response with\n * the WWW-Authenticate header when converted to a Response.\n *\n * @typeParam N - The Lexicon error code type\n *\n * @example Throwing an auth error\n * ```typescript\n * import { LexServerAuthError } from '@atproto/lex-server'\n *\n * throw new LexServerAuthError(\n * 'AuthenticationRequired',\n * 'Invalid or expired token',\n * { Bearer: { error: 'InvalidToken', realm: 'api.example.com' } }\n * )\n * ```\n */\nexport class LexServerAuthError<\n N extends LexErrorCode = LexErrorCode,\n> extends LexServerError<N> {\n name = 'LexServerAuthError'\n\n /**\n * Creates a new authentication error.\n *\n * @param error - The Lexicon error code (e.g., 'AuthenticationRequired')\n * @param message - Human-readable error message\n * @param wwwAuthenticate - WWW-Authenticate header parameters\n * @param options - Standard Error options including `cause`\n */\n constructor(\n error: N,\n message: string,\n readonly wwwAuthenticate: WWWAuthenticate = {},\n options?: ErrorOptions,\n ) {\n const headers = Object.keys(wwwAuthenticate).length\n ? new Headers({\n 'WWW-Authenticate': formatWWWAuthenticateHeader(wwwAuthenticate),\n 'Access-Control-Expose-Headers': 'WWW-Authenticate', // CORS\n })\n : undefined\n super(401, { error, message }, headers, options)\n }\n\n /**\n * Creates a LexServerAuthError from an existing LexError.\n *\n * If the input is already a LexServerAuthError, returns it unchanged.\n * Otherwise, wraps the error with the provided WWW-Authenticate parameters.\n *\n * @param cause - The original LexError to wrap\n * @param wwwAuthenticate - WWW-Authenticate header parameters\n * @returns A LexServerAuthError instance\n *\n * @example\n * ```typescript\n * function authenticate(token: string): Promise<User> {\n * try {\n * return await validateToken(token)\n * } catch (cause) {\n * throw LexServerAuthError.from(cause, {\n * Bearer: { error: 'InvalidToken' }\n * })\n * }\n * }\n * ```\n */\n static from(\n cause: unknown,\n wwwAuthenticate?: WWWAuthenticate,\n ): LexServerAuthError {\n if (cause instanceof LexServerAuthError) {\n return cause\n }\n\n if (cause instanceof LexError) {\n return new LexServerAuthError(\n cause.error,\n cause.message,\n wwwAuthenticate,\n { cause },\n )\n }\n\n return new LexServerAuthError(\n 'AuthenticationRequired',\n 'Authentication failed',\n wwwAuthenticate,\n { cause },\n )\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lex-router.d.ts","sourceRoot":"","sources":["../src/lex-router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lex-router.d.ts","sourceRoot":"","sources":["../src/lex-router.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lex-router.js","sourceRoot":"","sources":["../src/lex-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode } from '@atproto/lex-cbor'\nimport {\n LexError,\n LexErrorData,\n LexValue,\n isPlainObject,\n ui8Concat,\n} from '@atproto/lex-data'\nimport { lexParse, lexToJson } from '@atproto/lex-json'\nimport {\n DidString,\n InferMethodInput,\n InferMethodMessage,\n InferMethodOutput,\n InferMethodOutputBody,\n InferMethodOutputEncoding,\n InferMethodParams,\n Main,\n NsidString,\n Procedure,\n Query,\n Subscription,\n getMain,\n isDidString,\n isNsidString,\n} from '@atproto/lex-schema'\nimport { LexServerError } from './errors.js'\nimport { drainWebsocket } from './lib/drain-websocket.js'\n\nconst XRPC_PATH_PREFIX = '/xrpc/'\nconst XRPC_HEALTH_CHECK_PATH = '/xrpc/_health'\n\ntype Awaitable<T> = T | Promise<T>\n\n/**\n * Union type representing the supported Lexicon method types.\n *\n * - `Query`: Read-only methods invoked via HTTP GET\n * - `Procedure`: Methods that may modify state, invoked via HTTP POST\n * - `Subscription`: Real-time streaming methods over WebSocket\n */\nexport type LexMethod = Query | Procedure | Subscription\n\n/**\n * Network address for TCP or UDP connections.\n *\n * @example\n * ```typescript\n * const addr: NetAddr = {\n * hostname: '127.0.0.1',\n * port: 3000,\n * transport: 'tcp'\n * }\n * ```\n */\nexport type NetAddr = {\n /** The hostname or IP address of the connection. */\n hostname: string\n /** The port number of the connection. */\n port: number\n /** The transport protocol used. */\n transport: 'tcp' | 'udp'\n}\n\n/**\n * Unix domain socket address.\n *\n * @example\n * ```typescript\n * const addr: UnixAddr = {\n * path: '/var/run/app.sock',\n * transport: 'unix'\n * }\n * ```\n */\nexport type UnixAddr = {\n /** The filesystem path to the Unix socket. */\n path: string\n /** The transport protocol used. */\n transport: 'unix' | 'unixpacket'\n}\n\n/**\n * Union type for all supported address types.\n *\n * Can be a network address ({@link NetAddr}), Unix socket address ({@link UnixAddr}),\n * or `undefined` when the address is not available.\n */\nexport type Addr = NetAddr | UnixAddr | undefined\n\n/**\n * Metadata about the client connection for an incoming request.\n *\n * @typeParam A - The address type, defaults to {@link Addr}\n *\n * @example\n * ```typescript\n * const info: ConnectionInfo<NetAddr> = {\n * remoteAddr: { hostname: '192.168.1.1', port: 54321, transport: 'tcp' },\n * completed: new Promise((resolve) => socket.on('close', resolve))\n * }\n * ```\n */\nexport type ConnectionInfo<A extends Addr = Addr> = {\n /** The remote address of the client, if available. */\n remoteAddr: A\n /** Promise that resolves when the connection is fully closed. */\n completed: Promise<void>\n}\n\n/**\n * Function signature for handling HTTP requests in the XRPC router.\n *\n * This is the standard fetch-style handler that processes incoming requests\n * and returns responses. It is used both internally by the router and can\n * be used to integrate with other HTTP frameworks.\n *\n * @param request - The incoming HTTP request\n * @param connection - Optional connection metadata including remote address\n * @returns A promise resolving to the HTTP response\n *\n * @example\n * ```typescript\n * const handler: FetchHandler = async (request, connection) => {\n * console.log('Request from:', connection?.remoteAddr)\n * return new Response('Hello, World!')\n * }\n * ```\n */\nexport type FetchHandler = (\n request: Request,\n connection?: ConnectionInfo,\n) => Promise<Response>\n\n/**\n * Context object passed to XRPC method handlers.\n *\n * Contains all the information needed to process a request, including\n * parsed parameters, authentication credentials, and the raw request object.\n *\n * @typeParam Method - The Lexicon method type (Query, Procedure, or Subscription)\n * @typeParam Credentials - The type of authentication credentials, determined by the auth handler\n *\n * @example\n * ```typescript\n * const handler: LexRouterMethodHandler<MyMethod, UserCredentials> = async (ctx) => {\n * const { credentials, params, input, signal } = ctx\n * // credentials.userId is available if auth handler returns UserCredentials\n * // params contains validated query parameters\n * // input contains the request body (for procedures)\n * // signal can be used to abort long-running operations\n * return { body: { result: 'success' } }\n * }\n * ```\n */\nexport type LexRouterHandlerContext<Method extends LexMethod, Credentials> = {\n /** Authentication credentials returned by the auth handler. */\n credentials: Credentials\n /** Parsed and validated request input (body for procedures, undefined for queries). */\n input: InferMethodInput<Method, Body>\n /** Parsed and validated URL query parameters. */\n params: InferMethodParams<Method>\n /** The original HTTP request object. */\n request: Request\n /** Abort signal that is triggered when the request is cancelled. */\n signal: AbortSignal\n /** Connection metadata including remote address. */\n connection?: ConnectionInfo\n}\n\ntype AsOptionalPayloadOptions<T> = T extends undefined | void\n ? { encoding?: undefined; body?: undefined }\n : T\n\n/**\n * Return type for XRPC method handlers (queries and procedures).\n *\n * Handlers can return either:\n * - A raw {@link Response} object for full control over the HTTP response\n * - An object with `body`, optional `encoding`, and optional `headers`\n *\n * For JSON methods, the body is automatically serialized. For other encodings,\n * the body must be a valid {@link BodyInit} type.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n *\n * @example\n * ```typescript\n * // Return JSON body (most common)\n * return { body: { users: [...] } }\n *\n * // Return with custom headers\n * return {\n * body: { data: 'value' },\n * headers: { 'Cache-Control': 'max-age=3600' }\n * }\n *\n * // Return raw Response for full control\n * return new Response(binaryData, {\n * headers: { 'Content-Type': 'application/octet-stream' }\n * })\n * ```\n */\nexport type LexRouterHandlerOutput<Method extends Query | Procedure> =\n | Response\n | ({\n headers?: HeadersInit\n } & (InferMethodOutputEncoding<Method> extends 'application/json'\n ? {\n // Allow omitting body when output is JSON\n encoding?: 'application/json'\n body: InferMethodOutputBody<Method>\n }\n : AsOptionalPayloadOptions<InferMethodOutput<Method, BodyInit>>))\n\n/**\n * Handler function for XRPC query and procedure methods.\n *\n * Receives a context object with request details and credentials,\n * and returns either a Response or a structured output object.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const getProfile: LexRouterMethodHandler<GetProfileMethod, UserCredentials> = async (ctx) => {\n * const profile = await db.getProfile(ctx.params.actor)\n * return { body: profile }\n * }\n * ```\n */\nexport type LexRouterMethodHandler<\n Method extends Query | Procedure = Query | Procedure,\n Credentials = unknown,\n> = (\n ctx: LexRouterHandlerContext<Method, Credentials>,\n) => Awaitable<LexRouterHandlerOutput<Method>>\n\n/**\n * Configuration object for registering an XRPC method with authentication.\n *\n * Used when you need to specify both a handler and an auth function.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const config: LexRouterMethodConfig<GetProfileMethod, UserCredentials> = {\n * handler: async (ctx) => {\n * return { body: await getProfile(ctx.params.actor) }\n * },\n * auth: async ({ request }) => {\n * return verifyToken(request.headers.get('authorization'))\n * }\n * }\n * ```\n */\nexport type LexRouterMethodConfig<\n Method extends Query | Procedure = Query | Procedure,\n Credentials = unknown,\n> = {\n /** The handler function that processes the request. */\n handler: LexRouterMethodHandler<Method, Credentials>\n /** Authentication function that validates credentials before the handler runs. */\n auth: LexRouterAuth<Credentials, Method>\n}\n\n/**\n * Handler function for XRPC subscription methods (WebSocket streams).\n *\n * Returns an async iterable that yields messages to be sent over the WebSocket.\n * The connection remains open until the iterable completes or an error occurs.\n *\n * @typeParam Method - The Lexicon subscription method type\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const subscribeRepos: LexRouterSubscriptionHandler<SubscribeReposMethod> = async function* (ctx) {\n * const cursor = ctx.params.cursor ?? 0\n * for await (const event of eventStream.since(cursor)) {\n * if (ctx.signal.aborted) break\n * yield { $type: 'com.atproto.sync.subscribeRepos#commit', ...event }\n * }\n * }\n * ```\n */\nexport type LexRouterSubscriptionHandler<\n Method extends Subscription = Subscription,\n Credentials = unknown,\n> = (\n ctx: LexRouterHandlerContext<Method, Credentials>,\n) => AsyncIterable<InferMethodMessage<Method>>\n\n/**\n * Configuration object for registering an XRPC subscription with authentication.\n *\n * Used when you need to specify both a handler and an auth function for subscriptions.\n *\n * @typeParam Method - The Lexicon subscription method type\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const config: LexRouterSubscriptionConfig<SubscribeReposMethod, ServiceCredentials> = {\n * handler: async function* (ctx) {\n * for await (const event of eventStream) {\n * yield event\n * }\n * },\n * auth: async ({ request }) => {\n * return verifyServiceAuth(request)\n * }\n * }\n * ```\n */\nexport type LexRouterSubscriptionConfig<\n Method extends Subscription = Subscription,\n Credentials = unknown,\n> = {\n /** The handler function that yields subscription messages. */\n handler: LexRouterSubscriptionHandler<Method, Credentials>\n /** Authentication function that validates credentials before the handler runs. */\n auth: LexRouterAuth<Credentials, Method>\n}\n\n/**\n * Context object passed to authentication handlers.\n *\n * Contains the information needed to authenticate a request before\n * the main handler is invoked.\n *\n * @typeParam Method - The Lexicon method type\n *\n * @example\n * ```typescript\n * const authHandler: LexRouterAuth<UserCredentials> = async (ctx) => {\n * const token = ctx.request.headers.get('authorization')\n * if (!token) throw new LexServerAuthError('AuthenticationRequired', 'Missing token')\n * return { userId: await verifyToken(token) }\n * }\n * ```\n */\nexport type LexRouterAuthContext<Method extends LexMethod = LexMethod> = {\n /** The Lexicon method definition being called. */\n method: Method\n /** Parsed and validated URL query parameters. */\n params: InferMethodParams<Method>\n /** The original HTTP request object. */\n request: Request\n /** Connection metadata including remote address. */\n connection?: ConnectionInfo\n}\n\n/**\n * Authentication handler function for XRPC methods.\n *\n * Called before the main handler to validate authentication credentials.\n * Should return the validated credentials or throw an error if authentication fails.\n *\n * @typeParam Credentials - The type of credentials to return on success\n * @typeParam Method - The Lexicon method type\n *\n * @example\n * ```typescript\n * // Simple token-based auth\n * const tokenAuth: LexRouterAuth<{ userId: string }> = async ({ request }) => {\n * const token = request.headers.get('authorization')?.replace('Bearer ', '')\n * if (!token) throw new LexServerAuthError('AuthenticationRequired', 'Token required')\n * const userId = await verifyToken(token)\n * if (!userId) throw new LexServerAuthError('AuthenticationRequired', 'Invalid token')\n * return { userId }\n * }\n *\n * // Using with serviceAuth for AT Protocol service authentication\n * import { serviceAuth } from '@atproto/lex-server'\n * const auth = serviceAuth({ audience: 'did:web:example.com', unique: checkNonce })\n * ```\n */\nexport type LexRouterAuth<\n Credentials = unknown,\n Method extends LexMethod = LexMethod,\n> = (ctx: LexRouterAuthContext<Method>) => Credentials | Promise<Credentials>\n\n/**\n * Context object passed to error handler callbacks.\n *\n * Used for logging and monitoring errors that occur during request handling.\n */\nexport type HandlerErrorContext = {\n request: Request\n method: LexMethod\n error: LexServerError\n}\n\nexport type HandlerErrorHook = (\n ctx: HandlerErrorContext,\n) => void | Promise<void>\n\nexport type SocketErrorContext = {\n request: Request\n method: Subscription\n error: unknown\n}\n\nexport type SocketErrorHook = (ctx: SocketErrorContext) => void | Promise<void>\n\n/**\n * Function that upgrades an HTTP request to a WebSocket connection.\n *\n * This is platform-specific: Deno provides this natively, while Node.js\n * requires the `upgradeWebSocket` function from this package.\n *\n * @param request - The HTTP request to upgrade\n * @returns An object containing the WebSocket and the upgrade response\n *\n * @example\n * ```typescript\n * // In Node.js, use the provided upgradeWebSocket function\n * import { upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n * ```\n */\nexport type UpgradeWebSocket = (request: Request) => {\n /** The WebSocket instance for bidirectional communication. */\n socket: WebSocket\n /** The HTTP response to return (101 Switching Protocols). */\n response: Response\n}\n\nexport type HealthCheckHandler = (\n request: Request,\n) => Awaitable<{ [x: string]: unknown; status: 'ok' }>\n\n/**\n * Configuration options for the {@link LexRouter}.\n *\n * @example\n * ```typescript\n * const options: LexRouterOptions = {\n * upgradeWebSocket,\n * onHandlerError: async ({ error, request, method }) => {\n * console.error(`Error in ${method.nsid}:`, error)\n * await reportToSentry(error)\n * },\n * highWaterMark: 64 * 1024, // 64KB\n * lowWaterMark: 16 * 1024 // 16KB\n * }\n * ```\n */\nexport type LexRouterOptions = {\n /**\n * Function to upgrade HTTP requests to WebSocket connections. Required for\n * subscription methods. Defaults to Deno's built-in\n * {@link globalThis.upgradeWebSocket} if available. For NodeJS, use the\n * homonymous export from `@atproto/lex-server/nodejs`.\n */\n upgradeWebSocket?: UpgradeWebSocket\n /**\n * Callback invoked when an error occurs during request handling. Useful for\n * logging and error reporting. Not called for client-induced errors (e.g.,\n * request abortion).\n */\n onHandlerError?: HandlerErrorHook\n /**\n * Optional hook for handling errors during generation of WebSocket messages.\n */\n onSocketError?: SocketErrorHook\n /**\n * Optional health check handler. If provided, this function will be called\n * for requests to the /xrpc/_health endpoint, allowing for custom health\n * check logic and responses.\n *\n * If not provided, the server will respond to /xrpc/_health requests with a\n * default JSON response of `{ status: 'ok' }`.\n */\n healthCheck?: HealthCheckHandler\n /**\n * Optional fallback handler for requests that are not /xrpc/ paths. Can be\n * used to serve static files or other routes. If not provided, non-/xrpc/\n * requests will return 404 responses.\n */\n fallback?: FetchHandler\n /**\n * High water mark for WebSocket backpressure (in bytes). When buffered data\n * exceeds this, the handler will wait before sending more.\n */\n highWaterMark?: number\n /**\n * Low water mark for WebSocket backpressure (in bytes). The handler resumes\n * sending when buffered data drops below this.\n */\n lowWaterMark?: number\n}\n\n/**\n * XRPC router for handling AT Protocol Lexicon methods.\n *\n * The router handles HTTP routing, parameter parsing, input validation,\n * authentication, and response serialization for XRPC methods. It supports\n * queries (GET), procedures (POST), and subscriptions (WebSocket).\n *\n * @example Setting up a basic XRPC server\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n * import { getProfile, createPost, subscribeRepos } from './lexicons.js'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Register a query handler (GET request)\n * router.add(getProfile, async (ctx) => {\n * const profile = await db.getProfile(ctx.params.actor)\n * return { body: profile }\n * })\n *\n * // Register a procedure handler with authentication (POST request)\n * router.add(createPost, {\n * handler: async (ctx) => {\n * const post = await db.createPost(ctx.credentials.did, ctx.input.body)\n * return { body: { uri: post.uri, cid: post.cid } }\n * },\n * auth: async ({ request }) => {\n * return verifyAccessToken(request)\n * }\n * })\n *\n * // Register a subscription handler (WebSocket)\n * router.add(subscribeRepos, async function* (ctx) {\n * for await (const event of eventStream.since(ctx.params.cursor)) {\n * if (ctx.signal.aborted) break\n * yield event\n * }\n * })\n *\n * // Start the server\n * const server = await serve(router, { port: 3000 })\n * console.log('XRPC server listening on port 3000')\n * ```\n *\n * @example Using with service authentication\n * ```typescript\n * import { LexRouter, serviceAuth } from '@atproto/lex-server'\n *\n * const router = new LexRouter()\n *\n * const auth = serviceAuth({\n * audience: 'did:web:api.example.com',\n * unique: async (nonce) => {\n * // Check and record nonce uniqueness\n * return await nonceStore.checkAndAdd(nonce)\n * }\n * })\n *\n * router.add(protectedMethod, {\n * handler: async (ctx) => {\n * // ctx.credentials contains { did, didDocument, jwt }\n * return { body: { callerDid: ctx.credentials.did } }\n * },\n * auth\n * })\n * ```\n */\nexport class LexRouter {\n /** Map of NSID strings to their fetch handlers. */\n readonly handlers: Map<NsidString, FetchHandler> = new Map()\n\n /**\n * Creates a new XRPC router.\n *\n * @param options - Router configuration options\n */\n constructor(readonly options: LexRouterOptions = {}) {}\n\n /**\n * Registers a subscription handler without authentication.\n *\n * @param ns - The Lexicon namespace definition for the subscription\n * @param handler - Async generator function that yields subscription messages\n * @returns This router instance for chaining\n */\n add<M extends Subscription>(\n ns: Main<M>,\n handler: LexRouterSubscriptionHandler<M, void>,\n ): this\n /**\n * Registers a subscription handler with authentication.\n *\n * @param ns - The Lexicon namespace definition for the subscription\n * @param config - Configuration object with handler and auth function\n * @returns This router instance for chaining\n */\n add<M extends Subscription, Credentials>(\n ns: Main<M>,\n config: LexRouterSubscriptionConfig<M, Credentials>,\n ): this\n /**\n * Registers a query or procedure handler without authentication.\n *\n * @param ns - The Lexicon namespace definition for the method\n * @param handler - Handler function that processes requests\n * @returns This router instance for chaining\n */\n add<M extends Query | Procedure>(\n ns: Main<M>,\n handler: LexRouterMethodHandler<M, void>,\n ): this\n /**\n * Registers a query or procedure handler with authentication.\n *\n * @param ns - The Lexicon namespace definition for the method\n * @param config - Configuration object with handler and auth function\n * @returns This router instance for chaining\n */\n add<M extends Query | Procedure, Credentials>(\n ns: Main<M>,\n config: LexRouterMethodConfig<M, Credentials>,\n ): this\n /**\n * Registers a Lexicon method handler.\n *\n * This is the unified overload that accepts any method type with optional authentication.\n *\n * @param ns - The Lexicon namespace definition\n * @param config - Handler function or configuration object\n * @returns This router instance for chaining\n *\n * @throws {TypeError} If a method with the same NSID is already registered\n *\n * @example\n * ```typescript\n * // Register without auth (credentials will be void)\n * router.add(myQuery, async (ctx) => {\n * return { body: { data: 'value' } }\n * })\n *\n * // Register with auth\n * router.add(myProcedure, {\n * handler: async (ctx) => {\n * console.log('Caller:', ctx.credentials.userId)\n * return { body: { success: true } }\n * },\n * auth: async ({ request }) => ({ userId: await verifyToken(request) })\n * })\n * ```\n */\n add<M extends LexMethod, Credentials = unknown>(\n ns: Main<M>,\n config: M extends Subscription\n ?\n | LexRouterSubscriptionHandler<M, Credentials>\n | LexRouterSubscriptionConfig<M, Credentials>\n : M extends Query | Procedure\n ?\n | LexRouterMethodHandler<M, Credentials>\n | LexRouterMethodConfig<M, Credentials>\n : never,\n ): this\n add<M extends LexMethod>(\n ns: Main<M>,\n config:\n | LexRouterSubscriptionHandler<any, any>\n | LexRouterSubscriptionConfig<any, any>\n | LexRouterMethodHandler<any, any>\n | LexRouterMethodConfig<any, any>,\n ) {\n const method = getMain(ns)\n const nsid = normalizeNsid(method.nsid)\n\n if (this.handlers.has(nsid)) {\n throw new TypeError(`Method ${method.nsid} already registered`)\n }\n\n const methodConfig =\n typeof config === 'function'\n ? { handler: config, auth: undefined }\n : config\n\n const handler: FetchHandler =\n method.type === 'subscription'\n ? this.buildSubscriptionHandler(\n method,\n methodConfig.handler as LexRouterSubscriptionHandler<any, any>,\n methodConfig.auth,\n )\n : this.buildMethodHandler(\n method,\n methodConfig.handler as LexRouterMethodHandler<any, any>,\n methodConfig.auth,\n )\n\n this.handlers.set(nsid, handler)\n\n return this\n }\n\n private buildMethodHandler<Method extends Query | Procedure, Credentials>(\n method: Method,\n methodHandler: LexRouterMethodHandler<Method, Credentials>,\n auth?: LexRouterAuth<Credentials, Method>,\n ): FetchHandler {\n const getInput = (\n method.type === 'procedure'\n ? getProcedureInput.bind(method)\n : getQueryInput.bind(method)\n ) as (request: Request) => Promise<InferMethodInput<Method, Body>>\n\n return async (request, connection) => {\n // @NOTE CORS requests should be handled by a middleware before reaching\n // this point.\n if (\n (method.type === 'procedure' && request.method !== 'POST') ||\n (method.type === 'query' &&\n request.method !== 'GET' &&\n request.method !== 'HEAD')\n ) {\n return invalidRequestResponse('Method not allowed', 405)\n }\n\n try {\n const url = new URL(request.url)\n const params = method.parameters.fromURLSearchParams(\n url.searchParams,\n ) as InferMethodParams<Method>\n\n const credentials = auth\n ? await auth({ method, params, request, connection })\n : (undefined as Credentials)\n\n const input = await getInput(request)\n\n const output = await methodHandler({\n credentials,\n params,\n input,\n request,\n connection,\n signal: request.signal,\n })\n\n if (output instanceof Response) {\n return output\n }\n\n // @TODO add validation of output based on method.output.schema?\n\n if (output.body === undefined && output.encoding === undefined) {\n return new Response(null, { status: 200, headers: output.headers })\n }\n\n if (method.output?.encoding === 'application/json') {\n return Response.json(lexToJson(output.body as LexValue), {\n status: 200,\n headers: output.headers,\n })\n }\n\n const headers = new Headers(output.headers)\n headers.set('content-type', output.encoding!)\n return new Response(output.body as BodyInit | null | undefined, {\n status: 200,\n headers,\n })\n } catch (error) {\n return this.handlerError(request, method, error)\n }\n }\n }\n\n private buildSubscriptionHandler<Method extends Subscription, Credentials>(\n method: Method,\n methodHandler: LexRouterSubscriptionHandler<Method, Credentials>,\n auth?: LexRouterAuth<Credentials, Method>,\n ): FetchHandler {\n const {\n onSocketError,\n upgradeWebSocket = (globalThis as any).Deno?.upgradeWebSocket as\n | UpgradeWebSocket\n | undefined,\n } = this.options\n if (!upgradeWebSocket) {\n throw new TypeError(\n 'WebSocket upgrade not supported in this environment. Please provide an upgradeWebSocket option when creating the LexRouter.',\n )\n }\n\n return async (request, connection) => {\n if (request.method !== 'GET') {\n return invalidRequestResponse('Method not allowed', 405)\n }\n\n if (\n request.headers.get('connection')?.toLowerCase() !== 'upgrade' ||\n request.headers.get('upgrade')?.toLowerCase() !== 'websocket'\n ) {\n return invalidRequestResponse(\n 'XRPC subscriptions are only available over WebSocket',\n 426,\n {\n Connection: 'Upgrade',\n Upgrade: 'websocket',\n },\n )\n }\n\n if (request.signal.aborted) {\n return invalidRequestResponse('Request aborted', 499)\n }\n\n try {\n const { response, socket } = upgradeWebSocket(request)\n\n // @NOTE We are using a distinct signal than request.signal because that\n // signal may get aborted before the WebSocket is closed (this is the\n // case with Deno).\n const abortController = new AbortController()\n const { signal } = abortController\n const abort = () => abortController.abort()\n\n const onOpen = async () => {\n try {\n const url = new URL(request.url)\n const params = method.parameters.fromURLSearchParams(\n url.searchParams,\n ) as InferMethodParams<Method>\n\n const credentials: Credentials = auth\n ? await auth({ method, params, request, connection })\n : (undefined as Credentials)\n\n signal.throwIfAborted()\n\n const iterable = methodHandler({\n credentials,\n params,\n input: undefined as InferMethodInput<Method, Body>,\n request,\n connection,\n signal,\n })\n\n const iterator = iterable[Symbol.asyncIterator]()\n\n if (iterator.return) {\n signal.addEventListener(\n 'abort',\n () => {\n // @NOTE if iterator.return() throws, and no onSocketError is\n // provided, or if onSocketError itself throws, the error will\n // be unhandled, causing the process to crash. This is\n // intentional, as it surfaces critical errors that occur\n // during cleanup of the subscription.\n\n void new Promise((resolve) => {\n // Wrapping in new Promise to catch any potential sync errors thrown by iterator.return()\n resolve(iterator.return!())\n }).catch(\n onSocketError\n ? (error) => onSocketError({ request, method, error })\n : null,\n )\n },\n {\n once: true,\n },\n )\n }\n\n while (!signal.aborted && socket.readyState === 1) {\n const result = await iterator.next()\n if (result.done) break\n\n // @TODO add validation of output based on method.output.schema?\n\n const data = encodeMessageFrame(method, result.value)\n\n socket.send(data)\n\n // Apply backpressure by waiting for the buffered data to drain\n // before generating the next message\n await drainWebsocket(socket, signal, this.options)\n }\n\n if (socket.readyState === 1) {\n socket.close(1000)\n }\n } catch (error) {\n // If the socket is still open, send an error frame before closing\n if (socket.readyState === 1) {\n const isLexError = error instanceof LexError\n\n // https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1\n const code =\n isLexError && method.errors?.includes(error.error)\n ? 1008 // Policy Violation for known LexErrors\n : 1011 // Internal Error for unexpected errors\n\n if (isLexError) {\n socket.send(encodeErrorFrame(error.toJSON()))\n socket.close(code, error.error)\n } else {\n const error = 'InternalServerError'\n const message = 'An internal error occurred'\n socket.send(encodeErrorFrame({ error, message }))\n socket.close(code, error)\n }\n }\n\n if (onSocketError && !isAbortReason(signal, error)) {\n await onSocketError({ request, method, error })\n }\n } finally {\n abortController.abort()\n }\n }\n\n socket.addEventListener('error', abort)\n socket.addEventListener('close', abort)\n socket.addEventListener('open', onOpen)\n socket.addEventListener('message', onMessage)\n\n return response\n } catch (error) {\n return this.handlerError(request, method, error)\n }\n }\n }\n\n private async handlerError(\n request: Request,\n method: LexMethod,\n cause: unknown,\n ) {\n // Only report unexpected processing errors\n if (isAbortReason(request.signal, cause)) {\n return Response.json({ error: 'RequestAborted' }, { status: 499 })\n }\n\n const error = LexServerError.from(cause)\n\n const { onHandlerError } = this.options\n if (onHandlerError) await onHandlerError({ error, request, method })\n\n return error.toResponse()\n }\n\n /**\n * The main fetch handler for processing XRPC requests.\n *\n * Routes incoming requests to the appropriate method handler based on the\n * NSID in the URL path. Returns appropriate error responses for invalid\n * paths or unimplemented methods.\n *\n * This handler can be used directly with HTTP servers that support the\n * fetch API pattern, or converted to a Node.js request listener using\n * `toRequestListener()`.\n *\n * @param request - The incoming HTTP request\n * @param connection - Optional connection metadata\n * @returns A promise resolving to the HTTP response\n *\n * @example\n * ```typescript\n * // Use with Deno\n * Deno.serve(router.fetch)\n *\n * // Use with Bun\n * Bun.serve({ fetch: router.fetch })\n *\n * // Use with Node.js\n * import { toRequestListener } from '@atproto/lex-server/nodejs'\n * const listener = toRequestListener(router.fetch)\n * http.createServer(listener).listen(3000)\n * ```\n */\n fetch: FetchHandler = async (\n request: Request,\n connection?: ConnectionInfo,\n ): Promise<Response> => {\n const { pathname } = new URL(request.url)\n const atprotoProxy = request.headers.get('atproto-proxy')\n\n if (!pathname.startsWith(XRPC_PATH_PREFIX)) {\n // Handle non XRPC paths\n const { fallback } = this.options\n if (fallback) return fallback(request, connection)\n return new Response('Not Found', { status: 404 })\n }\n\n if (pathname === XRPC_HEALTH_CHECK_PATH) {\n if (request.method !== 'GET') {\n return invalidRequestResponse('Method not allowed', 405)\n }\n if (atprotoProxy != null) {\n return invalidRequestResponse(\n 'atproto-proxy header is not allowed on health check endpoint',\n )\n }\n\n const { healthCheck } = this.options\n const data = healthCheck ? await healthCheck(request) : { status: 'ok' }\n\n return Response.json(data)\n }\n\n const subPath = pathname.slice(XRPC_PATH_PREFIX.length)\n\n if (!isNsidString(subPath)) {\n return invalidRequestResponse('Invalid NSID in URL path')\n }\n\n const nsid = normalizeNsid(subPath)\n if (atprotoProxy == null) {\n const handler = this.handlers.get(nsid)\n if (handler) return handler(request, connection)\n } else {\n // Handle service proxying logic.\n\n const proxyInfo = parseAtprotoProxyHeader(atprotoProxy)\n if (!proxyInfo) {\n return invalidRequestResponse(\n `Invalid atproto-proxy header value: ${atprotoProxy}`,\n )\n }\n\n // @TODO actually implement service proxying logic here. The reason it was\n // not done already is because we want to perform all the heavy lifting\n // here, while still allowing the possibility to override the endpoint\n // resolution, etc.\n\n // @NOTE see ./service-auth.ts for potential common code (did resolver, etc.)\n }\n\n return Response.json(\n {\n error: 'MethodNotImplemented',\n message: `XRPC method \"${nsid}\" not implemented on this server`,\n },\n { status: 501 },\n )\n }\n}\n\nasync function getProcedureInput<M extends Procedure>(\n this: M,\n request: Request,\n): Promise<InferMethodInput<M, Body>> {\n const encodingRaw = request.headers\n .get('content-type')\n ?.split(';')[0]\n .trim()\n .toLowerCase()\n\n const encoding =\n encodingRaw ||\n // If the caller did not provide a content-type, but the method\n // expects an input, assume binary\n (request.body != null && this.input.encoding != null\n ? 'application/octet-stream'\n : undefined)\n\n if (!this.input.matchesEncoding(encoding)) {\n throw new LexServerError(400, {\n error: 'InvalidRequest',\n message: `Invalid content-type: ${encoding}`,\n })\n }\n\n if (this.input.encoding === 'application/json') {\n // @TODO limit size?\n const data = lexParse(await request.text())\n const body = this.input.schema ? this.input.schema.parse(data) : data\n return { encoding, body } as InferMethodInput<M, Body>\n } else if (this.input.encoding) {\n const body: Body = request\n return { encoding, body } as InferMethodInput<M, Body>\n } else {\n return undefined as InferMethodInput<M, Body>\n }\n}\n\nasync function getQueryInput<M extends Query>(\n this: M,\n request: Request,\n): Promise<InferMethodInput<M, Body>> {\n if (\n request.body ||\n request.headers.has('content-type') ||\n request.headers.has('content-length')\n ) {\n throw new LexServerError(400, {\n error: 'InvalidRequest',\n message: 'GET requests must not have a body',\n })\n }\n\n return undefined as InferMethodInput<M, Body>\n}\n\nfunction onMessage(this: WebSocket, _event: unknown) {\n const error = 'InvalidRequest'\n const message = 'XRPC subscriptions do not accept messages'\n this.send(encodeErrorFrame({ error, message }))\n // 1003 indicates that an endpoint is terminating the connection\n // because it has received a type of data it cannot accept (e.g., an\n // endpoint that understands only text data MAY send this if it\n // receives a binary message).\n this.close(1003, error)\n}\n\n// Pre-encoded frame header for error frames\nconst ERROR_FRAME_HEADER = /*#__PURE__*/ encode({ op: -1 })\n\nfunction encodeErrorFrame(errorData: LexErrorData): Uint8Array<ArrayBuffer> {\n return ui8Concat([ERROR_FRAME_HEADER, encode(errorData)])\n}\n\n// Pre-encoded frame header for message frames with unknown type\nconst UNKNOWN_MESSAGE_FRAME_HEADER = /*#__PURE__*/ encode({ op: 1 })\n\nfunction encodeMessageFrame(\n method: Subscription,\n value: LexValue,\n): Uint8Array<ArrayBuffer> {\n if (isPlainObject(value) && typeof value.$type === 'string') {\n const { $type, ...rest } = value\n return ui8Concat([\n encode({\n op: 1,\n t:\n // If $type starts with `nsid#`, strip the NSID prefix\n $type.charCodeAt(0) !== 0x23 && // '#'\n $type.charCodeAt(method.nsid.length) === 0x23 && // '#'\n $type.startsWith(method.nsid)\n ? $type.slice(method.nsid.length)\n : $type,\n }),\n encode(rest),\n ])\n }\n\n return ui8Concat([UNKNOWN_MESSAGE_FRAME_HEADER, encode(value)])\n}\n\nfunction isAbortReason(signal: AbortSignal, error: unknown): boolean {\n return (\n signal.aborted &&\n signal.reason != null &&\n error instanceof Error &&\n (error === signal.reason || error.cause === signal.reason)\n )\n}\n\nexport type ServiceProxyInfo = {\n did: DidString\n serviceId: string\n}\n\nfunction parseAtprotoProxyHeader(value: string): ServiceProxyInfo | null {\n // /!\\ Hot path\n\n // (fast) sanity check to avoid unnecessary parsing for non-DID values\n if (!value.startsWith('did:')) return null\n\n // The format is expected to be `did:example:service#serviceId`\n const hashIndex = value.indexOf('#')\n if (hashIndex === -1) return null\n\n const fragmentIndex = hashIndex + 1\n // Basic validation if the fragment\n if (fragmentIndex === value.length) return null\n if (value.includes('#', fragmentIndex)) return null\n if (value.includes(' ', fragmentIndex)) return null\n\n const did = value.slice(0, hashIndex)\n if (!isDidString(did)) return null\n\n const serviceId = value.slice(fragmentIndex)\n return { did, serviceId }\n}\n\nfunction normalizeNsid(nsid: NsidString): NsidString {\n const lastDotIdx = nsid.lastIndexOf('.')\n\n // The domain name part of the NSID is case-insensitive, but the last part is\n // case-sensitive. Normalize the domain part to lowercase.\n if (lastDotIdx !== -1 && hasUpperCase(nsid, 0, lastDotIdx)) {\n return `${nsid.slice(0, lastDotIdx).toLowerCase()}.${nsid.slice(lastDotIdx + 1)}` as NsidString\n }\n\n return nsid\n}\n\nfunction hasUpperCase(str: string, start = 0, end = str.length): boolean {\n for (let i = start; i < end; i++) {\n const code = str.charCodeAt(i)\n if (code >= 0x41 && code <= 0x5a) {\n return true\n }\n }\n return false\n}\n\nfunction invalidRequestResponse(\n message: string,\n status = 400,\n headers?: HeadersInit,\n): Response {\n return Response.json(\n {\n error: 'InvalidRequest',\n message,\n },\n { status, headers },\n )\n}\n"]}
1
+ {"version":3,"file":"lex-router.js","sourceRoot":"","sources":["../src/lex-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode } from '@atproto/lex-cbor'\nimport {\n LexError,\n LexErrorData,\n LexValue,\n isPlainObject,\n ui8Concat,\n} from '@atproto/lex-data'\nimport { lexParse, lexToJson } from '@atproto/lex-json'\nimport {\n DidString,\n InferMethodInput,\n InferMethodMessage,\n InferMethodOutput,\n InferMethodOutputBody,\n InferMethodOutputEncoding,\n InferMethodParams,\n Main,\n NsidString,\n Procedure,\n Query,\n Subscription,\n getMain,\n isDidString,\n isNsidString,\n} from '@atproto/lex-schema'\nimport { LexServerError } from './errors.js'\nimport { drainWebsocket } from './lib/drain-websocket.js'\n\nconst XRPC_PATH_PREFIX = '/xrpc/'\nconst XRPC_HEALTH_CHECK_PATH = '/xrpc/_health'\n\ntype Awaitable<T> = T | Promise<T>\n\n/**\n * Union type representing the supported Lexicon method types.\n *\n * - `Query`: Read-only methods invoked via HTTP GET\n * - `Procedure`: Methods that may modify state, invoked via HTTP POST\n * - `Subscription`: Real-time streaming methods over WebSocket\n */\nexport type LexMethod = Query | Procedure | Subscription\n\n/**\n * Network address for TCP or UDP connections.\n *\n * @example\n * ```typescript\n * const addr: NetAddr = {\n * hostname: '127.0.0.1',\n * port: 3000,\n * transport: 'tcp'\n * }\n * ```\n */\nexport type NetAddr = {\n /** The hostname or IP address of the connection. */\n hostname: string\n /** The port number of the connection. */\n port: number\n /** The transport protocol used. */\n transport: 'tcp' | 'udp'\n}\n\n/**\n * Unix domain socket address.\n *\n * @example\n * ```typescript\n * const addr: UnixAddr = {\n * path: '/var/run/app.sock',\n * transport: 'unix'\n * }\n * ```\n */\nexport type UnixAddr = {\n /** The filesystem path to the Unix socket. */\n path: string\n /** The transport protocol used. */\n transport: 'unix' | 'unixpacket'\n}\n\n/**\n * Union type for all supported address types.\n *\n * Can be a network address ({@link NetAddr}), Unix socket address ({@link UnixAddr}),\n * or `undefined` when the address is not available.\n */\nexport type Addr = NetAddr | UnixAddr | undefined\n\n/**\n * Metadata about the client connection for an incoming request.\n *\n * @typeParam A - The address type, defaults to {@link Addr}\n *\n * @example\n * ```typescript\n * const info: ConnectionInfo<NetAddr> = {\n * remoteAddr: { hostname: '192.168.1.1', port: 54321, transport: 'tcp' },\n * completed: new Promise((resolve) => socket.on('close', resolve))\n * }\n * ```\n */\nexport type ConnectionInfo<A extends Addr = Addr> = {\n /** The remote address of the client, if available. */\n remoteAddr: A\n /** Promise that resolves when the connection is fully closed. */\n completed: Promise<void>\n}\n\n/**\n * Function signature for handling HTTP requests in the XRPC router.\n *\n * This is the standard fetch-style handler that processes incoming requests\n * and returns responses. It is used both internally by the router and can\n * be used to integrate with other HTTP frameworks.\n *\n * @param request - The incoming HTTP request\n * @param connection - Optional connection metadata including remote address\n * @returns A promise resolving to the HTTP response\n *\n * @example\n * ```typescript\n * const handler: FetchHandler = async (request, connection) => {\n * console.log('Request from:', connection?.remoteAddr)\n * return new Response('Hello, World!')\n * }\n * ```\n */\nexport type FetchHandler = (\n request: Request,\n connection?: ConnectionInfo,\n) => Promise<Response>\n\n/**\n * Context object passed to XRPC method handlers.\n *\n * Contains all the information needed to process a request, including\n * parsed parameters, authentication credentials, and the raw request object.\n *\n * @typeParam Method - The Lexicon method type (Query, Procedure, or Subscription)\n * @typeParam Credentials - The type of authentication credentials, determined by the auth handler\n *\n * @example\n * ```typescript\n * const handler: LexRouterMethodHandler<MyMethod, UserCredentials> = async (ctx) => {\n * const { credentials, params, input, signal } = ctx\n * // credentials.userId is available if auth handler returns UserCredentials\n * // params contains validated query parameters\n * // input contains the request body (for procedures)\n * // signal can be used to abort long-running operations\n * return { body: { result: 'success' } }\n * }\n * ```\n */\nexport type LexRouterHandlerContext<Method extends LexMethod, Credentials> = {\n /** Authentication credentials returned by the auth handler. */\n credentials: Credentials\n /** Parsed and validated request input (body for procedures, undefined for queries). */\n input: InferMethodInput<Method, Body>\n /** Parsed and validated URL query parameters. */\n params: InferMethodParams<Method>\n /** The original HTTP request object. */\n request: Request\n /** Abort signal that is triggered when the request is cancelled. */\n signal: AbortSignal\n /** Connection metadata including remote address. */\n connection?: ConnectionInfo\n}\n\ntype AsOptionalPayloadOptions<T> = T extends undefined | void\n ? { encoding?: undefined; body?: undefined }\n : T\n\n/**\n * Return type for XRPC method handlers (queries and procedures).\n *\n * Handlers can return either:\n * - A raw {@link Response} object for full control over the HTTP response\n * - An object with `body`, optional `encoding`, and optional `headers`\n *\n * For JSON methods, the body is automatically serialized. For other encodings,\n * the body must be a valid {@link BodyInit} type.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n *\n * @example\n * ```typescript\n * // Return JSON body (most common)\n * return { body: { users: [...] } }\n *\n * // Return with custom headers\n * return {\n * body: { data: 'value' },\n * headers: { 'Cache-Control': 'max-age=3600' }\n * }\n *\n * // Return raw Response for full control\n * return new Response(binaryData, {\n * headers: { 'Content-Type': 'application/octet-stream' }\n * })\n * ```\n */\nexport type LexRouterHandlerOutput<Method extends Query | Procedure> =\n | Response\n | ({\n headers?: HeadersInit\n } & (InferMethodOutputEncoding<Method> extends 'application/json'\n ? {\n // Allow omitting body when output is JSON\n encoding?: 'application/json'\n body: InferMethodOutputBody<Method>\n }\n : AsOptionalPayloadOptions<InferMethodOutput<Method, BodyInit>>))\n\n/**\n * Handler function for XRPC query and procedure methods.\n *\n * Receives a context object with request details and credentials,\n * and returns either a Response or a structured output object.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const getProfile: LexRouterMethodHandler<GetProfileMethod, UserCredentials> = async (ctx) => {\n * const profile = await db.getProfile(ctx.params.actor)\n * return { body: profile }\n * }\n * ```\n */\nexport type LexRouterMethodHandler<\n Method extends Query | Procedure = Query | Procedure,\n Credentials = unknown,\n> = (\n ctx: LexRouterHandlerContext<Method, Credentials>,\n) => Awaitable<LexRouterHandlerOutput<Method>>\n\n/**\n * Configuration object for registering an XRPC method with authentication.\n *\n * Used when you need to specify both a handler and an auth function.\n *\n * @typeParam Method - The Lexicon method type (Query or Procedure)\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const config: LexRouterMethodConfig<GetProfileMethod, UserCredentials> = {\n * handler: async (ctx) => {\n * return { body: await getProfile(ctx.params.actor) }\n * },\n * auth: async ({ request }) => {\n * return verifyToken(request.headers.get('authorization'))\n * }\n * }\n * ```\n */\nexport type LexRouterMethodConfig<\n Method extends Query | Procedure = Query | Procedure,\n Credentials = unknown,\n> = {\n /** The handler function that processes the request. */\n handler: LexRouterMethodHandler<Method, Credentials>\n /** Authentication function that validates credentials before the handler runs. */\n auth: LexRouterAuth<Credentials, Method>\n}\n\n/**\n * Handler function for XRPC subscription methods (WebSocket streams).\n *\n * Returns an async iterable that yields messages to be sent over the WebSocket.\n * The connection remains open until the iterable completes or an error occurs.\n *\n * @typeParam Method - The Lexicon subscription method type\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const subscribeRepos: LexRouterSubscriptionHandler<SubscribeReposMethod> = async function* (ctx) {\n * const cursor = ctx.params.cursor ?? 0\n * for await (const event of eventStream.since(cursor)) {\n * if (ctx.signal.aborted) break\n * yield { $type: 'com.atproto.sync.subscribeRepos#commit', ...event }\n * }\n * }\n * ```\n */\nexport type LexRouterSubscriptionHandler<\n Method extends Subscription = Subscription,\n Credentials = unknown,\n> = (\n ctx: LexRouterHandlerContext<Method, Credentials>,\n) => AsyncIterable<InferMethodMessage<Method>>\n\n/**\n * Configuration object for registering an XRPC subscription with authentication.\n *\n * Used when you need to specify both a handler and an auth function for subscriptions.\n *\n * @typeParam Method - The Lexicon subscription method type\n * @typeParam Credentials - The type of authentication credentials\n *\n * @example\n * ```typescript\n * const config: LexRouterSubscriptionConfig<SubscribeReposMethod, ServiceCredentials> = {\n * handler: async function* (ctx) {\n * for await (const event of eventStream) {\n * yield event\n * }\n * },\n * auth: async ({ request }) => {\n * return verifyServiceAuth(request)\n * }\n * }\n * ```\n */\nexport type LexRouterSubscriptionConfig<\n Method extends Subscription = Subscription,\n Credentials = unknown,\n> = {\n /** The handler function that yields subscription messages. */\n handler: LexRouterSubscriptionHandler<Method, Credentials>\n /** Authentication function that validates credentials before the handler runs. */\n auth: LexRouterAuth<Credentials, Method>\n}\n\n/**\n * Context object passed to authentication handlers.\n *\n * Contains the information needed to authenticate a request before\n * the main handler is invoked.\n *\n * @typeParam Method - The Lexicon method type\n *\n * @example\n * ```typescript\n * const authHandler: LexRouterAuth<UserCredentials> = async (ctx) => {\n * const token = ctx.request.headers.get('authorization')\n * if (!token) throw new LexServerAuthError('AuthenticationRequired', 'Missing token')\n * return { userId: await verifyToken(token) }\n * }\n * ```\n */\nexport type LexRouterAuthContext<Method extends LexMethod = LexMethod> = {\n /** The Lexicon method definition being called. */\n method: Method\n /** Parsed and validated URL query parameters. */\n params: InferMethodParams<Method>\n /** The original HTTP request object. */\n request: Request\n /** Connection metadata including remote address. */\n connection?: ConnectionInfo\n}\n\n/**\n * Authentication handler function for XRPC methods.\n *\n * Called before the main handler to validate authentication credentials.\n * Should return the validated credentials or throw an error if authentication fails.\n *\n * @typeParam Credentials - The type of credentials to return on success\n * @typeParam Method - The Lexicon method type\n *\n * @example\n * ```typescript\n * // Simple token-based auth\n * const tokenAuth: LexRouterAuth<{ userId: string }> = async ({ request }) => {\n * const token = request.headers.get('authorization')?.replace('Bearer ', '')\n * if (!token) throw new LexServerAuthError('AuthenticationRequired', 'Token required')\n * const userId = await verifyToken(token)\n * if (!userId) throw new LexServerAuthError('AuthenticationRequired', 'Invalid token')\n * return { userId }\n * }\n *\n * // Using with serviceAuth for AT Protocol service authentication\n * import { serviceAuth } from '@atproto/lex-server'\n * const auth = serviceAuth({ audience: 'did:web:example.com', unique: checkNonce })\n * ```\n */\nexport type LexRouterAuth<\n Credentials = unknown,\n Method extends LexMethod = LexMethod,\n> = (ctx: LexRouterAuthContext<Method>) => Credentials | Promise<Credentials>\n\n/**\n * Context object passed to error handler callbacks.\n *\n * Used for logging and monitoring errors that occur during request handling.\n */\nexport type HandlerErrorContext = {\n request: Request\n method: LexMethod\n error: LexServerError\n}\n\nexport type HandlerErrorHook = (\n ctx: HandlerErrorContext,\n) => void | Promise<void>\n\nexport type SocketErrorContext = {\n request: Request\n method: Subscription\n error: unknown\n}\n\nexport type SocketErrorHook = (ctx: SocketErrorContext) => void | Promise<void>\n\n/**\n * Function that upgrades an HTTP request to a WebSocket connection.\n *\n * This is platform-specific: Deno provides this natively, while Node.js\n * requires the `upgradeWebSocket` function from this package.\n *\n * @param request - The HTTP request to upgrade\n * @returns An object containing the WebSocket and the upgrade response\n *\n * @example\n * ```typescript\n * // In Node.js, use the provided upgradeWebSocket function\n * import { upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n * ```\n */\nexport type UpgradeWebSocket = (request: Request) => {\n /** The WebSocket instance for bidirectional communication. */\n socket: WebSocket\n /** The HTTP response to return (101 Switching Protocols). */\n response: Response\n}\n\nexport type HealthCheckHandler = (\n request: Request,\n) => Awaitable<{ [x: string]: unknown; status: 'ok' }>\n\n/**\n * Configuration options for the {@link LexRouter}.\n *\n * @example\n * ```typescript\n * const options: LexRouterOptions = {\n * upgradeWebSocket,\n * onHandlerError: async ({ error, request, method }) => {\n * console.error(`Error in ${method.nsid}:`, error)\n * await reportToSentry(error)\n * },\n * highWaterMark: 64 * 1024, // 64KB\n * lowWaterMark: 16 * 1024 // 16KB\n * }\n * ```\n */\nexport type LexRouterOptions = {\n /**\n * Function to upgrade HTTP requests to WebSocket connections. Required for\n * subscription methods. Defaults to Deno's built-in\n * {@link globalThis.upgradeWebSocket} if available. For NodeJS, use the\n * homonymous export from `@atproto/lex-server/nodejs`.\n */\n upgradeWebSocket?: UpgradeWebSocket\n /**\n * Callback invoked when an error occurs during request handling. Useful for\n * logging and error reporting. Not called for client-induced errors (e.g.,\n * request abortion).\n */\n onHandlerError?: HandlerErrorHook\n /**\n * Optional hook for handling errors during generation of WebSocket messages.\n */\n onSocketError?: SocketErrorHook\n /**\n * Optional health check handler. If provided, this function will be called\n * for requests to the /xrpc/_health endpoint, allowing for custom health\n * check logic and responses.\n *\n * If not provided, the server will respond to /xrpc/_health requests with a\n * default JSON response of `{ status: 'ok' }`.\n */\n healthCheck?: HealthCheckHandler\n /**\n * Optional fallback handler for requests that are not /xrpc/ paths. Can be\n * used to serve static files or other routes. If not provided, non-/xrpc/\n * requests will return 404 responses.\n */\n fallback?: FetchHandler\n /**\n * High water mark for WebSocket backpressure (in bytes). When buffered data\n * exceeds this, the handler will wait before sending more.\n */\n highWaterMark?: number\n /**\n * Low water mark for WebSocket backpressure (in bytes). The handler resumes\n * sending when buffered data drops below this.\n */\n lowWaterMark?: number\n}\n\n/**\n * XRPC router for handling AT Protocol Lexicon methods.\n *\n * The router handles HTTP routing, parameter parsing, input validation,\n * authentication, and response serialization for XRPC methods. It supports\n * queries (GET), procedures (POST), and subscriptions (WebSocket).\n *\n * @example Setting up a basic XRPC server\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n * import { getProfile, createPost, subscribeRepos } from './lexicons.js'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Register a query handler (GET request)\n * router.add(getProfile, async (ctx) => {\n * const profile = await db.getProfile(ctx.params.actor)\n * return { body: profile }\n * })\n *\n * // Register a procedure handler with authentication (POST request)\n * router.add(createPost, {\n * handler: async (ctx) => {\n * const post = await db.createPost(ctx.credentials.did, ctx.input.body)\n * return { body: { uri: post.uri, cid: post.cid } }\n * },\n * auth: async ({ request }) => {\n * return verifyAccessToken(request)\n * }\n * })\n *\n * // Register a subscription handler (WebSocket)\n * router.add(subscribeRepos, async function* (ctx) {\n * for await (const event of eventStream.since(ctx.params.cursor)) {\n * if (ctx.signal.aborted) break\n * yield event\n * }\n * })\n *\n * // Start the server\n * const server = await serve(router, { port: 3000 })\n * console.log('XRPC server listening on port 3000')\n * ```\n *\n * @example Using with service authentication\n * ```typescript\n * import { LexRouter, serviceAuth } from '@atproto/lex-server'\n *\n * const router = new LexRouter()\n *\n * const auth = serviceAuth({\n * audience: 'did:web:api.example.com',\n * unique: async (nonce) => {\n * // Check and record nonce uniqueness\n * return await nonceStore.checkAndAdd(nonce)\n * }\n * })\n *\n * router.add(protectedMethod, {\n * handler: async (ctx) => {\n * // ctx.credentials contains { did, didDocument, jwt }\n * return { body: { callerDid: ctx.credentials.did } }\n * },\n * auth\n * })\n * ```\n */\nexport class LexRouter {\n /** Map of NSID strings to their fetch handlers. */\n readonly handlers: Map<NsidString, FetchHandler> = new Map()\n\n /**\n * Creates a new XRPC router.\n *\n * @param options - Router configuration options\n */\n constructor(readonly options: LexRouterOptions = {}) {}\n\n /**\n * Registers a subscription handler without authentication.\n *\n * @param ns - The Lexicon namespace definition for the subscription\n * @param handler - Async generator function that yields subscription messages\n * @returns This router instance for chaining\n */\n add<M extends Subscription>(\n ns: Main<M>,\n handler: LexRouterSubscriptionHandler<M, void>,\n ): this\n /**\n * Registers a subscription handler with authentication.\n *\n * @param ns - The Lexicon namespace definition for the subscription\n * @param config - Configuration object with handler and auth function\n * @returns This router instance for chaining\n */\n add<M extends Subscription, Credentials>(\n ns: Main<M>,\n config: LexRouterSubscriptionConfig<M, Credentials>,\n ): this\n /**\n * Registers a query or procedure handler without authentication.\n *\n * @param ns - The Lexicon namespace definition for the method\n * @param handler - Handler function that processes requests\n * @returns This router instance for chaining\n */\n add<M extends Query | Procedure>(\n ns: Main<M>,\n handler: LexRouterMethodHandler<M, void>,\n ): this\n /**\n * Registers a query or procedure handler with authentication.\n *\n * @param ns - The Lexicon namespace definition for the method\n * @param config - Configuration object with handler and auth function\n * @returns This router instance for chaining\n */\n add<M extends Query | Procedure, Credentials>(\n ns: Main<M>,\n config: LexRouterMethodConfig<M, Credentials>,\n ): this\n /**\n * Registers a Lexicon method handler.\n *\n * This is the unified overload that accepts any method type with optional authentication.\n *\n * @param ns - The Lexicon namespace definition\n * @param config - Handler function or configuration object\n * @returns This router instance for chaining\n *\n * @throws {TypeError} If a method with the same NSID is already registered\n *\n * @example\n * ```typescript\n * // Register without auth (credentials will be void)\n * router.add(myQuery, async (ctx) => {\n * return { body: { data: 'value' } }\n * })\n *\n * // Register with auth\n * router.add(myProcedure, {\n * handler: async (ctx) => {\n * console.log('Caller:', ctx.credentials.userId)\n * return { body: { success: true } }\n * },\n * auth: async ({ request }) => ({ userId: await verifyToken(request) })\n * })\n * ```\n */\n add<M extends LexMethod, Credentials = unknown>(\n ns: Main<M>,\n config: M extends Subscription\n ?\n | LexRouterSubscriptionHandler<M, Credentials>\n | LexRouterSubscriptionConfig<M, Credentials>\n : M extends Query | Procedure\n ?\n | LexRouterMethodHandler<M, Credentials>\n | LexRouterMethodConfig<M, Credentials>\n : never,\n ): this\n add<M extends LexMethod>(\n ns: Main<M>,\n config:\n | LexRouterSubscriptionHandler<any, any>\n | LexRouterSubscriptionConfig<any, any>\n | LexRouterMethodHandler<any, any>\n | LexRouterMethodConfig<any, any>,\n ) {\n const method = getMain(ns)\n const nsid = normalizeNsid(method.nsid)\n\n if (this.handlers.has(nsid)) {\n throw new TypeError(`Method ${method.nsid} already registered`)\n }\n\n const methodConfig =\n typeof config === 'function'\n ? { handler: config, auth: undefined }\n : config\n\n const handler: FetchHandler =\n method.type === 'subscription'\n ? this.buildSubscriptionHandler(\n method,\n methodConfig.handler as LexRouterSubscriptionHandler<any, any>,\n methodConfig.auth,\n )\n : this.buildMethodHandler(\n method,\n methodConfig.handler as LexRouterMethodHandler<any, any>,\n methodConfig.auth,\n )\n\n this.handlers.set(nsid, handler)\n\n return this\n }\n\n private buildMethodHandler<Method extends Query | Procedure, Credentials>(\n method: Method,\n methodHandler: LexRouterMethodHandler<Method, Credentials>,\n auth?: LexRouterAuth<Credentials, Method>,\n ): FetchHandler {\n const getInput = (\n method.type === 'procedure'\n ? getProcedureInput.bind(method)\n : getQueryInput.bind(method)\n ) as (request: Request) => Promise<InferMethodInput<Method, Body>>\n\n return async (request, connection) => {\n // @NOTE CORS requests should be handled by a middleware before reaching\n // this point.\n if (\n (method.type === 'procedure' && request.method !== 'POST') ||\n (method.type === 'query' &&\n request.method !== 'GET' &&\n request.method !== 'HEAD')\n ) {\n return invalidRequestResponse('Method not allowed', 405)\n }\n\n try {\n const url = new URL(request.url)\n const params = method.parameters.fromURLSearchParams(\n url.searchParams,\n ) as InferMethodParams<Method>\n\n const credentials = auth\n ? await auth({ method, params, request, connection })\n : (undefined as Credentials)\n\n const input = await getInput(request)\n\n const output = await methodHandler({\n credentials,\n params,\n input,\n request,\n connection,\n signal: request.signal,\n })\n\n if (output instanceof Response) {\n return output\n }\n\n // @TODO add validation of output based on method.output.schema?\n\n if (output.body === undefined && output.encoding === undefined) {\n return new Response(null, { status: 200, headers: output.headers })\n }\n\n if (method.output?.encoding === 'application/json') {\n return Response.json(lexToJson(output.body as LexValue), {\n status: 200,\n headers: output.headers,\n })\n }\n\n const headers = new Headers(output.headers)\n headers.set('content-type', output.encoding!)\n return new Response(output.body as BodyInit | null | undefined, {\n status: 200,\n headers,\n })\n } catch (error) {\n return this.handlerError(request, method, error)\n }\n }\n }\n\n private buildSubscriptionHandler<Method extends Subscription, Credentials>(\n method: Method,\n methodHandler: LexRouterSubscriptionHandler<Method, Credentials>,\n auth?: LexRouterAuth<Credentials, Method>,\n ): FetchHandler {\n const {\n onSocketError,\n upgradeWebSocket = (globalThis as any).Deno?.upgradeWebSocket as\n | UpgradeWebSocket\n | undefined,\n } = this.options\n if (!upgradeWebSocket) {\n throw new TypeError(\n 'WebSocket upgrade not supported in this environment. Please provide an upgradeWebSocket option when creating the LexRouter.',\n )\n }\n\n return async (request, connection) => {\n if (request.method !== 'GET') {\n return invalidRequestResponse('Method not allowed', 405)\n }\n\n if (\n request.headers.get('connection')?.toLowerCase() !== 'upgrade' ||\n request.headers.get('upgrade')?.toLowerCase() !== 'websocket'\n ) {\n return invalidRequestResponse(\n 'XRPC subscriptions are only available over WebSocket',\n 426,\n {\n Connection: 'Upgrade',\n Upgrade: 'websocket',\n },\n )\n }\n\n if (request.signal.aborted) {\n return invalidRequestResponse('Request aborted', 499)\n }\n\n try {\n const { response, socket } = upgradeWebSocket(request)\n\n // @NOTE We are using a distinct signal than request.signal because that\n // signal may get aborted before the WebSocket is closed (this is the\n // case with Deno).\n const abortController = new AbortController()\n const { signal } = abortController\n const abort = () => abortController.abort()\n\n const onOpen = async () => {\n try {\n const url = new URL(request.url)\n const params = method.parameters.fromURLSearchParams(\n url.searchParams,\n ) as InferMethodParams<Method>\n\n const credentials: Credentials = auth\n ? await auth({ method, params, request, connection })\n : (undefined as Credentials)\n\n signal.throwIfAborted()\n\n const iterable = methodHandler({\n credentials,\n params,\n input: undefined as InferMethodInput<Method, Body>,\n request,\n connection,\n signal,\n })\n\n const iterator = iterable[Symbol.asyncIterator]()\n\n if (iterator.return) {\n signal.addEventListener(\n 'abort',\n () => {\n // @NOTE if iterator.return() throws, and no onSocketError is\n // provided, or if onSocketError itself throws, the error will\n // be unhandled, causing the process to crash. This is\n // intentional, as it surfaces critical errors that occur\n // during cleanup of the subscription.\n\n void new Promise((resolve) => {\n // Wrapping in new Promise to catch any potential sync errors thrown by iterator.return()\n resolve(iterator.return!())\n }).catch(\n onSocketError\n ? (error) => onSocketError({ request, method, error })\n : null,\n )\n },\n {\n once: true,\n },\n )\n }\n\n while (!signal.aborted && socket.readyState === 1) {\n const result = await iterator.next()\n if (result.done) break\n\n // @TODO add validation of output based on method.output.schema?\n\n const data = encodeMessageFrame(method, result.value)\n\n socket.send(data)\n\n // Apply backpressure by waiting for the buffered data to drain\n // before generating the next message\n await drainWebsocket(socket, signal, this.options)\n }\n\n if (socket.readyState === 1) {\n socket.close(1000)\n }\n } catch (error) {\n // If the socket is still open, send an error frame before closing\n if (socket.readyState === 1) {\n const isLexError = error instanceof LexError\n\n // https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1\n const code =\n isLexError && method.errors?.includes(error.error)\n ? 1008 // Policy Violation for known LexErrors\n : 1011 // Internal Error for unexpected errors\n\n if (isLexError) {\n socket.send(encodeErrorFrame(error.toJSON()))\n socket.close(code, error.error)\n } else {\n const error = 'InternalServerError'\n const message = 'An internal error occurred'\n socket.send(encodeErrorFrame({ error, message }))\n socket.close(code, error)\n }\n }\n\n if (onSocketError && !isAbortReason(signal, error)) {\n await onSocketError({ request, method, error })\n }\n } finally {\n abortController.abort()\n }\n }\n\n socket.addEventListener('error', abort)\n socket.addEventListener('close', abort)\n socket.addEventListener('open', onOpen)\n socket.addEventListener('message', onMessage)\n\n return response\n } catch (error) {\n return this.handlerError(request, method, error)\n }\n }\n }\n\n private async handlerError(\n request: Request,\n method: LexMethod,\n cause: unknown,\n ) {\n // Only report unexpected processing errors\n if (isAbortReason(request.signal, cause)) {\n return Response.json({ error: 'RequestAborted' }, { status: 499 })\n }\n\n const error = LexServerError.from(cause)\n\n const { onHandlerError } = this.options\n if (onHandlerError) await onHandlerError({ error, request, method })\n\n return error.toResponse()\n }\n\n /**\n * The main fetch handler for processing XRPC requests.\n *\n * Routes incoming requests to the appropriate method handler based on the\n * NSID in the URL path. Returns appropriate error responses for invalid\n * paths or unimplemented methods.\n *\n * This handler can be used directly with HTTP servers that support the\n * fetch API pattern, or converted to a Node.js request listener using\n * `toRequestListener()`.\n *\n * @param request - The incoming HTTP request\n * @param connection - Optional connection metadata\n * @returns A promise resolving to the HTTP response\n *\n * @example\n * ```typescript\n * // Use with Deno\n * Deno.serve(router.fetch)\n *\n * // Use with Bun\n * Bun.serve({ fetch: router.fetch })\n *\n * // Use with Node.js\n * import { toRequestListener } from '@atproto/lex-server/nodejs'\n * const listener = toRequestListener(router.fetch)\n * http.createServer(listener).listen(3000)\n * ```\n */\n fetch: FetchHandler = async (\n request: Request,\n connection?: ConnectionInfo,\n ): Promise<Response> => {\n const { pathname } = new URL(request.url)\n const atprotoProxy = request.headers.get('atproto-proxy')\n\n if (!pathname.startsWith(XRPC_PATH_PREFIX)) {\n // Handle non XRPC paths\n const { fallback } = this.options\n if (fallback) return fallback(request, connection)\n return new Response('Not Found', { status: 404 })\n }\n\n if (pathname === XRPC_HEALTH_CHECK_PATH) {\n if (request.method !== 'GET') {\n return invalidRequestResponse('Method not allowed', 405)\n }\n if (atprotoProxy != null) {\n return invalidRequestResponse(\n 'atproto-proxy header is not allowed on health check endpoint',\n )\n }\n\n const { healthCheck } = this.options\n const data = healthCheck ? await healthCheck(request) : { status: 'ok' }\n\n return Response.json(data)\n }\n\n const subPath = pathname.slice(XRPC_PATH_PREFIX.length)\n\n if (!isNsidString(subPath)) {\n return invalidRequestResponse('Invalid NSID in URL path')\n }\n\n const nsid = normalizeNsid(subPath)\n if (atprotoProxy == null) {\n const handler = this.handlers.get(nsid)\n if (handler) return handler(request, connection)\n } else {\n // Handle service proxying logic.\n\n const proxyInfo = parseAtprotoProxyHeader(atprotoProxy)\n if (!proxyInfo) {\n return invalidRequestResponse(\n `Invalid atproto-proxy header value: ${atprotoProxy}`,\n )\n }\n\n // @TODO actually implement service proxying logic here. The reason it was\n // not done already is because we want to perform all the heavy lifting\n // here, while still allowing the possibility to override the endpoint\n // resolution, etc.\n\n // @NOTE see ./service-auth.ts for potential common code (did resolver, etc.)\n }\n\n return Response.json(\n {\n error: 'MethodNotImplemented',\n message: `XRPC method \"${nsid}\" not implemented on this server`,\n },\n { status: 501 },\n )\n }\n}\n\nasync function getProcedureInput<M extends Procedure>(\n this: M,\n request: Request,\n): Promise<InferMethodInput<M, Body>> {\n const encodingRaw = request.headers\n .get('content-type')\n ?.split(';')[0]\n .trim()\n .toLowerCase()\n\n const encoding =\n encodingRaw ||\n // If the caller did not provide a content-type, but the method\n // expects an input, assume binary\n (request.body != null && this.input.encoding != null\n ? 'application/octet-stream'\n : undefined)\n\n if (!this.input.matchesEncoding(encoding)) {\n throw new LexServerError(400, {\n error: 'InvalidRequest',\n message: `Invalid content-type: ${encoding}`,\n })\n }\n\n if (this.input.encoding === 'application/json') {\n // @TODO limit size?\n const data = lexParse(await request.text())\n const body = this.input.schema ? this.input.schema.parse(data) : data\n return { encoding, body } as InferMethodInput<M, Body>\n } else if (this.input.encoding) {\n const body: Body = request\n return { encoding, body } as InferMethodInput<M, Body>\n } else {\n return undefined as InferMethodInput<M, Body>\n }\n}\n\nasync function getQueryInput<M extends Query>(\n this: M,\n request: Request,\n): Promise<InferMethodInput<M, Body>> {\n if (\n request.body ||\n request.headers.has('content-type') ||\n request.headers.has('content-length')\n ) {\n throw new LexServerError(400, {\n error: 'InvalidRequest',\n message: 'GET requests must not have a body',\n })\n }\n\n return undefined as InferMethodInput<M, Body>\n}\n\nfunction onMessage(this: WebSocket, _event: unknown) {\n const error = 'InvalidRequest'\n const message = 'XRPC subscriptions do not accept messages'\n this.send(encodeErrorFrame({ error, message }))\n // 1003 indicates that an endpoint is terminating the connection\n // because it has received a type of data it cannot accept (e.g., an\n // endpoint that understands only text data MAY send this if it\n // receives a binary message).\n this.close(1003, error)\n}\n\n// Pre-encoded frame header for error frames\nconst ERROR_FRAME_HEADER = /*#__PURE__*/ encode({ op: -1 })\n\nfunction encodeErrorFrame(errorData: LexErrorData): Uint8Array<ArrayBuffer> {\n return ui8Concat([ERROR_FRAME_HEADER, encode(errorData)])\n}\n\n// Pre-encoded frame header for message frames with unknown type\nconst UNKNOWN_MESSAGE_FRAME_HEADER = /*#__PURE__*/ encode({ op: 1 })\n\nfunction encodeMessageFrame(\n method: Subscription,\n value: LexValue,\n): Uint8Array<ArrayBuffer> {\n if (isPlainObject(value) && typeof value.$type === 'string') {\n const { $type, ...rest } = value\n return ui8Concat([\n encode({\n op: 1,\n t:\n // If $type starts with `nsid#`, strip the NSID prefix\n $type.charCodeAt(0) !== 0x23 && // '#'\n $type.charCodeAt(method.nsid.length) === 0x23 && // '#'\n $type.startsWith(method.nsid)\n ? $type.slice(method.nsid.length)\n : $type,\n }),\n encode(rest),\n ])\n }\n\n return ui8Concat([UNKNOWN_MESSAGE_FRAME_HEADER, encode(value)])\n}\n\nfunction isAbortReason(signal: AbortSignal, error: unknown): boolean {\n return (\n signal.aborted &&\n signal.reason != null &&\n error instanceof Error &&\n (error === signal.reason || error.cause === signal.reason)\n )\n}\n\nexport type ServiceProxyInfo = {\n did: DidString\n serviceId: string\n}\n\nfunction parseAtprotoProxyHeader(value: string): ServiceProxyInfo | null {\n // /!\\ Hot path\n\n // (fast) sanity check to avoid unnecessary parsing for non-DID values\n if (!value.startsWith('did:')) return null\n\n // The format is expected to be `did:example:service#serviceId`\n const hashIndex = value.indexOf('#')\n if (hashIndex === -1) return null\n\n const fragmentIndex = hashIndex + 1\n // Basic validation if the fragment\n if (fragmentIndex === value.length) return null\n if (value.includes('#', fragmentIndex)) return null\n if (value.includes(' ', fragmentIndex)) return null\n\n const did = value.slice(0, hashIndex)\n if (!isDidString(did)) return null\n\n const serviceId = value.slice(fragmentIndex)\n return { did, serviceId }\n}\n\nfunction normalizeNsid(nsid: NsidString): NsidString {\n const lastDotIdx = nsid.lastIndexOf('.')\n\n // The domain name part of the NSID is case-insensitive, but the last part is\n // case-sensitive. Normalize the domain part to lowercase.\n if (lastDotIdx !== -1 && hasUpperCase(nsid, 0, lastDotIdx)) {\n return `${nsid.slice(0, lastDotIdx).toLowerCase()}.${nsid.slice(lastDotIdx + 1)}` as NsidString\n }\n\n return nsid\n}\n\nfunction hasUpperCase(str: string, start = 0, end = str.length): boolean {\n for (let i = start; i < end; i++) {\n const code = str.charCodeAt(i)\n if (code >= 0x41 && code <= 0x5a) {\n return true\n }\n }\n return false\n}\n\nfunction invalidRequestResponse(\n message: string,\n status = 400,\n headers?: HeadersInit,\n): Response {\n return Response.json(\n {\n error: 'InvalidRequest',\n message,\n },\n { status, headers },\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"drain-websocket.js","sourceRoot":"","sources":["../../src/lib/drain-websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,MAAmB,EACnB,EACE,aAAa,GAAG,OAAO,EAAE,SAAS;AAClC,YAAY,GAAG,MAAM,EAAE,QAAQ;KAI7B,EAAE;IAEN,IAAI,MAAM,CAAC,cAAc,GAAG,aAAa,EAAE,CAAC;QAC1C,wEAAwE;QACxE,4EAA4E;QAC5E,sEAAsE;QACtE,aAAa;QACb,OACE,MAAM,CAAC,UAAU,KAAK,CAAC;YACvB,MAAM,CAAC,cAAc,KAAK,CAAC;YAC3B,MAAM,CAAC,cAAc,GAAG,YAAY,EACpC,CAAC;YACD,MAAM,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { abortableSleep } from './sleep.js'\n\n/**\n * Performs polling based backpressure management for a WebSocket connection. If\n * the amount of buffered data exceeds the specified high water mark, this\n * function will wait until the buffered amount drops below the low water mark\n * before resolving. This is useful for preventing memory issues when sending\n * large amounts of data over a WebSocket connection.\n */\nexport async function drainWebsocket(\n socket: WebSocket,\n signal: AbortSignal,\n {\n highWaterMark = 250_000, // 250 KB\n lowWaterMark = 50_000, // 50 KB\n }: {\n highWaterMark?: number\n lowWaterMark?: number\n } = {},\n): Promise<void> {\n if (socket.bufferedAmount > highWaterMark) {\n // Once we exceed the high water mark, we wait until the buffered amount\n // drops below the low water mark before allowing more data to be sent. This\n // creates a hysteresis effect that prevents rapid toggling around the\n // threshold.\n while (\n socket.readyState === 1 &&\n socket.bufferedAmount !== 0 &&\n socket.bufferedAmount > lowWaterMark\n ) {\n await abortableSleep(10, signal)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"drain-websocket.js","sourceRoot":"","sources":["../../src/lib/drain-websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,MAAmB,EACnB,EACE,aAAa,GAAG,OAAO,EAAE,SAAS;AAClC,YAAY,GAAG,MAAM,EAAE,QAAQ;EAChC,GAGG,EAAE;IAEN,IAAI,MAAM,CAAC,cAAc,GAAG,aAAa,EAAE,CAAC;QAC1C,wEAAwE;QACxE,4EAA4E;QAC5E,sEAAsE;QACtE,aAAa;QACb,OACE,MAAM,CAAC,UAAU,KAAK,CAAC;YACvB,MAAM,CAAC,cAAc,KAAK,CAAC;YAC3B,MAAM,CAAC,cAAc,GAAG,YAAY,EACpC,CAAC;YACD,MAAM,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { abortableSleep } from './sleep.js'\n\n/**\n * Performs polling based backpressure management for a WebSocket connection. If\n * the amount of buffered data exceeds the specified high water mark, this\n * function will wait until the buffered amount drops below the low water mark\n * before resolving. This is useful for preventing memory issues when sending\n * large amounts of data over a WebSocket connection.\n */\nexport async function drainWebsocket(\n socket: WebSocket,\n signal: AbortSignal,\n {\n highWaterMark = 250_000, // 250 KB\n lowWaterMark = 50_000, // 50 KB\n }: {\n highWaterMark?: number\n lowWaterMark?: number\n } = {},\n): Promise<void> {\n if (socket.bufferedAmount > highWaterMark) {\n // Once we exceed the high water mark, we wait until the buffered amount\n // drops below the low water mark before allowing more data to be sent. This\n // creates a hysteresis effect that prevents rapid toggling around the\n // threshold.\n while (\n socket.readyState === 1 &&\n socket.bufferedAmount !== 0 &&\n socket.bufferedAmount > lowWaterMark\n ) {\n await abortableSleep(10, signal)\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"nodejs.d.ts","sourceRoot":"","sources":["../src/nodejs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nodejs.d.ts","sourceRoot":"","sources":["../src/nodejs.ts"],"names":[],"mappings":"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"}
package/dist/nodejs.js CHANGED
@@ -2,10 +2,8 @@ import { once } from 'node:events';
2
2
  import { createServer as createHttpServer, } from 'node:http';
3
3
  import { Readable } from 'node:stream';
4
4
  import { pipeline } from 'node:stream/promises';
5
- // eslint-disable-next-line import/default, import/no-named-as-default-member
5
+ // eslint-disable-next-line import/default
6
6
  import httpTerminator from 'http-terminator';
7
- // eslint-disable-next-line import/no-named-as-default-member
8
- const { createHttpTerminator } = httpTerminator;
9
7
  import { WebSocket as WebSocketPonyfill, WebSocketServer } from 'ws';
10
8
  // @ts-expect-error
11
9
  Symbol.asyncDispose ??= Symbol.for('Symbol.asyncDispose');
@@ -350,7 +348,7 @@ export function createServer(handler, options = {}) {
350
348
  const fetchHandler = typeof handler === 'function' ? handler : handler.fetch.bind(handler);
351
349
  const listener = toRequestListener(fetchHandler);
352
350
  const server = createHttpServer(options, listener);
353
- const terminator = createHttpTerminator({
351
+ const terminator = httpTerminator.createHttpTerminator({
354
352
  server: server,
355
353
  gracefulTerminationTimeout: options?.gracefulTerminationTimeout,
356
354
  });
@@ -1 +1 @@
1
- {"version":3,"file":"nodejs.js","sourceRoot":"","sources":["../src/nodejs.ts"],"names":[],"mappings":"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","sourcesContent":["import { once } from 'node:events'\nimport {\n IncomingHttpHeaders,\n IncomingMessage,\n RequestListener,\n Server as HttpServer,\n ServerOptions,\n ServerResponse,\n createServer as createHttpServer,\n} from 'node:http'\nimport { ListenOptions } from 'node:net'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport type { ReadableStream as NodeReadableStream } from 'node:stream/web'\n// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport httpTerminator from 'http-terminator'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { createHttpTerminator } = httpTerminator\nimport { WebSocket as WebSocketPonyfill, WebSocketServer } from 'ws'\nimport type { FetchHandler } from './lex-router.js'\n\n// @ts-expect-error\nSymbol.asyncDispose ??= Symbol.for('Symbol.asyncDispose')\n\nconst kResponseWs = Symbol.for('@atproto/lex-server:WebSocket')\n\nfunction isUpgradeRequest(request: Request, upgrade: string): boolean {\n return (\n request.method === 'GET' &&\n request.headers.get('connection')?.toLowerCase() === 'upgrade' &&\n request.headers.get('upgrade')?.toLowerCase() === upgrade\n )\n}\n\n/**\n * Upgrades an HTTP request to a WebSocket connection for Node.js.\n *\n * This function must be passed to the {@link LexRouter} constructor to enable\n * subscription (WebSocket) support on Node.js. It creates a WebSocket instance\n * and a placeholder response that signals the need for protocol upgrade.\n *\n * The actual upgrade is handled internally when the response is sent through\n * {@link sendResponse}.\n *\n * @param request - The incoming HTTP request to upgrade\n * @returns An object containing the WebSocket and upgrade response\n * @throws {TypeError} If the request is not a valid WebSocket upgrade request\n *\n * @example\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * // Pass to router for subscription support\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Now you can add subscription handlers\n * router.add(subscribeRepos, async function* (ctx) {\n * for await (const event of eventStream) {\n * yield event\n * }\n * })\n * ```\n */\nexport function upgradeWebSocket(request: Request): {\n response: Response\n socket: WebSocket\n} {\n if (!isUpgradeRequest(request, 'websocket')) {\n throw new TypeError('upgradeWebSocket() expects a WebSocket upgrade')\n }\n\n // Placeholder response for WebSocket upgrade. The actual handling will happen\n // through the handleWebSocketUpgrade function. Headers set on the response\n // will be applied during the upgrade.\n const response = new Response(null, { status: 200 })\n\n // The Response constructor does not allow setting status 101, so we\n // define it directly. The purpose of this response is just to signal\n // that an upgrade is needed, and to carry any headers.\n Object.defineProperty(response, 'status', {\n value: 101,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n // @ts-expect-error\n const socket: WebSocket = new WebSocketPonyfill(null, undefined, {\n autoPong: true,\n })\n\n // Attach the WebSocket to the response for later retrieval\n Object.defineProperty(response, kResponseWs, {\n value: socket,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n return { response, socket }\n}\n\nconst kUpgradeEvent = Symbol.for('@atproto/lex-server:upgrade')\n\nfunction handleWebSocketUpgrade(\n req: IncomingMessage,\n response: Response,\n): void {\n const ws = (response as { [kResponseWs]?: WebSocketPonyfill })[kResponseWs]\n if (!ws) throw new TypeError('Response not created by upgradeWebSocket()')\n\n // Create a one time use WebSocketServer to handle the upgrade\n const wss = new WebSocketServer({\n autoPong: true,\n noServer: true,\n clientTracking: false,\n perMessageDeflate: true,\n // @ts-expect-error\n WebSocket: function () {\n // Return the websocket that was created earlier instead of a new instance\n return ws\n },\n })\n\n // Apply headers that might have been set on the response object during\n // handling. This will be called during wss.handleUpgrade().\n wss.on('headers', (headers) => {\n for (const [name, value] of response.headers) {\n headers.push(`${name}: ${value}`)\n }\n })\n\n wss.handleUpgrade(req, req.socket, Buffer.alloc(0), (_socket) => {\n // @TODO find a way to properly \"close\" the _socket when the server is\n // shutting down (might require replacing http-terminator with a local\n // implementation)\n\n req.emit(kUpgradeEvent, ws)\n })\n}\n\n/**\n * Sends a fetch API Response through a Node.js ServerResponse.\n *\n * Handles both regular HTTP responses and WebSocket upgrades. For WebSocket\n * upgrades (status 101), delegates to the WebSocket upgrade handler.\n *\n * This function is used internally by {@link toRequestListener} and\n * {@link createServer}, but can be used directly for custom integrations.\n *\n * @param req - The Node.js IncomingMessage\n * @param res - The Node.js ServerResponse to write to\n * @param response - The fetch API Response to send\n * @throws {TypeError} If headers have already been sent\n *\n * @example\n * ```typescript\n * import http from 'node:http'\n * import { sendResponse } from '@atproto/lex-server/nodejs'\n *\n * const server = http.createServer(async (req, res) => {\n * const response = new Response('Hello, World!', {\n * headers: { 'Content-Type': 'text/plain' }\n * })\n * await sendResponse(req, res, response)\n * })\n * ```\n */\nexport async function sendResponse(\n req: IncomingMessage,\n res: ServerResponse,\n response: Response,\n): Promise<void> {\n // Invalid usage\n if (res.headersSent) {\n throw new TypeError('Response has already been sent')\n }\n\n if (response.status === 101) {\n return handleWebSocketUpgrade(req, response)\n }\n\n res.statusCode = response.status\n res.statusMessage = response.statusText\n\n for (const [key, value] of response.headers) {\n res.setHeader(key, value)\n }\n\n if (response.body != null && req.method !== 'HEAD') {\n const stream = Readable.fromWeb(response.body as NodeReadableStream)\n await pipeline(stream, res)\n } else {\n await response.body?.cancel()\n res.end()\n }\n}\n\nfunction toRequest(req: IncomingMessage): Request {\n const host = req.headers.host ?? req.socket.localAddress ?? 'localhost'\n const isEncrypted = (req.socket as any).encrypted === true\n const protocol = isEncrypted ? 'https' : 'http'\n const url = new URL(req.url ?? '/', `${protocol}://${host}`)\n const headers = toHeaders(req.headers)\n const body = toBody(req)\n const signal = requestSignal(req)\n\n return new Request(url, {\n signal,\n method: req.method,\n headers,\n body,\n referrer: headers.get('referrer') ?? headers.get('referer') ?? undefined,\n redirect: 'manual',\n // @ts-expect-error\n duplex: body ? 'half' : undefined,\n })\n}\n\nfunction requestSignal(req: IncomingMessage): AbortSignal {\n if (req.destroyed) return AbortSignal.abort()\n\n const abortController = new AbortController()\n\n const abort = (err?: Error | WebSocket) => {\n abortController.abort(err instanceof Error ? err : undefined)\n\n req.off('close', abort)\n req.off('error', abort)\n req.off('end', abort)\n req.off(kUpgradeEvent, abort)\n }\n\n req.on('close', abort)\n req.on('error', abort)\n req.on('end', abort)\n req.on(kUpgradeEvent, abort)\n\n return abortController.signal\n}\n\nfunction requestCompletion(req: IncomingMessage): Promise<void> {\n if (req.destroyed) return Promise.resolve()\n\n // Unlike the abort signal, we complete the promise only when the request\n // is fully done, accounting for websocket upgrade.\n return new Promise((resolve) => {\n const cleanup = () => {\n req.off('close', done)\n req.off('error', done)\n req.off('end', done)\n req.off(kUpgradeEvent, onUpgrade)\n }\n\n const onUpgrade = (ws: WebSocket) => {\n cleanup()\n ws.addEventListener('close', () => resolve())\n }\n\n const done = () => {\n resolve()\n cleanup()\n }\n\n req.on('close', done)\n req.on('error', done)\n req.on('end', done)\n req.on(kUpgradeEvent, onUpgrade)\n })\n}\n\nfunction toHeaders(headers: IncomingHttpHeaders): Headers {\n const result = new Headers()\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue\n if (Array.isArray(value)) {\n for (const v of value) result.append(key, v)\n } else {\n result.set(key, value)\n }\n }\n return result\n}\n\nfunction toBody(req: IncomingMessage): null | ReadableStream {\n if (\n req.method === 'GET' ||\n req.method === 'HEAD' ||\n req.method === 'OPTIONS'\n ) {\n return null\n }\n\n if (\n req.headers['content-type'] == null &&\n req.headers['transfer-encoding'] == null &&\n req.headers['content-length'] == null\n ) {\n return null\n }\n\n return Readable.toWeb(req) as ReadableStream\n}\n\n/**\n * Network address type for Node.js TCP connections.\n *\n * @example\n * ```typescript\n * const addr: NetAddr = {\n * transport: 'tcp',\n * hostname: '192.168.1.100',\n * port: 54321\n * }\n * ```\n */\nexport type NetAddr = {\n /** Always 'tcp' for Node.js HTTP connections. */\n transport: 'tcp'\n /** The IP address of the remote client. */\n hostname: string\n /** The port number of the remote client. */\n port: number\n}\n\n/**\n * Connection metadata for Node.js HTTP requests.\n *\n * Provides information about the client connection, including the remote\n * address and a promise that resolves when the connection is fully closed\n * (including WebSocket connections).\n */\nexport type NodeConnectionInfo = {\n /** Promise that resolves when the connection is fully closed. */\n completed: Promise<void>\n /** The remote address of the client, if available. */\n remoteAddr: NetAddr | undefined\n}\n\n/**\n * Interface for objects that can handle fetch-style requests.\n *\n * Used by {@link createServer} and {@link serve} to accept either\n * a fetch handler function or an object with a `fetch` method\n * (like {@link LexRouter}).\n */\nexport interface HandlerObject {\n /** The fetch handler method. */\n fetch: FetchHandler\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n fetchHandler: FetchHandler,\n) {\n const request = toRequest(req)\n const info = toConnectionInfo(req)\n const response = await fetchHandler(request, info)\n await sendResponse(req, res, response)\n}\n\nfunction toConnectionInfo(req: IncomingMessage): NodeConnectionInfo {\n const { socket } = req\n\n return {\n completed: requestCompletion(req),\n remoteAddr:\n socket.remoteAddress != null\n ? {\n transport: 'tcp',\n hostname: socket.remoteAddress,\n port: socket.remotePort!,\n }\n : undefined,\n }\n}\n\n/**\n * Converts a fetch-style handler to a Node.js request listener.\n *\n * The returned listener can be used with Node.js HTTP servers directly,\n * or as middleware in frameworks like Express (supports the `next` callback).\n *\n * @typeParam Request - The request class type (default: IncomingMessage)\n * @typeParam Response - The response class type (default: ServerResponse)\n * @param fetchHandler - The fetch-style handler function\n * @returns A Node.js RequestListener compatible with http.createServer\n *\n * @example Using as Express middleware\n * ```typescript\n * import express from 'express'\n * import { toRequestListener } from '@atproto/lex-server/nodejs'\n * import { LexRouter } from '@atproto/lex-server'\n *\n * const router = new LexRouter()\n * // Register handlers...\n *\n * const app = express()\n *\n * // Mount the XRPC router\n * app.use(toRequestListener(router.fetch))\n * ```\n */\nexport function toRequestListener<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(fetchHandler: FetchHandler) {\n return ((\n req: InstanceType<Request>,\n res: InstanceType<Response> & { req: InstanceType<Request> },\n next?: (err?: unknown) => void,\n ): void => {\n handleRequest(req, res, fetchHandler).catch((err) => {\n if (next) next(err)\n else {\n if (!res.headersSent) {\n res.statusCode = 500\n res.setHeader('content-type', 'text/plain; charset=utf-8')\n res.end('Internal Server Error')\n } else if (!res.writableEnded) {\n res.destroy()\n }\n }\n })\n }) satisfies RequestListener<Request, Response>\n}\n\n/**\n * Options for creating an XRPC server.\n *\n * Extends Node.js {@link ServerOptions} with additional options for graceful shutdown.\n */\nexport type CreateServerOptions<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> = ServerOptions<Request, Response> & {\n /**\n * Timeout in milliseconds for graceful termination.\n *\n * When `terminate()` is called, the server will wait up to this duration\n * for active connections to complete before forcibly closing them.\n */\n gracefulTerminationTimeout?: number\n}\n\n/**\n * Extended HTTP server with graceful shutdown support.\n *\n * Extends the standard Node.js HttpServer with a `terminate()` method\n * for graceful shutdown and implements `AsyncDisposable` for use with\n * `await using`.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n *\n * @example Graceful shutdown\n * ```typescript\n * const server = createServer(router)\n * server.listen(3000)\n *\n * process.on('SIGTERM', async () => {\n * console.log('Shutting down...')\n * await server.terminate()\n * console.log('Server stopped')\n * })\n * ```\n *\n * @example Using with await using\n * ```typescript\n * await using server = await serve(router, { port: 3000 })\n * // Server will be automatically terminated when scope exits\n * ```\n */\nexport interface Server<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> extends HttpServer<Request, Response>,\n AsyncDisposable {\n /**\n * Gracefully terminates the server.\n *\n * Stops accepting new connections and waits for active connections\n * to complete (up to `gracefulTerminationTimeout`).\n *\n * @returns Promise that resolves when the server is fully stopped\n */\n terminate(): Promise<void>\n [Symbol.asyncDispose](): Promise<void>\n}\n\n/**\n * Creates an HTTP server configured for XRPC request handling.\n *\n * The server includes graceful shutdown support and can be used with\n * either a fetch handler function or an object with a `fetch` method\n * (like {@link LexRouter}).\n *\n * Note: This creates the server but does not start listening. Call\n * `server.listen()` to start the server, or use {@link serve} for\n * a combined create-and-listen operation.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n * @param handler - A fetch handler or object with fetch method\n * @param options - Server configuration options\n * @returns An HTTP server with graceful shutdown support\n *\n * @example Basic usage\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { createServer, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n * router.add(myMethod, myHandler)\n *\n * const server = createServer(router)\n * server.listen(3000, () => {\n * console.log('Server listening on port 3000')\n * })\n * ```\n *\n * @example With graceful termination timeout\n * ```typescript\n * const server = createServer(router, {\n * gracefulTerminationTimeout: 10000 // 10 seconds\n * })\n * ```\n */\nexport function createServer<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(\n handler: FetchHandler | HandlerObject,\n options: CreateServerOptions<Request, Response> = {},\n): Server<Request, Response> {\n const fetchHandler =\n typeof handler === 'function' ? handler : handler.fetch.bind(handler)\n\n const listener = toRequestListener(fetchHandler)\n const server = createHttpServer(options, listener)\n\n const terminator = createHttpTerminator({\n server: server as HttpServer,\n gracefulTerminationTimeout: options?.gracefulTerminationTimeout,\n })\n\n const terminate = async function terminate(this: Server<Request, Response>) {\n if (this !== server) {\n throw new TypeError('Server.terminate called with incorrect context')\n }\n // @TODO properly close all active WebSocket connections\n return terminator.terminate()\n }\n\n Object.defineProperty(server, 'terminate', {\n value: terminate,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n Object.defineProperty(server, Symbol.asyncDispose, {\n value: terminate,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n return server as Server<Request, Response>\n}\n\n/**\n * Combined options for creating and starting an XRPC server.\n *\n * Includes both server creation options and network listen options.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n *\n * @example\n * ```typescript\n * const options: StartServerOptions = {\n * port: 3000,\n * host: '0.0.0.0',\n * gracefulTerminationTimeout: 10000\n * }\n * ```\n */\nexport type StartServerOptions<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> = ListenOptions & CreateServerOptions<Request, Response>\n\n/**\n * Creates and starts an HTTP server, returning when it's ready to accept connections.\n *\n * This is a convenience function that combines {@link createServer} and `server.listen()`\n * into a single async operation. The returned promise resolves once the server\n * is actively listening.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n * @param handler - A fetch handler or object with fetch method (like {@link LexRouter})\n * @param options - Combined server and listen options\n * @returns Promise resolving to the running server\n *\n * @example Basic usage\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Register handlers\n * router.add(getProfile, async (ctx) => {\n * return { body: await db.getProfile(ctx.params.actor) }\n * })\n *\n * // Start server on port 3000\n * const server = await serve(router, { port: 3000 })\n * console.log('Server listening on port 3000')\n *\n * // Graceful shutdown\n * process.on('SIGTERM', () => server.terminate())\n * process.on('SIGINT', () => server.terminate())\n * ```\n *\n * @example With all options\n * ```typescript\n * const server = await serve(router, {\n * port: 3000,\n * host: '0.0.0.0',\n * gracefulTerminationTimeout: 15000,\n * })\n * ```\n *\n * @example Using with await using (auto-cleanup)\n * ```typescript\n * async function main() {\n * await using server = await serve(router, { port: 3000 })\n *\n * // Server is running...\n * console.log('Server listening on port 3000')\n *\n * // Wait for termination signal\n * await Promise.race([\n * once(process, 'SIGINT'),\n * once(process, 'SIGTERM'),\n * ])\n *\n * // Server will be automatically terminated when scope exits\n * }\n * ```\n */\nexport async function serve<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(\n handler: FetchHandler | HandlerObject,\n options?: StartServerOptions<Request, Response>,\n): Promise<Server<Request, Response>> {\n const server = createServer(handler, options)\n server.listen(options)\n await once(server, 'listening')\n return server\n}\n"]}
1
+ {"version":3,"file":"nodejs.js","sourceRoot":"","sources":["../src/nodejs.ts"],"names":[],"mappings":"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","sourcesContent":["import { once } from 'node:events'\nimport {\n IncomingHttpHeaders,\n IncomingMessage,\n RequestListener,\n Server as HttpServer,\n ServerOptions,\n ServerResponse,\n createServer as createHttpServer,\n} from 'node:http'\nimport { ListenOptions } from 'node:net'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport type { ReadableStream as NodeReadableStream } from 'node:stream/web'\n// eslint-disable-next-line import/default\nimport httpTerminator from 'http-terminator'\nimport { WebSocket as WebSocketPonyfill, WebSocketServer } from 'ws'\nimport type { FetchHandler } from './lex-router.js'\n\n// @ts-expect-error\nSymbol.asyncDispose ??= Symbol.for('Symbol.asyncDispose')\n\nconst kResponseWs = Symbol.for('@atproto/lex-server:WebSocket')\n\nfunction isUpgradeRequest(request: Request, upgrade: string): boolean {\n return (\n request.method === 'GET' &&\n request.headers.get('connection')?.toLowerCase() === 'upgrade' &&\n request.headers.get('upgrade')?.toLowerCase() === upgrade\n )\n}\n\n/**\n * Upgrades an HTTP request to a WebSocket connection for Node.js.\n *\n * This function must be passed to the {@link LexRouter} constructor to enable\n * subscription (WebSocket) support on Node.js. It creates a WebSocket instance\n * and a placeholder response that signals the need for protocol upgrade.\n *\n * The actual upgrade is handled internally when the response is sent through\n * {@link sendResponse}.\n *\n * @param request - The incoming HTTP request to upgrade\n * @returns An object containing the WebSocket and upgrade response\n * @throws {TypeError} If the request is not a valid WebSocket upgrade request\n *\n * @example\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * // Pass to router for subscription support\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Now you can add subscription handlers\n * router.add(subscribeRepos, async function* (ctx) {\n * for await (const event of eventStream) {\n * yield event\n * }\n * })\n * ```\n */\nexport function upgradeWebSocket(request: Request): {\n response: Response\n socket: WebSocket\n} {\n if (!isUpgradeRequest(request, 'websocket')) {\n throw new TypeError('upgradeWebSocket() expects a WebSocket upgrade')\n }\n\n // Placeholder response for WebSocket upgrade. The actual handling will happen\n // through the handleWebSocketUpgrade function. Headers set on the response\n // will be applied during the upgrade.\n const response = new Response(null, { status: 200 })\n\n // The Response constructor does not allow setting status 101, so we\n // define it directly. The purpose of this response is just to signal\n // that an upgrade is needed, and to carry any headers.\n Object.defineProperty(response, 'status', {\n value: 101,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n // @ts-expect-error\n const socket: WebSocket = new WebSocketPonyfill(null, undefined, {\n autoPong: true,\n })\n\n // Attach the WebSocket to the response for later retrieval\n Object.defineProperty(response, kResponseWs, {\n value: socket,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n return { response, socket }\n}\n\nconst kUpgradeEvent = Symbol.for('@atproto/lex-server:upgrade')\n\nfunction handleWebSocketUpgrade(\n req: IncomingMessage,\n response: Response,\n): void {\n const ws = (response as { [kResponseWs]?: WebSocketPonyfill })[kResponseWs]\n if (!ws) throw new TypeError('Response not created by upgradeWebSocket()')\n\n // Create a one time use WebSocketServer to handle the upgrade\n const wss = new WebSocketServer({\n autoPong: true,\n noServer: true,\n clientTracking: false,\n perMessageDeflate: true,\n // @ts-expect-error\n WebSocket: function () {\n // Return the websocket that was created earlier instead of a new instance\n return ws\n },\n })\n\n // Apply headers that might have been set on the response object during\n // handling. This will be called during wss.handleUpgrade().\n wss.on('headers', (headers) => {\n for (const [name, value] of response.headers) {\n headers.push(`${name}: ${value}`)\n }\n })\n\n wss.handleUpgrade(req, req.socket, Buffer.alloc(0), (_socket) => {\n // @TODO find a way to properly \"close\" the _socket when the server is\n // shutting down (might require replacing http-terminator with a local\n // implementation)\n\n req.emit(kUpgradeEvent, ws)\n })\n}\n\n/**\n * Sends a fetch API Response through a Node.js ServerResponse.\n *\n * Handles both regular HTTP responses and WebSocket upgrades. For WebSocket\n * upgrades (status 101), delegates to the WebSocket upgrade handler.\n *\n * This function is used internally by {@link toRequestListener} and\n * {@link createServer}, but can be used directly for custom integrations.\n *\n * @param req - The Node.js IncomingMessage\n * @param res - The Node.js ServerResponse to write to\n * @param response - The fetch API Response to send\n * @throws {TypeError} If headers have already been sent\n *\n * @example\n * ```typescript\n * import http from 'node:http'\n * import { sendResponse } from '@atproto/lex-server/nodejs'\n *\n * const server = http.createServer(async (req, res) => {\n * const response = new Response('Hello, World!', {\n * headers: { 'Content-Type': 'text/plain' }\n * })\n * await sendResponse(req, res, response)\n * })\n * ```\n */\nexport async function sendResponse(\n req: IncomingMessage,\n res: ServerResponse,\n response: Response,\n): Promise<void> {\n // Invalid usage\n if (res.headersSent) {\n throw new TypeError('Response has already been sent')\n }\n\n if (response.status === 101) {\n return handleWebSocketUpgrade(req, response)\n }\n\n res.statusCode = response.status\n res.statusMessage = response.statusText\n\n for (const [key, value] of response.headers) {\n res.setHeader(key, value)\n }\n\n if (response.body != null && req.method !== 'HEAD') {\n const stream = Readable.fromWeb(response.body as NodeReadableStream)\n await pipeline(stream, res)\n } else {\n await response.body?.cancel()\n res.end()\n }\n}\n\nfunction toRequest(req: IncomingMessage): Request {\n const host = req.headers.host ?? req.socket.localAddress ?? 'localhost'\n const isEncrypted = (req.socket as any).encrypted === true\n const protocol = isEncrypted ? 'https' : 'http'\n const url = new URL(req.url ?? '/', `${protocol}://${host}`)\n const headers = toHeaders(req.headers)\n const body = toBody(req)\n const signal = requestSignal(req)\n\n return new Request(url, {\n signal,\n method: req.method,\n headers,\n body,\n referrer: headers.get('referrer') ?? headers.get('referer') ?? undefined,\n redirect: 'manual',\n // @ts-expect-error\n duplex: body ? 'half' : undefined,\n })\n}\n\nfunction requestSignal(req: IncomingMessage): AbortSignal {\n if (req.destroyed) return AbortSignal.abort()\n\n const abortController = new AbortController()\n\n const abort = (err?: Error | WebSocket) => {\n abortController.abort(err instanceof Error ? err : undefined)\n\n req.off('close', abort)\n req.off('error', abort)\n req.off('end', abort)\n req.off(kUpgradeEvent, abort)\n }\n\n req.on('close', abort)\n req.on('error', abort)\n req.on('end', abort)\n req.on(kUpgradeEvent, abort)\n\n return abortController.signal\n}\n\nfunction requestCompletion(req: IncomingMessage): Promise<void> {\n if (req.destroyed) return Promise.resolve()\n\n // Unlike the abort signal, we complete the promise only when the request\n // is fully done, accounting for websocket upgrade.\n return new Promise((resolve) => {\n const cleanup = () => {\n req.off('close', done)\n req.off('error', done)\n req.off('end', done)\n req.off(kUpgradeEvent, onUpgrade)\n }\n\n const onUpgrade = (ws: WebSocket) => {\n cleanup()\n ws.addEventListener('close', () => resolve())\n }\n\n const done = () => {\n resolve()\n cleanup()\n }\n\n req.on('close', done)\n req.on('error', done)\n req.on('end', done)\n req.on(kUpgradeEvent, onUpgrade)\n })\n}\n\nfunction toHeaders(headers: IncomingHttpHeaders): Headers {\n const result = new Headers()\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue\n if (Array.isArray(value)) {\n for (const v of value) result.append(key, v)\n } else {\n result.set(key, value)\n }\n }\n return result\n}\n\nfunction toBody(req: IncomingMessage): null | ReadableStream {\n if (\n req.method === 'GET' ||\n req.method === 'HEAD' ||\n req.method === 'OPTIONS'\n ) {\n return null\n }\n\n if (\n req.headers['content-type'] == null &&\n req.headers['transfer-encoding'] == null &&\n req.headers['content-length'] == null\n ) {\n return null\n }\n\n return Readable.toWeb(req) as ReadableStream\n}\n\n/**\n * Network address type for Node.js TCP connections.\n *\n * @example\n * ```typescript\n * const addr: NetAddr = {\n * transport: 'tcp',\n * hostname: '192.168.1.100',\n * port: 54321\n * }\n * ```\n */\nexport type NetAddr = {\n /** Always 'tcp' for Node.js HTTP connections. */\n transport: 'tcp'\n /** The IP address of the remote client. */\n hostname: string\n /** The port number of the remote client. */\n port: number\n}\n\n/**\n * Connection metadata for Node.js HTTP requests.\n *\n * Provides information about the client connection, including the remote\n * address and a promise that resolves when the connection is fully closed\n * (including WebSocket connections).\n */\nexport type NodeConnectionInfo = {\n /** Promise that resolves when the connection is fully closed. */\n completed: Promise<void>\n /** The remote address of the client, if available. */\n remoteAddr: NetAddr | undefined\n}\n\n/**\n * Interface for objects that can handle fetch-style requests.\n *\n * Used by {@link createServer} and {@link serve} to accept either\n * a fetch handler function or an object with a `fetch` method\n * (like {@link LexRouter}).\n */\nexport interface HandlerObject {\n /** The fetch handler method. */\n fetch: FetchHandler\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n fetchHandler: FetchHandler,\n) {\n const request = toRequest(req)\n const info = toConnectionInfo(req)\n const response = await fetchHandler(request, info)\n await sendResponse(req, res, response)\n}\n\nfunction toConnectionInfo(req: IncomingMessage): NodeConnectionInfo {\n const { socket } = req\n\n return {\n completed: requestCompletion(req),\n remoteAddr:\n socket.remoteAddress != null\n ? {\n transport: 'tcp',\n hostname: socket.remoteAddress,\n port: socket.remotePort!,\n }\n : undefined,\n }\n}\n\n/**\n * Converts a fetch-style handler to a Node.js request listener.\n *\n * The returned listener can be used with Node.js HTTP servers directly,\n * or as middleware in frameworks like Express (supports the `next` callback).\n *\n * @typeParam Request - The request class type (default: IncomingMessage)\n * @typeParam Response - The response class type (default: ServerResponse)\n * @param fetchHandler - The fetch-style handler function\n * @returns A Node.js RequestListener compatible with http.createServer\n *\n * @example Using as Express middleware\n * ```typescript\n * import express from 'express'\n * import { toRequestListener } from '@atproto/lex-server/nodejs'\n * import { LexRouter } from '@atproto/lex-server'\n *\n * const router = new LexRouter()\n * // Register handlers...\n *\n * const app = express()\n *\n * // Mount the XRPC router\n * app.use(toRequestListener(router.fetch))\n * ```\n */\nexport function toRequestListener<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(fetchHandler: FetchHandler) {\n return ((\n req: InstanceType<Request>,\n res: InstanceType<Response> & { req: InstanceType<Request> },\n next?: (err?: unknown) => void,\n ): void => {\n handleRequest(req, res, fetchHandler).catch((err) => {\n if (next) next(err)\n else {\n if (!res.headersSent) {\n res.statusCode = 500\n res.setHeader('content-type', 'text/plain; charset=utf-8')\n res.end('Internal Server Error')\n } else if (!res.writableEnded) {\n res.destroy()\n }\n }\n })\n }) satisfies RequestListener<Request, Response>\n}\n\n/**\n * Options for creating an XRPC server.\n *\n * Extends Node.js {@link ServerOptions} with additional options for graceful shutdown.\n */\nexport type CreateServerOptions<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> = ServerOptions<Request, Response> & {\n /**\n * Timeout in milliseconds for graceful termination.\n *\n * When `terminate()` is called, the server will wait up to this duration\n * for active connections to complete before forcibly closing them.\n */\n gracefulTerminationTimeout?: number\n}\n\n/**\n * Extended HTTP server with graceful shutdown support.\n *\n * Extends the standard Node.js HttpServer with a `terminate()` method\n * for graceful shutdown and implements `AsyncDisposable` for use with\n * `await using`.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n *\n * @example Graceful shutdown\n * ```typescript\n * const server = createServer(router)\n * server.listen(3000)\n *\n * process.on('SIGTERM', async () => {\n * console.log('Shutting down...')\n * await server.terminate()\n * console.log('Server stopped')\n * })\n * ```\n *\n * @example Using with await using\n * ```typescript\n * await using server = await serve(router, { port: 3000 })\n * // Server will be automatically terminated when scope exits\n * ```\n */\nexport interface Server<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> extends HttpServer<Request, Response>,\n AsyncDisposable {\n /**\n * Gracefully terminates the server.\n *\n * Stops accepting new connections and waits for active connections\n * to complete (up to `gracefulTerminationTimeout`).\n *\n * @returns Promise that resolves when the server is fully stopped\n */\n terminate(): Promise<void>\n [Symbol.asyncDispose](): Promise<void>\n}\n\n/**\n * Creates an HTTP server configured for XRPC request handling.\n *\n * The server includes graceful shutdown support and can be used with\n * either a fetch handler function or an object with a `fetch` method\n * (like {@link LexRouter}).\n *\n * Note: This creates the server but does not start listening. Call\n * `server.listen()` to start the server, or use {@link serve} for\n * a combined create-and-listen operation.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n * @param handler - A fetch handler or object with fetch method\n * @param options - Server configuration options\n * @returns An HTTP server with graceful shutdown support\n *\n * @example Basic usage\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { createServer, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n * router.add(myMethod, myHandler)\n *\n * const server = createServer(router)\n * server.listen(3000, () => {\n * console.log('Server listening on port 3000')\n * })\n * ```\n *\n * @example With graceful termination timeout\n * ```typescript\n * const server = createServer(router, {\n * gracefulTerminationTimeout: 10000 // 10 seconds\n * })\n * ```\n */\nexport function createServer<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(\n handler: FetchHandler | HandlerObject,\n options: CreateServerOptions<Request, Response> = {},\n): Server<Request, Response> {\n const fetchHandler =\n typeof handler === 'function' ? handler : handler.fetch.bind(handler)\n\n const listener = toRequestListener(fetchHandler)\n const server = createHttpServer(options, listener)\n\n const terminator = httpTerminator.createHttpTerminator({\n server: server as HttpServer,\n gracefulTerminationTimeout: options?.gracefulTerminationTimeout,\n })\n\n const terminate = async function terminate(this: Server<Request, Response>) {\n if (this !== server) {\n throw new TypeError('Server.terminate called with incorrect context')\n }\n // @TODO properly close all active WebSocket connections\n return terminator.terminate()\n }\n\n Object.defineProperty(server, 'terminate', {\n value: terminate,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n Object.defineProperty(server, Symbol.asyncDispose, {\n value: terminate,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n\n return server as Server<Request, Response>\n}\n\n/**\n * Combined options for creating and starting an XRPC server.\n *\n * Includes both server creation options and network listen options.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n *\n * @example\n * ```typescript\n * const options: StartServerOptions = {\n * port: 3000,\n * host: '0.0.0.0',\n * gracefulTerminationTimeout: 10000\n * }\n * ```\n */\nexport type StartServerOptions<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n> = ListenOptions & CreateServerOptions<Request, Response>\n\n/**\n * Creates and starts an HTTP server, returning when it's ready to accept connections.\n *\n * This is a convenience function that combines {@link createServer} and `server.listen()`\n * into a single async operation. The returned promise resolves once the server\n * is actively listening.\n *\n * @typeParam Request - The request class type\n * @typeParam Response - The response class type\n * @param handler - A fetch handler or object with fetch method (like {@link LexRouter})\n * @param options - Combined server and listen options\n * @returns Promise resolving to the running server\n *\n * @example Basic usage\n * ```typescript\n * import { LexRouter } from '@atproto/lex-server'\n * import { serve, upgradeWebSocket } from '@atproto/lex-server/nodejs'\n *\n * const router = new LexRouter({ upgradeWebSocket })\n *\n * // Register handlers\n * router.add(getProfile, async (ctx) => {\n * return { body: await db.getProfile(ctx.params.actor) }\n * })\n *\n * // Start server on port 3000\n * const server = await serve(router, { port: 3000 })\n * console.log('Server listening on port 3000')\n *\n * // Graceful shutdown\n * process.on('SIGTERM', () => server.terminate())\n * process.on('SIGINT', () => server.terminate())\n * ```\n *\n * @example With all options\n * ```typescript\n * const server = await serve(router, {\n * port: 3000,\n * host: '0.0.0.0',\n * gracefulTerminationTimeout: 15000,\n * })\n * ```\n *\n * @example Using with await using (auto-cleanup)\n * ```typescript\n * async function main() {\n * await using server = await serve(router, { port: 3000 })\n *\n * // Server is running...\n * console.log('Server listening on port 3000')\n *\n * // Wait for termination signal\n * await Promise.race([\n * once(process, 'SIGINT'),\n * once(process, 'SIGTERM'),\n * ])\n *\n * // Server will be automatically terminated when scope exits\n * }\n * ```\n */\nexport async function serve<\n Request extends typeof IncomingMessage = typeof IncomingMessage,\n Response extends typeof ServerResponse<\n InstanceType<Request>\n > = typeof ServerResponse,\n>(\n handler: FetchHandler | HandlerObject,\n options?: StartServerOptions<Request, Response>,\n): Promise<Server<Request, Response>> {\n const server = createServer(handler, options)\n server.listen(options)\n await once(server, 'listening')\n return server\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },
@@ -44,24 +44,24 @@
44
44
  "http-terminator": "^3.2.0",
45
45
  "tslib": "^2.8.1",
46
46
  "ws": "^8.18.3",
47
- "@atproto-labs/did-resolver": "^0.3.1",
48
- "@atproto/crypto": "^0.5.0",
49
- "@atproto/did": "^0.5.0",
50
- "@atproto/lex-cbor": "^0.1.0",
51
- "@atproto/lex-client": "^0.1.3",
52
- "@atproto/lex-data": "^0.1.1",
53
- "@atproto/lex-json": "^0.1.0",
54
- "@atproto/lex-schema": "^0.1.2"
47
+ "@atproto/crypto": "^0.5.2",
48
+ "@atproto-labs/did-resolver": "^0.3.3",
49
+ "@atproto/lex-cbor": "^0.1.2",
50
+ "@atproto/did": "^0.5.2",
51
+ "@atproto/lex-client": "^0.1.5",
52
+ "@atproto/lex-data": "^0.1.3",
53
+ "@atproto/lex-json": "^0.1.2",
54
+ "@atproto/lex-schema": "^0.1.5"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/ws": "^8.18.1",
58
58
  "@vitest/coverage-v8": "4.0.16",
59
59
  "vitest": "^4.0.16",
60
- "@atproto/lex": "^0.1.3",
61
- "@atproto/lex-client": "^0.1.3"
60
+ "@atproto/lex-client": "^0.1.5",
61
+ "@atproto/lex": "^0.1.5"
62
62
  },
63
63
  "scripts": {
64
- "build": "tsc --build tsconfig.build.json",
64
+ "build": "tsgo --build tsconfig.build.json",
65
65
  "test": "vitest run"
66
66
  }
67
67
  }
package/src/nodejs.ts CHANGED
@@ -12,10 +12,8 @@ import { ListenOptions } from 'node:net'
12
12
  import { Readable } from 'node:stream'
13
13
  import { pipeline } from 'node:stream/promises'
14
14
  import type { ReadableStream as NodeReadableStream } from 'node:stream/web'
15
- // eslint-disable-next-line import/default, import/no-named-as-default-member
15
+ // eslint-disable-next-line import/default
16
16
  import httpTerminator from 'http-terminator'
17
- // eslint-disable-next-line import/no-named-as-default-member
18
- const { createHttpTerminator } = httpTerminator
19
17
  import { WebSocket as WebSocketPonyfill, WebSocketServer } from 'ws'
20
18
  import type { FetchHandler } from './lex-router.js'
21
19
 
@@ -549,7 +547,7 @@ export function createServer<
549
547
  const listener = toRequestListener(fetchHandler)
550
548
  const server = createHttpServer(options, listener)
551
549
 
552
- const terminator = createHttpTerminator({
550
+ const terminator = httpTerminator.createHttpTerminator({
553
551
  server: server as HttpServer,
554
552
  gracefulTerminationTimeout: options?.gracefulTerminationTimeout,
555
553
  })
@@ -7,6 +7,6 @@
7
7
  "importHelpers": true,
8
8
  "target": "ES2023",
9
9
  "rootDir": "./src",
10
- "outDir": "./dist"
11
- }
10
+ "outDir": "./dist",
11
+ },
12
12
  }
package/tsconfig.json CHANGED
@@ -3,6 +3,6 @@
3
3
  "references": [
4
4
  { "path": "./tsconfig.build.json" },
5
5
  { "path": "./tsconfig.examples.json" },
6
- { "path": "./tsconfig.tests.json" }
7
- ]
6
+ { "path": "./tsconfig.tests.json" },
7
+ ],
8
8
  }
@@ -4,6 +4,5 @@
4
4
  "compilerOptions": {
5
5
  "noImplicitAny": true,
6
6
  "rootDir": "./",
7
- "baseUrl": "./"
8
- }
7
+ },
9
8
  }