@nestjs-kit/better-auth 0.0.0-stage → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +1078 -2
  3. package/dist/admin.cjs +88 -0
  4. package/dist/admin.cjs.map +1 -0
  5. package/dist/admin.d.cts +14 -0
  6. package/dist/admin.d.cts.map +1 -0
  7. package/dist/admin.d.mts +14 -0
  8. package/dist/admin.d.mts.map +1 -0
  9. package/dist/admin.mjs +85 -0
  10. package/dist/admin.mjs.map +1 -0
  11. package/dist/api-key.cjs +164 -0
  12. package/dist/api-key.cjs.map +1 -0
  13. package/dist/api-key.d.cts +42 -0
  14. package/dist/api-key.d.cts.map +1 -0
  15. package/dist/api-key.d.mts +42 -0
  16. package/dist/api-key.d.mts.map +1 -0
  17. package/dist/api-key.mjs +160 -0
  18. package/dist/api-key.mjs.map +1 -0
  19. package/dist/auth-contracts-Brh_Qko9.d.cts +1654 -0
  20. package/dist/auth-contracts-Brh_Qko9.d.cts.map +1 -0
  21. package/dist/auth-contracts-Cz7C4_Ch.d.mts +1654 -0
  22. package/dist/auth-contracts-Cz7C4_Ch.d.mts.map +1 -0
  23. package/dist/auth-decorators-B1mFnGJ6.mjs +284 -0
  24. package/dist/auth-decorators-B1mFnGJ6.mjs.map +1 -0
  25. package/dist/auth-decorators-Cu_nxWnF.cjs +421 -0
  26. package/dist/auth-decorators-Cu_nxWnF.cjs.map +1 -0
  27. package/dist/auth-errors-C3rbTV9p.mjs +301 -0
  28. package/dist/auth-errors-C3rbTV9p.mjs.map +1 -0
  29. package/dist/auth-errors-DmiKl0L_.cjs +378 -0
  30. package/dist/auth-errors-DmiKl0L_.cjs.map +1 -0
  31. package/dist/auth-guard-CLyhAEEj.cjs +136 -0
  32. package/dist/auth-guard-CLyhAEEj.cjs.map +1 -0
  33. package/dist/auth-guard-h9QB_l11.mjs +125 -0
  34. package/dist/auth-guard-h9QB_l11.mjs.map +1 -0
  35. package/dist/auth-module-BgcY2HpA.cjs +2809 -0
  36. package/dist/auth-module-BgcY2HpA.cjs.map +1 -0
  37. package/dist/auth-module-CtHx3gRU.mjs +2708 -0
  38. package/dist/auth-module-CtHx3gRU.mjs.map +1 -0
  39. package/dist/auth-scope-interceptor-BjxAL1-S.cjs +290 -0
  40. package/dist/auth-scope-interceptor-BjxAL1-S.cjs.map +1 -0
  41. package/dist/auth-scope-interceptor-DYPn3b8M.mjs +231 -0
  42. package/dist/auth-scope-interceptor-DYPn3b8M.mjs.map +1 -0
  43. package/dist/bridge-protocol-BDw8opAG.cjs +25 -0
  44. package/dist/bridge-protocol-BDw8opAG.cjs.map +1 -0
  45. package/dist/bridge-protocol-c66aEkr5.mjs +8 -0
  46. package/dist/bridge-protocol-c66aEkr5.mjs.map +1 -0
  47. package/dist/decorate-Cr4Q7bNE.cjs +319 -0
  48. package/dist/decorate-Cr4Q7bNE.cjs.map +1 -0
  49. package/dist/decorate-Dt0e9K6R.mjs +80 -0
  50. package/dist/decorate-Dt0e9K6R.mjs.map +1 -0
  51. package/dist/express.cjs +256 -0
  52. package/dist/express.cjs.map +1 -0
  53. package/dist/express.d.cts +37 -0
  54. package/dist/express.d.cts.map +1 -0
  55. package/dist/express.d.mts +37 -0
  56. package/dist/express.d.mts.map +1 -0
  57. package/dist/express.mjs +254 -0
  58. package/dist/express.mjs.map +1 -0
  59. package/dist/fastify.cjs +218 -0
  60. package/dist/fastify.cjs.map +1 -0
  61. package/dist/fastify.d.cts +28 -0
  62. package/dist/fastify.d.cts.map +1 -0
  63. package/dist/fastify.d.mts +28 -0
  64. package/dist/fastify.d.mts.map +1 -0
  65. package/dist/fastify.mjs +216 -0
  66. package/dist/fastify.mjs.map +1 -0
  67. package/dist/graphql.cjs +509 -0
  68. package/dist/graphql.cjs.map +1 -0
  69. package/dist/graphql.d.cts +38 -0
  70. package/dist/graphql.d.cts.map +1 -0
  71. package/dist/graphql.d.mts +38 -0
  72. package/dist/graphql.d.mts.map +1 -0
  73. package/dist/graphql.mjs +503 -0
  74. package/dist/graphql.mjs.map +1 -0
  75. package/dist/index.cjs +86 -0
  76. package/dist/index.d.cts +2 -0
  77. package/dist/index.d.mts +2 -0
  78. package/dist/index.mjs +8 -0
  79. package/dist/microservices.cjs +231 -0
  80. package/dist/microservices.cjs.map +1 -0
  81. package/dist/microservices.d.cts +39 -0
  82. package/dist/microservices.d.cts.map +1 -0
  83. package/dist/microservices.d.mts +39 -0
  84. package/dist/microservices.d.mts.map +1 -0
  85. package/dist/microservices.mjs +222 -0
  86. package/dist/microservices.mjs.map +1 -0
  87. package/dist/organization.cjs +191 -0
  88. package/dist/organization.cjs.map +1 -0
  89. package/dist/organization.d.cts +40 -0
  90. package/dist/organization.d.cts.map +1 -0
  91. package/dist/organization.d.mts +40 -0
  92. package/dist/organization.d.mts.map +1 -0
  93. package/dist/organization.mjs +177 -0
  94. package/dist/organization.mjs.map +1 -0
  95. package/dist/platform-CZl7TY8j.mjs +414 -0
  96. package/dist/platform-CZl7TY8j.mjs.map +1 -0
  97. package/dist/platform-YICqqYv6.cjs +473 -0
  98. package/dist/platform-YICqqYv6.cjs.map +1 -0
  99. package/dist/platform.cjs +10 -0
  100. package/dist/platform.d.cts +43 -0
  101. package/dist/platform.d.cts.map +1 -0
  102. package/dist/platform.d.mts +43 -0
  103. package/dist/platform.d.mts.map +1 -0
  104. package/dist/platform.mjs +1 -0
  105. package/dist/plugin.cjs +323 -0
  106. package/dist/plugin.cjs.map +1 -0
  107. package/dist/plugin.d.cts +24 -0
  108. package/dist/plugin.d.cts.map +1 -0
  109. package/dist/plugin.d.mts +24 -0
  110. package/dist/plugin.d.mts.map +1 -0
  111. package/dist/plugin.mjs +321 -0
  112. package/dist/plugin.mjs.map +1 -0
  113. package/dist/principal-readings-Chmt6rQV.cjs +208 -0
  114. package/dist/principal-readings-Chmt6rQV.cjs.map +1 -0
  115. package/dist/principal-readings-Ied2staw.mjs +191 -0
  116. package/dist/principal-readings-Ied2staw.mjs.map +1 -0
  117. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  118. package/dist/testing/conformance.cjs +6214 -0
  119. package/dist/testing/conformance.cjs.map +1 -0
  120. package/dist/testing/conformance.d.cts +528 -0
  121. package/dist/testing/conformance.d.cts.map +1 -0
  122. package/dist/testing/conformance.d.mts +528 -0
  123. package/dist/testing/conformance.d.mts.map +1 -0
  124. package/dist/testing/conformance.mjs +6204 -0
  125. package/dist/testing/conformance.mjs.map +1 -0
  126. package/dist/testing.cjs +221 -0
  127. package/dist/testing.cjs.map +1 -0
  128. package/dist/testing.d.cts +64 -0
  129. package/dist/testing.d.cts.map +1 -0
  130. package/dist/testing.d.mts +64 -0
  131. package/dist/testing.d.mts.map +1 -0
  132. package/dist/testing.mjs +214 -0
  133. package/dist/testing.mjs.map +1 -0
  134. package/dist/websockets.cjs +396 -0
  135. package/dist/websockets.cjs.map +1 -0
  136. package/dist/websockets.d.cts +67 -0
  137. package/dist/websockets.d.cts.map +1 -0
  138. package/dist/websockets.d.mts +67 -0
  139. package/dist/websockets.d.mts.map +1 -0
  140. package/dist/websockets.mjs +383 -0
  141. package/dist/websockets.mjs.map +1 -0
  142. package/package.json +327 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.mjs","names":[],"sources":["../src/express-platform.ts"],"sourcesContent":["import {\n type IncomingHttpHeaders,\n IncomingMessage,\n ServerResponse,\n} from \"node:http\";\nimport { Readable } from \"node:stream\";\nimport type { AbstractHttpAdapter } from \"@nestjs/core\";\nimport { parse, pathToRegexp } from \"path-to-regexp\";\nimport type {\n ApplicationRouteDescriptor,\n AuthRouteBinding,\n ExpressPlatformOptions,\n HttpPlatform,\n PlatformMountContext,\n PlatformPrepareContext,\n ProxyTrust,\n} from \"./auth-contracts.js\";\nimport { BetterAuthConfigurationError } from \"./auth-errors.js\";\nimport {\n appendSetCookie,\n bindAsyncContext,\n mayHaveBody,\n readBoundedBody,\n recoverConsumedBody,\n toWebHeaders,\n writeWebResponse,\n} from \"./platform.js\";\n\nconst RAW_BODY = Symbol.for(\"@nestjs-kit/better-auth:raw-body\");\n\ntype Next = (error?: unknown) => void;\ntype CapturedBody = Awaited<ReturnType<typeof readBoundedBody>>;\ntype ExpressResponse = ServerResponse & { req?: ExpressRequest };\ntype ExpressRequest = IncomingMessage & {\n readonly originalUrl?: string;\n readonly protocol?: string;\n readonly host?: string;\n readonly ip?: string;\n readonly res?: ExpressResponse;\n readonly params?: Record<string, unknown>;\n readonly body?: unknown;\n readonly rawBody?: Buffer;\n [RAW_BODY]?: CapturedBody;\n};\ntype ExpressApplication = {\n use(\n handler: (req: ExpressRequest, res: ExpressResponse, next: Next) => void,\n ): unknown;\n get(setting: string): unknown;\n readonly router?: unknown;\n};\ntype ExpressRouterOptions = {\n readonly caseSensitive: boolean;\n readonly strict: boolean;\n};\ntype ApplicationRouteMatcher = {\n readonly method: string;\n readonly regexp: RegExp;\n};\n\nfunction application(adapter: AbstractHttpAdapter): ExpressApplication {\n return adapter.getInstance() as ExpressApplication;\n}\n\nfunction routerOptions(\n app: ExpressApplication | undefined,\n): ExpressRouterOptions {\n const router = app?.router;\n if (\n (typeof router !== \"object\" && typeof router !== \"function\") ||\n router === null\n ) {\n throw new BetterAuthConfigurationError(\n \"UNSUPPORTED_EXPRESS_ROUTER\",\n \"The Express application does not expose its initialized router.\",\n \"Use Express 5.2.x with @nestjs/platform-express 12.x, or move controller routes outside the auth mount.\",\n );\n }\n const options = router as Partial<ExpressRouterOptions>;\n if (\n typeof options.caseSensitive !== \"boolean\" ||\n typeof options.strict !== \"boolean\"\n ) {\n throw new BetterAuthConfigurationError(\n \"UNSUPPORTED_EXPRESS_ROUTER\",\n \"The initialized Express router does not expose compatible routing options.\",\n \"Use Express 5.2.x with @nestjs/platform-express 12.x, or move controller routes outside the auth mount.\",\n );\n }\n return { caseSensitive: options.caseSensitive, strict: options.strict };\n}\n\nfunction routeMayOverlapMount(path: string, basePath: string): boolean {\n const { tokens } = parse(path);\n let literalPrefix = \"\";\n let dynamic = false;\n for (const token of tokens) {\n if (token.type !== \"text\") {\n dynamic = true;\n break;\n }\n literalPrefix += token.value;\n }\n const route = literalPrefix.toLowerCase();\n const base = basePath.toLowerCase().replace(/(?<!\\/)\\/+$/, \"\") || \"/\";\n if (base === \"/\") {\n return route.startsWith(\"/\");\n }\n if (!dynamic) {\n const exact = route.replace(/(?<!\\/)\\/+$/, \"\") || \"/\";\n return exact === base || exact.startsWith(`${base}/`);\n }\n if (base.startsWith(route)) {\n return true;\n }\n return route === base || route.startsWith(`${base}/`);\n}\n\nfunction rawTarget(req: ExpressRequest): string {\n return req.originalUrl ?? req.url ?? \"/\";\n}\n\nfunction rawPath(req: ExpressRequest): string {\n const target = rawTarget(req);\n const query = target.indexOf(\"?\");\n return query === -1 ? target : target.slice(0, query);\n}\n\nfunction declaredLength(\n headers: IncomingHttpHeaders,\n limit: number,\n): number | undefined {\n const value = headers[\"content-length\"];\n const first = Array.isArray(value) ? value[0] : value;\n if (typeof first !== \"string\" || !/^\\d+$/.test(first)) {\n return undefined;\n }\n const parsed = Number(first);\n return Number.isSafeInteger(parsed) ? parsed : limit + 1;\n}\n\nfunction requestUrl(req: ExpressRequest): string {\n const socket = req.socket as typeof req.socket & { encrypted?: boolean };\n return `${req.protocol ?? (socket.encrypted ? \"https\" : \"http\")}://${req.host ?? \"\"}${rawTarget(req)}`;\n}\n\n/**\n * Identifies Express's request by the Node objects it extends, never by shape: a GraphQL\n * context can carry client-parsed data, and JSON can reproduce any structural check.\n * light-my-request's inject() re-parents Express's shared request prototype onto its own\n * Readable-based request for the whole process, so a stream request is accepted too; its\n * response must still be a ServerResponse bound to it in both directions.\n */\nfunction isExpressRequest(value: unknown): value is ExpressRequest {\n if (!(value instanceof IncomingMessage || value instanceof Readable)) {\n return false;\n }\n const res: unknown = Reflect.get(value, \"res\");\n return (\n res instanceof ServerResponse &&\n res.req === value &&\n Reflect.get(value, \"res\") === res &&\n typeof res.setHeader === \"function\" &&\n typeof res.getHeader === \"function\"\n );\n}\n\nfunction nativeResponse(value: unknown): ServerResponse | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n const response = value as Partial<ServerResponse>;\n return typeof response.setHeader === \"function\" &&\n typeof response.getHeader === \"function\"\n ? (value as ServerResponse)\n : null;\n}\n\nfunction proxyTrustOf(value: unknown): ProxyTrust {\n if (value === false || value === undefined) {\n return { mode: \"none\", detail: \"trust proxy = false\" };\n }\n if (value === true) {\n return { mode: \"all\", detail: \"trust proxy = true\" };\n }\n const rendered =\n typeof value === \"function\"\n ? \"<function>\"\n : Array.isArray(value)\n ? JSON.stringify(value)\n : String(value);\n return { mode: \"partial\", detail: `trust proxy = ${rendered}` };\n}\n\nfunction abortOnDisconnect(\n req: ExpressRequest,\n res: ExpressResponse,\n): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abort = () => controller.abort();\n req.once(\"aborted\", abort);\n res.once(\"close\", abort);\n if (req.aborted || res.destroyed) {\n abort();\n }\n return {\n signal: controller.signal,\n dispose: () => {\n req.removeListener(\"aborted\", abort);\n res.removeListener(\"close\", abort);\n },\n };\n}\n\n/** Express-specific two-phase HTTP integration. */\nexport class ExpressPlatform implements HttpPlatform {\n readonly id = \"express\";\n #warnedConsumedBody = false;\n #applicationRoutes: readonly ApplicationRouteMatcher[] = [];\n #application: ExpressApplication | undefined;\n\n constructor(private readonly options: ExpressPlatformOptions = {}) {}\n\n readonly requests = {\n isRequest: (value: unknown): boolean => isExpressRequest(value),\n isLive: (value: unknown): boolean =>\n isExpressRequest(value) && value.res?.writableEnded === false,\n key: (value: unknown): object => value as object,\n headers: (value: unknown): Headers =>\n toWebHeaders((value as ExpressRequest).headers),\n request: (value: unknown) => {\n const req = value as ExpressRequest;\n return { method: req.method ?? \"GET\", url: requestUrl(req) };\n },\n clientIp: (value: unknown): string | null =>\n this.clientIp(value as ExpressRequest),\n param: (value: unknown, name: string): string | undefined => {\n const parameter = (value as ExpressRequest).params?.[name];\n return typeof parameter === \"string\" ? parameter : undefined;\n },\n cookieSink: (request: unknown, response: unknown) => {\n const req = request as ExpressRequest;\n const res = nativeResponse(response) ?? nativeResponse(req.res);\n return res === null\n ? null\n : {\n append: (cookies: readonly string[]) =>\n appendSetCookie(res, cookies),\n };\n },\n };\n\n supports(adapter: AbstractHttpAdapter): boolean {\n return adapter.getType?.() === \"express\";\n }\n\n prepare(ctx: PlatformPrepareContext): void {\n const app = application(ctx.adapter);\n this.#application = app;\n app.use((req, _res, next) => {\n const binding = ctx.route(rawPath(req));\n const method = (req.method ?? \"GET\").toUpperCase();\n if (\n !binding ||\n this.isApplicationRoute(method, rawPath(req)) ||\n method === \"GET\" ||\n method === \"HEAD\" ||\n method === \"OPTIONS\" ||\n !mayHaveBody(method, req.headers)\n ) {\n next();\n return;\n }\n\n const continueRequest = bindAsyncContext(next);\n if (req.readableEnded || req.readable === false) {\n const recovered = recoverConsumedBody(req);\n req[RAW_BODY] = {\n ok: true,\n bytes: recovered ?? new Uint8Array(),\n };\n if (!this.#warnedConsumedBody) {\n this.#warnedConsumedBody = true;\n ctx.logger.warn(\n \"W_BODY_ALREADY_CONSUMED: an Express body parser ran before the auth capture; raw-signature webhooks may receive re-serialized bytes.\",\n );\n }\n continueRequest();\n return;\n }\n\n void readBoundedBody(req, {\n limit: binding.bodyLimit,\n declaredLength: declaredLength(req.headers, binding.bodyLimit),\n drainOnOverflow: true,\n drainCap: Math.min(Number.MAX_SAFE_INTEGER, binding.bodyLimit * 8),\n }).then(\n (captured) => {\n req[RAW_BODY] = captured;\n continueRequest();\n },\n (error: unknown) => continueRequest(error),\n );\n });\n }\n\n applicationRoutes(\n routes: readonly ApplicationRouteDescriptor[],\n bindings: readonly AuthRouteBinding[],\n ): void {\n const bodyRoutes = routes.flatMap((route) => {\n if ([\"GET\", \"HEAD\", \"OPTIONS\"].includes(route.method)) {\n return [];\n }\n const paths = route.paths.filter((path) =>\n bindings.some((binding) =>\n routeMayOverlapMount(path, binding.basePath),\n ),\n );\n return paths.length ? [{ ...route, paths }] : [];\n });\n const conditional = bodyRoutes.find((route) => route.conditions.length > 0);\n if (conditional) {\n throw new BetterAuthConfigurationError(\n \"CONDITIONAL_ROUTE_SHADOW\",\n `${conditional.source} at '${conditional.paths.join(\", \")}' uses ${conditional.conditions.join(\" and \")} routing under an auth mount.`,\n \"Move the controller route outside the auth mount or make its host and version routing unconditional.\",\n );\n }\n if (bodyRoutes.length === 0) {\n this.#applicationRoutes = [];\n return;\n }\n const { caseSensitive, strict } = routerOptions(this.#application);\n this.#applicationRoutes = Object.freeze(\n bodyRoutes.flatMap((route) =>\n route.paths.map((path) => ({\n method: route.method,\n regexp: pathToRegexp(path, {\n end: true,\n sensitive: caseSensitive,\n trailing: !strict,\n }).regexp,\n })),\n ),\n );\n }\n\n mount(ctx: PlatformMountContext): void {\n application(ctx.adapter).use((req, res, next) => {\n if (!ctx.binding.matches(rawPath(req))) {\n next();\n return;\n }\n const disconnect = abortOnDisconnect(req, res);\n void this.dispatch(ctx.binding, req, res, disconnect.signal).then(\n () => disconnect.dispose(),\n (error: unknown) => {\n disconnect.dispose();\n if (!disconnect.signal.aborted) {\n next(error);\n }\n },\n );\n });\n }\n\n proxyTrust(adapter: AbstractHttpAdapter): ProxyTrust {\n return proxyTrustOf(application(adapter).get(\"trust proxy\"));\n }\n\n private clientIp(req: ExpressRequest): string | null {\n if (this.options.clientIp) {\n return this.options.clientIp(req);\n }\n return req.ip ?? null;\n }\n\n private isApplicationRoute(method: string, pathname: string): boolean {\n return this.#applicationRoutes.some(\n (route) =>\n (route.method === \"ALL\" || route.method === method) &&\n route.regexp.test(pathname),\n );\n }\n\n private async dispatch(\n binding: AuthRouteBinding,\n req: ExpressRequest,\n res: ExpressResponse,\n signal: AbortSignal,\n ): Promise<void> {\n const captured = req[RAW_BODY];\n if (\n (captured && !captured.ok && captured.reason === \"aborted\") ||\n signal.aborted\n ) {\n return;\n }\n const response =\n captured && !captured.ok && captured.reason === \"too-large\"\n ? binding.payloadTooLarge()\n : await binding.handle({\n method: req.method ?? \"GET\",\n url: requestUrl(req),\n headers: toWebHeaders(req.headers),\n body: captured?.ok ? captured.bytes : null,\n clientIp: this.clientIp(req),\n platformRequest: req,\n signal,\n });\n if (signal.aborted) {\n await response.body?.cancel().catch(() => undefined);\n return;\n }\n await writeWebResponse(res, response, {\n head: req.method?.toUpperCase() === \"HEAD\",\n });\n }\n}\n\nexport function expressPlatform(\n options?: ExpressPlatformOptions,\n): ExpressPlatform {\n return new ExpressPlatform(options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,218 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_platform = require("./platform-YICqqYv6.cjs");
3
+ //#region src/fastify-platform.ts
4
+ function instanceOf(adapter) {
5
+ return adapter.getInstance();
6
+ }
7
+ function asRequest(value) {
8
+ if (typeof value !== "object" || value === null) return;
9
+ const request = value;
10
+ return typeof request.raw === "object" && request.raw !== null ? request : void 0;
11
+ }
12
+ function varyParts(value) {
13
+ return (Array.isArray(value) ? value : value === void 0 ? [] : [value]).flatMap((item) => String(item).split(","));
14
+ }
15
+ function mergedVary(current, added) {
16
+ const values = [...varyParts(current), ...varyParts(added)].map((item) => item.trim()).filter(Boolean);
17
+ if (values.includes("*")) return "*";
18
+ const seen = /* @__PURE__ */ new Set();
19
+ return values.filter((item) => {
20
+ const key = item.toLowerCase();
21
+ if (seen.has(key)) return false;
22
+ seen.add(key);
23
+ return true;
24
+ }).join(", ");
25
+ }
26
+ function abortOnDisconnect(request, response) {
27
+ const controller = new AbortController();
28
+ let disposed = false;
29
+ const abort = () => {
30
+ if (!controller.signal.aborted) controller.abort();
31
+ };
32
+ const onRequestAborted = () => abort();
33
+ const onRequestError = () => abort();
34
+ const onResponseClose = () => {
35
+ if (!response.writableFinished) abort();
36
+ };
37
+ const onResponseError = () => abort();
38
+ const dispose = () => {
39
+ if (disposed) return;
40
+ disposed = true;
41
+ request.removeListener("aborted", onRequestAborted);
42
+ request.removeListener("error", onRequestError);
43
+ response.removeListener("close", onResponseClose);
44
+ response.removeListener("error", onResponseError);
45
+ };
46
+ request.once("aborted", onRequestAborted);
47
+ request.once("error", onRequestError);
48
+ response.once("close", onResponseClose);
49
+ response.once("error", onResponseError);
50
+ if (request.aborted || response.destroyed || request.socket.destroyed && !response.writableFinished) abort();
51
+ return {
52
+ signal: controller.signal,
53
+ dispose
54
+ };
55
+ }
56
+ function appendReplyCookies(reply, cookies) {
57
+ for (const cookie of require_platform.setCookieAdditions(require_platform.headerLines(reply.getHeader("set-cookie")), cookies)) reply.header("set-cookie", cookie);
58
+ }
59
+ async function sendWebResponse(reply, response, head) {
60
+ reply.code(response.status);
61
+ for (const [name, value] of response.headers) {
62
+ if (name === "set-cookie") continue;
63
+ reply.header(name, name === "vary" ? mergedVary(reply.getHeader(name), value) : value);
64
+ }
65
+ appendReplyCookies(reply, response.headers.getSetCookie());
66
+ if (reply.request.raw.httpVersionMajor === 2) for (const name of [
67
+ "connection",
68
+ "keep-alive",
69
+ "proxy-connection",
70
+ "transfer-encoding",
71
+ "upgrade"
72
+ ]) reply.removeHeader(name);
73
+ if (head && response.body !== null) await response.body.cancel().catch(() => void 0);
74
+ return reply.send(head ? void 0 : response.body ?? void 0);
75
+ }
76
+ /**
77
+ * Fastify's encapsulated auth-route platform adapter.
78
+ *
79
+ * Fastify applies `trustProxy` to `request.ip`, but does not expose that option
80
+ * through its public instance metadata. Proxy-trust reporting is therefore
81
+ * intentionally unavailable instead of guessing a diagnostic mode.
82
+ */
83
+ var FastifyPlatform = class {
84
+ options;
85
+ id = "fastify";
86
+ capabilities = {
87
+ http2: true,
88
+ prepareAtInit: true
89
+ };
90
+ requests;
91
+ #replies = /* @__PURE__ */ new WeakMap();
92
+ constructor(options = {}) {
93
+ this.options = options;
94
+ this.requests = {
95
+ isRequest: (value) => {
96
+ const request = asRequest(value);
97
+ return request !== void 0 && this.#replies.has(request.raw);
98
+ },
99
+ isLive: (value) => {
100
+ const request = asRequest(value);
101
+ const reply = request && this.#replies.get(request.raw);
102
+ return reply !== void 0 && !reply.sent;
103
+ },
104
+ key: (value) => {
105
+ return asRequest(value)?.raw ?? value;
106
+ },
107
+ headers: (value) => {
108
+ const request = asRequest(value);
109
+ return request ? require_platform.toWebHeaders(request.raw.headers) : new Headers();
110
+ },
111
+ request: (value) => {
112
+ const request = asRequest(value);
113
+ if (!request) return {
114
+ method: "GET",
115
+ url: ""
116
+ };
117
+ return {
118
+ method: request.method,
119
+ url: `${request.protocol}://${request.host}${request.originalUrl}`
120
+ };
121
+ },
122
+ clientIp: (value) => {
123
+ const request = asRequest(value);
124
+ return request ? this.options.clientIp?.(request) ?? request.ip ?? null : null;
125
+ },
126
+ param: (value, name) => {
127
+ const request = asRequest(value);
128
+ if (!request || typeof request.params !== "object" || request.params === null) return;
129
+ const parameter = Reflect.get(request.params, name);
130
+ return typeof parameter === "string" ? parameter : void 0;
131
+ },
132
+ cookieSink: (value, response) => {
133
+ const request = asRequest(value);
134
+ if (!request) return null;
135
+ const supplied = response;
136
+ const reply = supplied && typeof supplied.header === "function" && typeof supplied.sent === "boolean" ? supplied : this.#replies.get(request.raw);
137
+ if (!reply) return null;
138
+ return { append: (cookies) => {
139
+ if (reply.sent || reply.raw.headersSent) return false;
140
+ appendReplyCookies(reply, cookies);
141
+ return true;
142
+ } };
143
+ },
144
+ responseFor: (value) => {
145
+ const request = asRequest(value);
146
+ return request ? this.#replies.get(request.raw) : void 0;
147
+ }
148
+ };
149
+ }
150
+ supports(adapter) {
151
+ return adapter.getType() === "fastify";
152
+ }
153
+ prepare(context) {
154
+ const root = instanceOf(context.adapter);
155
+ this.#replies = /* @__PURE__ */ new WeakMap();
156
+ root.addHook("onRequest", (request, reply, done) => {
157
+ this.#replies.set(request.raw, reply);
158
+ done();
159
+ });
160
+ }
161
+ async mount(context) {
162
+ const root = instanceOf(context.adapter);
163
+ const { binding } = context;
164
+ await root.register(async (scope) => {
165
+ scope.removeAllContentTypeParsers();
166
+ scope.addContentTypeParser("*", {
167
+ parseAs: "buffer",
168
+ bodyLimit: binding.bodyLimit
169
+ }, (_request, body, done) => done(null, body));
170
+ scope.setErrorHandler(function(error, request, reply) {
171
+ if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "FST_ERR_CTP_BODY_TOO_LARGE") return sendWebResponse(reply, binding.payloadTooLarge(), false);
172
+ return root.errorHandler.call(this, error, request, reply);
173
+ });
174
+ const handler = async (request, reply) => {
175
+ const cancellation = abortOnDisconnect(request.raw, reply.raw);
176
+ try {
177
+ const response = await binding.handle({
178
+ method: request.method,
179
+ url: `${request.protocol}://${request.host}${request.originalUrl}`,
180
+ headers: require_platform.toWebHeaders(request.raw.headers),
181
+ body: request.body instanceof Uint8Array ? request.body : null,
182
+ clientIp: this.options.clientIp?.(request) ?? request.ip ?? null,
183
+ platformRequest: request,
184
+ signal: cancellation.signal
185
+ });
186
+ if (cancellation.signal.aborted) return;
187
+ return await sendWebResponse(reply, response, request.method.toUpperCase() === "HEAD");
188
+ } catch (error) {
189
+ if (cancellation.signal.aborted) return;
190
+ throw error;
191
+ } finally {
192
+ cancellation.dispose();
193
+ }
194
+ };
195
+ const methods = [...scope.supportedMethods];
196
+ scope.route({
197
+ method: methods,
198
+ url: "/",
199
+ handler,
200
+ exposeHeadRoute: false
201
+ });
202
+ scope.route({
203
+ method: methods,
204
+ url: "/*",
205
+ handler,
206
+ exposeHeadRoute: false
207
+ });
208
+ }, { prefix: binding.basePath });
209
+ }
210
+ };
211
+ function fastifyPlatform(options) {
212
+ return new FastifyPlatform(options);
213
+ }
214
+ //#endregion
215
+ exports.FastifyPlatform = FastifyPlatform;
216
+ exports.fastifyPlatform = fastifyPlatform;
217
+
218
+ //# sourceMappingURL=fastify.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.cjs","names":["setCookieAdditions","headerLines","toWebHeaders"],"sources":["../src/fastify-platform.ts"],"sourcesContent":["import type { IncomingHttpHeaders, IncomingMessage } from \"node:http\";\nimport type { AbstractHttpAdapter } from \"@nestjs/core\";\nimport type {\n CookieSink,\n ExtensionRef,\n FastifyPlatformOptions,\n HttpPlatform,\n HttpRequestAccessor,\n PlatformMountContext,\n PlatformPrepareContext,\n} from \"./auth-contracts.js\";\nimport { toWebHeaders } from \"./platform.js\";\nimport { headerLines, setCookieAdditions } from \"./set-cookies.js\";\n\ninterface RawReplyLike {\n headersSent?: boolean;\n destroyed?: boolean;\n writableEnded?: boolean;\n writableFinished?: boolean;\n once(event: \"close\", listener: () => void): unknown;\n once(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener(event: \"close\", listener: () => void): unknown;\n removeListener(event: \"error\", listener: (error: Error) => void): unknown;\n}\n\ninterface FastifyReplyLike {\n readonly raw: RawReplyLike;\n readonly request: FastifyRequestLike;\n readonly sent: boolean;\n code(status: number): FastifyReplyLike;\n header(name: string, value: string | readonly string[]): FastifyReplyLike;\n getHeader(name: string): string | number | readonly string[] | undefined;\n removeHeader(name: string): FastifyReplyLike;\n send(payload?: unknown): unknown;\n}\n\ninterface FastifyRequestLike {\n readonly body?: unknown;\n readonly headers: IncomingHttpHeaders;\n readonly host: string;\n readonly ip?: string;\n readonly method: string;\n readonly originalUrl: string;\n readonly params?: unknown;\n readonly protocol: string;\n readonly raw: IncomingMessage;\n}\n\ninterface FastifyInstanceLike {\n readonly errorHandler: (\n this: FastifyInstanceLike,\n error: unknown,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => unknown;\n readonly supportedMethods: readonly string[];\n addContentTypeParser(\n contentType: string,\n options: { readonly parseAs: \"buffer\"; readonly bodyLimit: number },\n parser: (\n request: FastifyRequestLike,\n body: Buffer,\n done: (error: Error | null, value?: Buffer) => void,\n ) => void,\n ): unknown;\n addHook(\n name: \"onRequest\",\n hook: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: (error?: Error) => void,\n ) => void,\n ): unknown;\n register(\n plugin: (scope: FastifyInstanceLike) => void | Promise<void>,\n options: { readonly prefix: string },\n ): PromiseLike<unknown>;\n removeAllContentTypeParsers(): unknown;\n route(options: {\n readonly method: readonly string[];\n readonly url: string;\n readonly exposeHeadRoute: false;\n readonly handler: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => Promise<unknown>;\n }): unknown;\n setErrorHandler(\n handler: (\n this: FastifyInstanceLike,\n error: unknown,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => unknown,\n ): unknown;\n}\n\nfunction instanceOf(adapter: AbstractHttpAdapter): FastifyInstanceLike {\n return adapter.getInstance() as FastifyInstanceLike;\n}\n\nfunction asRequest(value: unknown): FastifyRequestLike | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const request = value as Partial<FastifyRequestLike>;\n return typeof request.raw === \"object\" && request.raw !== null\n ? (request as FastifyRequestLike)\n : undefined;\n}\n\nfunction varyParts(value: string | number | readonly string[] | undefined) {\n const values = Array.isArray(value)\n ? value\n : value === undefined\n ? []\n : [value];\n return values.flatMap((item) => String(item).split(\",\"));\n}\n\nfunction mergedVary(\n current: string | number | readonly string[] | undefined,\n added: string,\n): string {\n const values = [...varyParts(current), ...varyParts(added)]\n .map((item) => item.trim())\n .filter(Boolean);\n if (values.includes(\"*\")) {\n return \"*\";\n }\n const seen = new Set<string>();\n return values\n .filter((item) => {\n const key = item.toLowerCase();\n if (seen.has(key)) {\n return false;\n }\n seen.add(key);\n return true;\n })\n .join(\", \");\n}\n\nfunction abortOnDisconnect(\n request: IncomingMessage,\n response: RawReplyLike,\n): { readonly signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n let disposed = false;\n const abort = () => {\n if (!controller.signal.aborted) {\n controller.abort();\n }\n };\n const onRequestAborted = () => abort();\n const onRequestError = () => abort();\n const onResponseClose = () => {\n if (!response.writableFinished) {\n abort();\n }\n };\n const onResponseError = () => abort();\n const dispose = () => {\n if (disposed) {\n return;\n }\n disposed = true;\n request.removeListener(\"aborted\", onRequestAborted);\n request.removeListener(\"error\", onRequestError);\n response.removeListener(\"close\", onResponseClose);\n response.removeListener(\"error\", onResponseError);\n };\n\n request.once(\"aborted\", onRequestAborted);\n request.once(\"error\", onRequestError);\n response.once(\"close\", onResponseClose);\n response.once(\"error\", onResponseError);\n if (\n request.aborted ||\n response.destroyed ||\n (request.socket.destroyed && !response.writableFinished)\n ) {\n abort();\n }\n return { signal: controller.signal, dispose };\n}\n\nfunction appendReplyCookies(\n reply: FastifyReplyLike,\n cookies: readonly string[],\n): void {\n for (const cookie of setCookieAdditions(\n headerLines(reply.getHeader(\"set-cookie\")),\n cookies,\n )) {\n reply.header(\"set-cookie\", cookie);\n }\n}\n\nasync function sendWebResponse(\n reply: FastifyReplyLike,\n response: Response,\n head: boolean,\n): Promise<unknown> {\n reply.code(response.status);\n for (const [name, value] of response.headers) {\n if (name === \"set-cookie\") {\n continue;\n }\n reply.header(\n name,\n name === \"vary\" ? mergedVary(reply.getHeader(name), value) : value,\n );\n }\n appendReplyCookies(reply, response.headers.getSetCookie());\n if (reply.request.raw.httpVersionMajor === 2) {\n for (const name of [\n \"connection\",\n \"keep-alive\",\n \"proxy-connection\",\n \"transfer-encoding\",\n \"upgrade\",\n ]) {\n reply.removeHeader(name);\n }\n }\n if (head && response.body !== null) {\n await response.body.cancel().catch(() => undefined);\n }\n return reply.send(head ? undefined : (response.body ?? undefined));\n}\n\n/**\n * Fastify's encapsulated auth-route platform adapter.\n *\n * Fastify applies `trustProxy` to `request.ip`, but does not expose that option\n * through its public instance metadata. Proxy-trust reporting is therefore\n * intentionally unavailable instead of guessing a diagnostic mode.\n */\nexport class FastifyPlatform implements HttpPlatform {\n readonly id = \"fastify\";\n readonly capabilities = { http2: true, prepareAtInit: true } as const;\n readonly requests: HttpRequestAccessor;\n #replies = new WeakMap<object, FastifyReplyLike>();\n\n constructor(private readonly options: FastifyPlatformOptions = {}) {\n this.requests = {\n isRequest: (value) => {\n const request = asRequest(value);\n return request !== undefined && this.#replies.has(request.raw);\n },\n isLive: (value) => {\n const request = asRequest(value);\n const reply = request && this.#replies.get(request.raw);\n return reply !== undefined && !reply.sent;\n },\n key: (value) => {\n const request = asRequest(value);\n return request?.raw ?? (value as object);\n },\n headers: (value) => {\n const request = asRequest(value);\n return request ? toWebHeaders(request.raw.headers) : new Headers();\n },\n request: (value) => {\n const request = asRequest(value);\n if (!request) {\n return { method: \"GET\", url: \"\" };\n }\n return {\n method: request.method,\n url: `${request.protocol}://${request.host}${request.originalUrl}`,\n };\n },\n clientIp: (value) => {\n const request = asRequest(value);\n return request\n ? (this.options.clientIp?.(request) ?? request.ip ?? null)\n : null;\n },\n param: (value, name) => {\n const request = asRequest(value);\n if (\n !request ||\n typeof request.params !== \"object\" ||\n request.params === null\n ) {\n return undefined;\n }\n const parameter = Reflect.get(request.params, name);\n return typeof parameter === \"string\" ? parameter : undefined;\n },\n cookieSink: (value, response) => {\n const request = asRequest(value);\n if (!request) {\n return null;\n }\n const supplied = response as Partial<FastifyReplyLike> | null;\n const reply =\n supplied &&\n typeof supplied.header === \"function\" &&\n typeof supplied.sent === \"boolean\"\n ? (supplied as FastifyReplyLike)\n : this.#replies.get(request.raw);\n if (!reply) {\n return null;\n }\n const sink: CookieSink = {\n append: (cookies) => {\n if (reply.sent || reply.raw.headersSent) {\n return false;\n }\n appendReplyCookies(reply, cookies);\n return true;\n },\n };\n return sink;\n },\n responseFor: (value) => {\n const request = asRequest(value);\n return request ? this.#replies.get(request.raw) : undefined;\n },\n };\n }\n\n supports(adapter: AbstractHttpAdapter): boolean {\n return adapter.getType() === \"fastify\";\n }\n\n prepare(context: PlatformPrepareContext): void {\n const root = instanceOf(context.adapter);\n this.#replies = new WeakMap<object, FastifyReplyLike>();\n root.addHook(\"onRequest\", (request, reply, done) => {\n this.#replies.set(request.raw, reply);\n done();\n });\n }\n\n async mount(context: PlatformMountContext): Promise<void> {\n const root = instanceOf(context.adapter);\n const { binding } = context;\n await root.register(\n async (scope) => {\n scope.removeAllContentTypeParsers();\n scope.addContentTypeParser(\n \"*\",\n { parseAs: \"buffer\", bodyLimit: binding.bodyLimit },\n (_request, body, done) => done(null, body),\n );\n scope.setErrorHandler(function (error, request, reply) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n Reflect.get(error, \"code\") === \"FST_ERR_CTP_BODY_TOO_LARGE\"\n ) {\n return sendWebResponse(reply, binding.payloadTooLarge(), false);\n }\n return root.errorHandler.call(this, error, request, reply);\n });\n const handler = async (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => {\n const cancellation = abortOnDisconnect(request.raw, reply.raw);\n try {\n const response = await binding.handle({\n method: request.method,\n url: `${request.protocol}://${request.host}${request.originalUrl}`,\n headers: toWebHeaders(request.raw.headers),\n body: request.body instanceof Uint8Array ? request.body : null,\n clientIp: this.options.clientIp?.(request) ?? request.ip ?? null,\n platformRequest: request,\n signal: cancellation.signal,\n });\n if (cancellation.signal.aborted) {\n return undefined;\n }\n return await sendWebResponse(\n reply,\n response,\n request.method.toUpperCase() === \"HEAD\",\n );\n } catch (error) {\n if (cancellation.signal.aborted) {\n return undefined;\n }\n throw error;\n } finally {\n cancellation.dispose();\n }\n };\n const methods = [...scope.supportedMethods];\n scope.route({\n method: methods,\n url: \"/\",\n handler,\n exposeHeadRoute: false,\n });\n scope.route({\n method: methods,\n url: \"/*\",\n handler,\n exposeHeadRoute: false,\n });\n },\n { prefix: binding.basePath },\n );\n }\n}\n\nexport function fastifyPlatform(\n options?: FastifyPlatformOptions,\n): ExtensionRef<HttpPlatform> {\n return new FastifyPlatform(options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { I as ExtensionRef, J as PlatformMountContext, L as FastifyPlatformOptions, U as HttpPlatform, W as HttpRequestAccessor, Y as PlatformPrepareContext } from "./auth-contracts-Brh_Qko9.cjs";
2
+ import { AbstractHttpAdapter } from "@nestjs/core";
3
+ //#region src/fastify-platform.d.ts
4
+ /**
5
+ * Fastify's encapsulated auth-route platform adapter.
6
+ *
7
+ * Fastify applies `trustProxy` to `request.ip`, but does not expose that option
8
+ * through its public instance metadata. Proxy-trust reporting is therefore
9
+ * intentionally unavailable instead of guessing a diagnostic mode.
10
+ */
11
+ export declare class FastifyPlatform implements HttpPlatform {
12
+ #private;
13
+ private readonly options;
14
+ readonly id = "fastify";
15
+ readonly capabilities: {
16
+ readonly http2: true;
17
+ readonly prepareAtInit: true;
18
+ };
19
+ readonly requests: HttpRequestAccessor;
20
+ constructor(options?: FastifyPlatformOptions);
21
+ supports(adapter: AbstractHttpAdapter): boolean;
22
+ prepare(context: PlatformPrepareContext): void;
23
+ mount(context: PlatformMountContext): Promise<void>;
24
+ }
25
+ export declare function fastifyPlatform(options?: FastifyPlatformOptions): ExtensionRef<HttpPlatform>;
26
+ //#endregion
27
+ export type { FastifyPlatformOptions };
28
+ //# sourceMappingURL=fastify.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.cts","names":[],"sources":["../src/fastify-platform.ts"],"mappings":";;;;;;;;;;qBA+Oa,2BAA2B;;mBAMT;WALpB;WACA;aAAiB;aAAa;;WAC9B,UAAU;EAGnB,YAA6B,UAAS;EAgFtC,SAAS,SAAS;EAIlB,QAAQ,SAAS;EASX,MAAM,SAAS,uBAAuB;;wBAwE9B,gBACd,UAAU,yBACT,aAAa"}
@@ -0,0 +1,28 @@
1
+ import { I as ExtensionRef, J as PlatformMountContext, L as FastifyPlatformOptions, U as HttpPlatform, W as HttpRequestAccessor, Y as PlatformPrepareContext } from "./auth-contracts-Cz7C4_Ch.mjs";
2
+ import { AbstractHttpAdapter } from "@nestjs/core";
3
+ //#region src/fastify-platform.d.ts
4
+ /**
5
+ * Fastify's encapsulated auth-route platform adapter.
6
+ *
7
+ * Fastify applies `trustProxy` to `request.ip`, but does not expose that option
8
+ * through its public instance metadata. Proxy-trust reporting is therefore
9
+ * intentionally unavailable instead of guessing a diagnostic mode.
10
+ */
11
+ export declare class FastifyPlatform implements HttpPlatform {
12
+ #private;
13
+ private readonly options;
14
+ readonly id = "fastify";
15
+ readonly capabilities: {
16
+ readonly http2: true;
17
+ readonly prepareAtInit: true;
18
+ };
19
+ readonly requests: HttpRequestAccessor;
20
+ constructor(options?: FastifyPlatformOptions);
21
+ supports(adapter: AbstractHttpAdapter): boolean;
22
+ prepare(context: PlatformPrepareContext): void;
23
+ mount(context: PlatformMountContext): Promise<void>;
24
+ }
25
+ export declare function fastifyPlatform(options?: FastifyPlatformOptions): ExtensionRef<HttpPlatform>;
26
+ //#endregion
27
+ export type { FastifyPlatformOptions };
28
+ //# sourceMappingURL=fastify.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.mts","names":[],"sources":["../src/fastify-platform.ts"],"mappings":";;;;;;;;;;qBA+Oa,2BAA2B;;mBAMT;WALpB;WACA;aAAiB;aAAa;;WAC9B,UAAU;EAGnB,YAA6B,UAAS;EAgFtC,SAAS,SAAS;EAIlB,QAAQ,SAAS;EASX,MAAM,SAAS,uBAAuB;;wBAwE9B,gBACd,UAAU,yBACT,aAAa"}
@@ -0,0 +1,216 @@
1
+ import { l as headerLines, o as toWebHeaders, u as setCookieAdditions } from "./platform-CZl7TY8j.mjs";
2
+ //#region src/fastify-platform.ts
3
+ function instanceOf(adapter) {
4
+ return adapter.getInstance();
5
+ }
6
+ function asRequest(value) {
7
+ if (typeof value !== "object" || value === null) return;
8
+ const request = value;
9
+ return typeof request.raw === "object" && request.raw !== null ? request : void 0;
10
+ }
11
+ function varyParts(value) {
12
+ return (Array.isArray(value) ? value : value === void 0 ? [] : [value]).flatMap((item) => String(item).split(","));
13
+ }
14
+ function mergedVary(current, added) {
15
+ const values = [...varyParts(current), ...varyParts(added)].map((item) => item.trim()).filter(Boolean);
16
+ if (values.includes("*")) return "*";
17
+ const seen = /* @__PURE__ */ new Set();
18
+ return values.filter((item) => {
19
+ const key = item.toLowerCase();
20
+ if (seen.has(key)) return false;
21
+ seen.add(key);
22
+ return true;
23
+ }).join(", ");
24
+ }
25
+ function abortOnDisconnect(request, response) {
26
+ const controller = new AbortController();
27
+ let disposed = false;
28
+ const abort = () => {
29
+ if (!controller.signal.aborted) controller.abort();
30
+ };
31
+ const onRequestAborted = () => abort();
32
+ const onRequestError = () => abort();
33
+ const onResponseClose = () => {
34
+ if (!response.writableFinished) abort();
35
+ };
36
+ const onResponseError = () => abort();
37
+ const dispose = () => {
38
+ if (disposed) return;
39
+ disposed = true;
40
+ request.removeListener("aborted", onRequestAborted);
41
+ request.removeListener("error", onRequestError);
42
+ response.removeListener("close", onResponseClose);
43
+ response.removeListener("error", onResponseError);
44
+ };
45
+ request.once("aborted", onRequestAborted);
46
+ request.once("error", onRequestError);
47
+ response.once("close", onResponseClose);
48
+ response.once("error", onResponseError);
49
+ if (request.aborted || response.destroyed || request.socket.destroyed && !response.writableFinished) abort();
50
+ return {
51
+ signal: controller.signal,
52
+ dispose
53
+ };
54
+ }
55
+ function appendReplyCookies(reply, cookies) {
56
+ for (const cookie of setCookieAdditions(headerLines(reply.getHeader("set-cookie")), cookies)) reply.header("set-cookie", cookie);
57
+ }
58
+ async function sendWebResponse(reply, response, head) {
59
+ reply.code(response.status);
60
+ for (const [name, value] of response.headers) {
61
+ if (name === "set-cookie") continue;
62
+ reply.header(name, name === "vary" ? mergedVary(reply.getHeader(name), value) : value);
63
+ }
64
+ appendReplyCookies(reply, response.headers.getSetCookie());
65
+ if (reply.request.raw.httpVersionMajor === 2) for (const name of [
66
+ "connection",
67
+ "keep-alive",
68
+ "proxy-connection",
69
+ "transfer-encoding",
70
+ "upgrade"
71
+ ]) reply.removeHeader(name);
72
+ if (head && response.body !== null) await response.body.cancel().catch(() => void 0);
73
+ return reply.send(head ? void 0 : response.body ?? void 0);
74
+ }
75
+ /**
76
+ * Fastify's encapsulated auth-route platform adapter.
77
+ *
78
+ * Fastify applies `trustProxy` to `request.ip`, but does not expose that option
79
+ * through its public instance metadata. Proxy-trust reporting is therefore
80
+ * intentionally unavailable instead of guessing a diagnostic mode.
81
+ */
82
+ var FastifyPlatform = class {
83
+ options;
84
+ id = "fastify";
85
+ capabilities = {
86
+ http2: true,
87
+ prepareAtInit: true
88
+ };
89
+ requests;
90
+ #replies = /* @__PURE__ */ new WeakMap();
91
+ constructor(options = {}) {
92
+ this.options = options;
93
+ this.requests = {
94
+ isRequest: (value) => {
95
+ const request = asRequest(value);
96
+ return request !== void 0 && this.#replies.has(request.raw);
97
+ },
98
+ isLive: (value) => {
99
+ const request = asRequest(value);
100
+ const reply = request && this.#replies.get(request.raw);
101
+ return reply !== void 0 && !reply.sent;
102
+ },
103
+ key: (value) => {
104
+ return asRequest(value)?.raw ?? value;
105
+ },
106
+ headers: (value) => {
107
+ const request = asRequest(value);
108
+ return request ? toWebHeaders(request.raw.headers) : new Headers();
109
+ },
110
+ request: (value) => {
111
+ const request = asRequest(value);
112
+ if (!request) return {
113
+ method: "GET",
114
+ url: ""
115
+ };
116
+ return {
117
+ method: request.method,
118
+ url: `${request.protocol}://${request.host}${request.originalUrl}`
119
+ };
120
+ },
121
+ clientIp: (value) => {
122
+ const request = asRequest(value);
123
+ return request ? this.options.clientIp?.(request) ?? request.ip ?? null : null;
124
+ },
125
+ param: (value, name) => {
126
+ const request = asRequest(value);
127
+ if (!request || typeof request.params !== "object" || request.params === null) return;
128
+ const parameter = Reflect.get(request.params, name);
129
+ return typeof parameter === "string" ? parameter : void 0;
130
+ },
131
+ cookieSink: (value, response) => {
132
+ const request = asRequest(value);
133
+ if (!request) return null;
134
+ const supplied = response;
135
+ const reply = supplied && typeof supplied.header === "function" && typeof supplied.sent === "boolean" ? supplied : this.#replies.get(request.raw);
136
+ if (!reply) return null;
137
+ return { append: (cookies) => {
138
+ if (reply.sent || reply.raw.headersSent) return false;
139
+ appendReplyCookies(reply, cookies);
140
+ return true;
141
+ } };
142
+ },
143
+ responseFor: (value) => {
144
+ const request = asRequest(value);
145
+ return request ? this.#replies.get(request.raw) : void 0;
146
+ }
147
+ };
148
+ }
149
+ supports(adapter) {
150
+ return adapter.getType() === "fastify";
151
+ }
152
+ prepare(context) {
153
+ const root = instanceOf(context.adapter);
154
+ this.#replies = /* @__PURE__ */ new WeakMap();
155
+ root.addHook("onRequest", (request, reply, done) => {
156
+ this.#replies.set(request.raw, reply);
157
+ done();
158
+ });
159
+ }
160
+ async mount(context) {
161
+ const root = instanceOf(context.adapter);
162
+ const { binding } = context;
163
+ await root.register(async (scope) => {
164
+ scope.removeAllContentTypeParsers();
165
+ scope.addContentTypeParser("*", {
166
+ parseAs: "buffer",
167
+ bodyLimit: binding.bodyLimit
168
+ }, (_request, body, done) => done(null, body));
169
+ scope.setErrorHandler(function(error, request, reply) {
170
+ if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "FST_ERR_CTP_BODY_TOO_LARGE") return sendWebResponse(reply, binding.payloadTooLarge(), false);
171
+ return root.errorHandler.call(this, error, request, reply);
172
+ });
173
+ const handler = async (request, reply) => {
174
+ const cancellation = abortOnDisconnect(request.raw, reply.raw);
175
+ try {
176
+ const response = await binding.handle({
177
+ method: request.method,
178
+ url: `${request.protocol}://${request.host}${request.originalUrl}`,
179
+ headers: toWebHeaders(request.raw.headers),
180
+ body: request.body instanceof Uint8Array ? request.body : null,
181
+ clientIp: this.options.clientIp?.(request) ?? request.ip ?? null,
182
+ platformRequest: request,
183
+ signal: cancellation.signal
184
+ });
185
+ if (cancellation.signal.aborted) return;
186
+ return await sendWebResponse(reply, response, request.method.toUpperCase() === "HEAD");
187
+ } catch (error) {
188
+ if (cancellation.signal.aborted) return;
189
+ throw error;
190
+ } finally {
191
+ cancellation.dispose();
192
+ }
193
+ };
194
+ const methods = [...scope.supportedMethods];
195
+ scope.route({
196
+ method: methods,
197
+ url: "/",
198
+ handler,
199
+ exposeHeadRoute: false
200
+ });
201
+ scope.route({
202
+ method: methods,
203
+ url: "/*",
204
+ handler,
205
+ exposeHeadRoute: false
206
+ });
207
+ }, { prefix: binding.basePath });
208
+ }
209
+ };
210
+ function fastifyPlatform(options) {
211
+ return new FastifyPlatform(options);
212
+ }
213
+ //#endregion
214
+ export { FastifyPlatform, fastifyPlatform };
215
+
216
+ //# sourceMappingURL=fastify.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.mjs","names":[],"sources":["../src/fastify-platform.ts"],"sourcesContent":["import type { IncomingHttpHeaders, IncomingMessage } from \"node:http\";\nimport type { AbstractHttpAdapter } from \"@nestjs/core\";\nimport type {\n CookieSink,\n ExtensionRef,\n FastifyPlatformOptions,\n HttpPlatform,\n HttpRequestAccessor,\n PlatformMountContext,\n PlatformPrepareContext,\n} from \"./auth-contracts.js\";\nimport { toWebHeaders } from \"./platform.js\";\nimport { headerLines, setCookieAdditions } from \"./set-cookies.js\";\n\ninterface RawReplyLike {\n headersSent?: boolean;\n destroyed?: boolean;\n writableEnded?: boolean;\n writableFinished?: boolean;\n once(event: \"close\", listener: () => void): unknown;\n once(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener(event: \"close\", listener: () => void): unknown;\n removeListener(event: \"error\", listener: (error: Error) => void): unknown;\n}\n\ninterface FastifyReplyLike {\n readonly raw: RawReplyLike;\n readonly request: FastifyRequestLike;\n readonly sent: boolean;\n code(status: number): FastifyReplyLike;\n header(name: string, value: string | readonly string[]): FastifyReplyLike;\n getHeader(name: string): string | number | readonly string[] | undefined;\n removeHeader(name: string): FastifyReplyLike;\n send(payload?: unknown): unknown;\n}\n\ninterface FastifyRequestLike {\n readonly body?: unknown;\n readonly headers: IncomingHttpHeaders;\n readonly host: string;\n readonly ip?: string;\n readonly method: string;\n readonly originalUrl: string;\n readonly params?: unknown;\n readonly protocol: string;\n readonly raw: IncomingMessage;\n}\n\ninterface FastifyInstanceLike {\n readonly errorHandler: (\n this: FastifyInstanceLike,\n error: unknown,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => unknown;\n readonly supportedMethods: readonly string[];\n addContentTypeParser(\n contentType: string,\n options: { readonly parseAs: \"buffer\"; readonly bodyLimit: number },\n parser: (\n request: FastifyRequestLike,\n body: Buffer,\n done: (error: Error | null, value?: Buffer) => void,\n ) => void,\n ): unknown;\n addHook(\n name: \"onRequest\",\n hook: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: (error?: Error) => void,\n ) => void,\n ): unknown;\n register(\n plugin: (scope: FastifyInstanceLike) => void | Promise<void>,\n options: { readonly prefix: string },\n ): PromiseLike<unknown>;\n removeAllContentTypeParsers(): unknown;\n route(options: {\n readonly method: readonly string[];\n readonly url: string;\n readonly exposeHeadRoute: false;\n readonly handler: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => Promise<unknown>;\n }): unknown;\n setErrorHandler(\n handler: (\n this: FastifyInstanceLike,\n error: unknown,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => unknown,\n ): unknown;\n}\n\nfunction instanceOf(adapter: AbstractHttpAdapter): FastifyInstanceLike {\n return adapter.getInstance() as FastifyInstanceLike;\n}\n\nfunction asRequest(value: unknown): FastifyRequestLike | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const request = value as Partial<FastifyRequestLike>;\n return typeof request.raw === \"object\" && request.raw !== null\n ? (request as FastifyRequestLike)\n : undefined;\n}\n\nfunction varyParts(value: string | number | readonly string[] | undefined) {\n const values = Array.isArray(value)\n ? value\n : value === undefined\n ? []\n : [value];\n return values.flatMap((item) => String(item).split(\",\"));\n}\n\nfunction mergedVary(\n current: string | number | readonly string[] | undefined,\n added: string,\n): string {\n const values = [...varyParts(current), ...varyParts(added)]\n .map((item) => item.trim())\n .filter(Boolean);\n if (values.includes(\"*\")) {\n return \"*\";\n }\n const seen = new Set<string>();\n return values\n .filter((item) => {\n const key = item.toLowerCase();\n if (seen.has(key)) {\n return false;\n }\n seen.add(key);\n return true;\n })\n .join(\", \");\n}\n\nfunction abortOnDisconnect(\n request: IncomingMessage,\n response: RawReplyLike,\n): { readonly signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n let disposed = false;\n const abort = () => {\n if (!controller.signal.aborted) {\n controller.abort();\n }\n };\n const onRequestAborted = () => abort();\n const onRequestError = () => abort();\n const onResponseClose = () => {\n if (!response.writableFinished) {\n abort();\n }\n };\n const onResponseError = () => abort();\n const dispose = () => {\n if (disposed) {\n return;\n }\n disposed = true;\n request.removeListener(\"aborted\", onRequestAborted);\n request.removeListener(\"error\", onRequestError);\n response.removeListener(\"close\", onResponseClose);\n response.removeListener(\"error\", onResponseError);\n };\n\n request.once(\"aborted\", onRequestAborted);\n request.once(\"error\", onRequestError);\n response.once(\"close\", onResponseClose);\n response.once(\"error\", onResponseError);\n if (\n request.aborted ||\n response.destroyed ||\n (request.socket.destroyed && !response.writableFinished)\n ) {\n abort();\n }\n return { signal: controller.signal, dispose };\n}\n\nfunction appendReplyCookies(\n reply: FastifyReplyLike,\n cookies: readonly string[],\n): void {\n for (const cookie of setCookieAdditions(\n headerLines(reply.getHeader(\"set-cookie\")),\n cookies,\n )) {\n reply.header(\"set-cookie\", cookie);\n }\n}\n\nasync function sendWebResponse(\n reply: FastifyReplyLike,\n response: Response,\n head: boolean,\n): Promise<unknown> {\n reply.code(response.status);\n for (const [name, value] of response.headers) {\n if (name === \"set-cookie\") {\n continue;\n }\n reply.header(\n name,\n name === \"vary\" ? mergedVary(reply.getHeader(name), value) : value,\n );\n }\n appendReplyCookies(reply, response.headers.getSetCookie());\n if (reply.request.raw.httpVersionMajor === 2) {\n for (const name of [\n \"connection\",\n \"keep-alive\",\n \"proxy-connection\",\n \"transfer-encoding\",\n \"upgrade\",\n ]) {\n reply.removeHeader(name);\n }\n }\n if (head && response.body !== null) {\n await response.body.cancel().catch(() => undefined);\n }\n return reply.send(head ? undefined : (response.body ?? undefined));\n}\n\n/**\n * Fastify's encapsulated auth-route platform adapter.\n *\n * Fastify applies `trustProxy` to `request.ip`, but does not expose that option\n * through its public instance metadata. Proxy-trust reporting is therefore\n * intentionally unavailable instead of guessing a diagnostic mode.\n */\nexport class FastifyPlatform implements HttpPlatform {\n readonly id = \"fastify\";\n readonly capabilities = { http2: true, prepareAtInit: true } as const;\n readonly requests: HttpRequestAccessor;\n #replies = new WeakMap<object, FastifyReplyLike>();\n\n constructor(private readonly options: FastifyPlatformOptions = {}) {\n this.requests = {\n isRequest: (value) => {\n const request = asRequest(value);\n return request !== undefined && this.#replies.has(request.raw);\n },\n isLive: (value) => {\n const request = asRequest(value);\n const reply = request && this.#replies.get(request.raw);\n return reply !== undefined && !reply.sent;\n },\n key: (value) => {\n const request = asRequest(value);\n return request?.raw ?? (value as object);\n },\n headers: (value) => {\n const request = asRequest(value);\n return request ? toWebHeaders(request.raw.headers) : new Headers();\n },\n request: (value) => {\n const request = asRequest(value);\n if (!request) {\n return { method: \"GET\", url: \"\" };\n }\n return {\n method: request.method,\n url: `${request.protocol}://${request.host}${request.originalUrl}`,\n };\n },\n clientIp: (value) => {\n const request = asRequest(value);\n return request\n ? (this.options.clientIp?.(request) ?? request.ip ?? null)\n : null;\n },\n param: (value, name) => {\n const request = asRequest(value);\n if (\n !request ||\n typeof request.params !== \"object\" ||\n request.params === null\n ) {\n return undefined;\n }\n const parameter = Reflect.get(request.params, name);\n return typeof parameter === \"string\" ? parameter : undefined;\n },\n cookieSink: (value, response) => {\n const request = asRequest(value);\n if (!request) {\n return null;\n }\n const supplied = response as Partial<FastifyReplyLike> | null;\n const reply =\n supplied &&\n typeof supplied.header === \"function\" &&\n typeof supplied.sent === \"boolean\"\n ? (supplied as FastifyReplyLike)\n : this.#replies.get(request.raw);\n if (!reply) {\n return null;\n }\n const sink: CookieSink = {\n append: (cookies) => {\n if (reply.sent || reply.raw.headersSent) {\n return false;\n }\n appendReplyCookies(reply, cookies);\n return true;\n },\n };\n return sink;\n },\n responseFor: (value) => {\n const request = asRequest(value);\n return request ? this.#replies.get(request.raw) : undefined;\n },\n };\n }\n\n supports(adapter: AbstractHttpAdapter): boolean {\n return adapter.getType() === \"fastify\";\n }\n\n prepare(context: PlatformPrepareContext): void {\n const root = instanceOf(context.adapter);\n this.#replies = new WeakMap<object, FastifyReplyLike>();\n root.addHook(\"onRequest\", (request, reply, done) => {\n this.#replies.set(request.raw, reply);\n done();\n });\n }\n\n async mount(context: PlatformMountContext): Promise<void> {\n const root = instanceOf(context.adapter);\n const { binding } = context;\n await root.register(\n async (scope) => {\n scope.removeAllContentTypeParsers();\n scope.addContentTypeParser(\n \"*\",\n { parseAs: \"buffer\", bodyLimit: binding.bodyLimit },\n (_request, body, done) => done(null, body),\n );\n scope.setErrorHandler(function (error, request, reply) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n Reflect.get(error, \"code\") === \"FST_ERR_CTP_BODY_TOO_LARGE\"\n ) {\n return sendWebResponse(reply, binding.payloadTooLarge(), false);\n }\n return root.errorHandler.call(this, error, request, reply);\n });\n const handler = async (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => {\n const cancellation = abortOnDisconnect(request.raw, reply.raw);\n try {\n const response = await binding.handle({\n method: request.method,\n url: `${request.protocol}://${request.host}${request.originalUrl}`,\n headers: toWebHeaders(request.raw.headers),\n body: request.body instanceof Uint8Array ? request.body : null,\n clientIp: this.options.clientIp?.(request) ?? request.ip ?? null,\n platformRequest: request,\n signal: cancellation.signal,\n });\n if (cancellation.signal.aborted) {\n return undefined;\n }\n return await sendWebResponse(\n reply,\n response,\n request.method.toUpperCase() === \"HEAD\",\n );\n } catch (error) {\n if (cancellation.signal.aborted) {\n return undefined;\n }\n throw error;\n } finally {\n cancellation.dispose();\n }\n };\n const methods = [...scope.supportedMethods];\n scope.route({\n method: methods,\n url: \"/\",\n handler,\n exposeHeadRoute: false,\n });\n scope.route({\n method: methods,\n url: \"/*\",\n handler,\n exposeHeadRoute: false,\n });\n },\n { prefix: binding.basePath },\n );\n }\n}\n\nexport function fastifyPlatform(\n options?: FastifyPlatformOptions,\n): ExtensionRef<HttpPlatform> {\n return new FastifyPlatform(options);\n}\n"],"mappings":"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"}