@lupinum/better-convex-nuxt 0.8.0-beta.40

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 (268) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/Apache-2.0.txt +201 -0
  3. package/README.md +151 -0
  4. package/THIRD_PARTY_NOTICES.md +38 -0
  5. package/dist/module.d.mts +55 -0
  6. package/dist/module.json +12 -0
  7. package/dist/module.mjs +309 -0
  8. package/dist/runtime/auth/auth-identity.d.ts +31 -0
  9. package/dist/runtime/auth/auth-identity.js +21 -0
  10. package/dist/runtime/auth/better-auth-browser-adapter.d.ts +33 -0
  11. package/dist/runtime/auth/better-auth-browser-adapter.js +215 -0
  12. package/dist/runtime/auth/client-engine-types.d.ts +4 -0
  13. package/dist/runtime/auth/client-engine-types.js +0 -0
  14. package/dist/runtime/auth/integrated-client.d.ts +25 -0
  15. package/dist/runtime/auth/integrated-client.js +132 -0
  16. package/dist/runtime/auth/operation-tracker.d.ts +7 -0
  17. package/dist/runtime/auth/operation-tracker.js +14 -0
  18. package/dist/runtime/auth/session-synchronization.d.ts +23 -0
  19. package/dist/runtime/auth/session-synchronization.js +156 -0
  20. package/dist/runtime/auth/token-fetcher.d.ts +66 -0
  21. package/dist/runtime/auth/token-fetcher.js +131 -0
  22. package/dist/runtime/auth/validate-auth-client-definition.d.ts +12 -0
  23. package/dist/runtime/auth/validate-auth-client-definition.js +47 -0
  24. package/dist/runtime/auth-client/convex-client-plugin.d.ts +31 -0
  25. package/dist/runtime/auth-client/convex-client-plugin.js +14 -0
  26. package/dist/runtime/auth-client/definition-types.d.ts +6 -0
  27. package/dist/runtime/auth-client/definition-types.js +0 -0
  28. package/dist/runtime/auth-client/empty-definition.d.ts +2 -0
  29. package/dist/runtime/auth-client/empty-definition.js +2 -0
  30. package/dist/runtime/auth-client/index.d.ts +71 -0
  31. package/dist/runtime/auth-client/index.js +3 -0
  32. package/dist/runtime/cli/auth-schema.d.ts +2 -0
  33. package/dist/runtime/cli/auth-schema.js +169 -0
  34. package/dist/runtime/cli/convex.d.ts +11 -0
  35. package/dist/runtime/cli/convex.js +274 -0
  36. package/dist/runtime/composables/useConvex.d.ts +4 -0
  37. package/dist/runtime/composables/useConvex.js +9 -0
  38. package/dist/runtime/composables/useConvexAction.d.ts +4 -0
  39. package/dist/runtime/composables/useConvexAction.js +18 -0
  40. package/dist/runtime/composables/useConvexAttachment.d.ts +9 -0
  41. package/dist/runtime/composables/useConvexAttachment.js +14 -0
  42. package/dist/runtime/composables/useConvexAuth.d.ts +10 -0
  43. package/dist/runtime/composables/useConvexAuth.js +37 -0
  44. package/dist/runtime/composables/useConvexConfig.d.ts +12 -0
  45. package/dist/runtime/composables/useConvexConfig.js +7 -0
  46. package/dist/runtime/composables/useConvexConnectionState.d.ts +33 -0
  47. package/dist/runtime/composables/useConvexConnectionState.js +24 -0
  48. package/dist/runtime/composables/useConvexFileUpload.d.ts +169 -0
  49. package/dist/runtime/composables/useConvexFileUpload.js +198 -0
  50. package/dist/runtime/composables/useConvexMutation.d.ts +13 -0
  51. package/dist/runtime/composables/useConvexMutation.js +24 -0
  52. package/dist/runtime/composables/useConvexPaginatedQuery.d.ts +13 -0
  53. package/dist/runtime/composables/useConvexPaginatedQuery.js +256 -0
  54. package/dist/runtime/composables/useConvexQuery.d.ts +19 -0
  55. package/dist/runtime/composables/useConvexQuery.js +308 -0
  56. package/dist/runtime/convex-auth/adapter/create-adapter.d.ts +33 -0
  57. package/dist/runtime/convex-auth/adapter/create-adapter.js +308 -0
  58. package/dist/runtime/convex-auth/adapter/define-functions.d.ts +160 -0
  59. package/dist/runtime/convex-auth/adapter/define-functions.js +497 -0
  60. package/dist/runtime/convex-auth/adapter/generate-schema.d.ts +16 -0
  61. package/dist/runtime/convex-auth/adapter/generate-schema.js +332 -0
  62. package/dist/runtime/convex-auth/adapter/metadata.d.ts +44 -0
  63. package/dist/runtime/convex-auth/adapter/metadata.js +91 -0
  64. package/dist/runtime/convex-auth/adapter/query.d.ts +32 -0
  65. package/dist/runtime/convex-auth/adapter/query.js +275 -0
  66. package/dist/runtime/convex-auth/adapter/relationships.d.ts +20 -0
  67. package/dist/runtime/convex-auth/adapter/relationships.js +128 -0
  68. package/dist/runtime/convex-auth/component/_generated/api.js +5 -0
  69. package/dist/runtime/convex-auth/component/_generated/component.d.ts +116 -0
  70. package/dist/runtime/convex-auth/component/_generated/component.js +0 -0
  71. package/dist/runtime/convex-auth/component/_generated/dataModel.js +0 -0
  72. package/dist/runtime/convex-auth/component/_generated/server.js +16 -0
  73. package/dist/runtime/convex-auth/component/adapter.d.ts +142 -0
  74. package/dist/runtime/convex-auth/component/adapter.js +16 -0
  75. package/dist/runtime/convex-auth/component/convex.config.d.ts +2 -0
  76. package/dist/runtime/convex-auth/component/convex.config.js +3 -0
  77. package/dist/runtime/convex-auth/component/schema.d.ts +799 -0
  78. package/dist/runtime/convex-auth/component/schema.js +180 -0
  79. package/dist/runtime/convex-auth/component/schemaMetadata.d.ts +2094 -0
  80. package/dist/runtime/convex-auth/component/schemaMetadata.js +2161 -0
  81. package/dist/runtime/convex-auth/context.d.ts +5 -0
  82. package/dist/runtime/convex-auth/context.js +8 -0
  83. package/dist/runtime/convex-auth/create-auth-component.d.ts +41 -0
  84. package/dist/runtime/convex-auth/create-auth-component.js +157 -0
  85. package/dist/runtime/convex-auth/index.d.ts +11 -0
  86. package/dist/runtime/convex-auth/index.js +7 -0
  87. package/dist/runtime/convex-auth/internal-session.d.ts +2 -0
  88. package/dist/runtime/convex-auth/internal-session.js +1 -0
  89. package/dist/runtime/convex-auth/jwks-rotation.d.ts +58 -0
  90. package/dist/runtime/convex-auth/jwks-rotation.js +163 -0
  91. package/dist/runtime/convex-auth/oauth-live-access.d.ts +17 -0
  92. package/dist/runtime/convex-auth/oauth-live-access.js +78 -0
  93. package/dist/runtime/convex-auth/oauth-provider-compat.d.ts +10 -0
  94. package/dist/runtime/convex-auth/oauth-provider-compat.js +170 -0
  95. package/dist/runtime/convex-auth/oauth-resource.d.ts +39 -0
  96. package/dist/runtime/convex-auth/oauth-resource.js +118 -0
  97. package/dist/runtime/convex-auth/oauth-security.d.ts +82 -0
  98. package/dist/runtime/convex-auth/oauth-security.js +454 -0
  99. package/dist/runtime/convex-auth/origin.d.ts +4 -0
  100. package/dist/runtime/convex-auth/origin.js +9 -0
  101. package/dist/runtime/convex-auth/plugin.d.ts +18 -0
  102. package/dist/runtime/convex-auth/plugin.js +605 -0
  103. package/dist/runtime/convex-auth/provider.d.ts +2 -0
  104. package/dist/runtime/convex-auth/provider.js +11 -0
  105. package/dist/runtime/convex-auth/test.d.ts +410 -0
  106. package/dist/runtime/convex-auth/test.js +9 -0
  107. package/dist/runtime/convex-auth/types.d.ts +18 -0
  108. package/dist/runtime/convex-auth/types.js +0 -0
  109. package/dist/runtime/convex-auth/user-projection.d.ts +106 -0
  110. package/dist/runtime/convex-auth/user-projection.js +128 -0
  111. package/dist/runtime/devtools/auth-proxy-registry.d.ts +4 -0
  112. package/dist/runtime/devtools/auth-proxy-registry.js +47 -0
  113. package/dist/runtime/devtools/bridge-setup.d.ts +21 -0
  114. package/dist/runtime/devtools/bridge-setup.js +165 -0
  115. package/dist/runtime/devtools/path-utils.d.ts +2 -0
  116. package/dist/runtime/devtools/path-utils.js +12 -0
  117. package/dist/runtime/devtools/server.d.ts +2 -0
  118. package/dist/runtime/devtools/server.js +108 -0
  119. package/dist/runtime/devtools/setup-client.d.ts +16 -0
  120. package/dist/runtime/devtools/setup-client.js +43 -0
  121. package/dist/runtime/devtools/sink.d.ts +18 -0
  122. package/dist/runtime/devtools/sink.js +110 -0
  123. package/dist/runtime/devtools/transport.d.ts +16 -0
  124. package/dist/runtime/devtools/transport.js +149 -0
  125. package/dist/runtime/devtools/types.d.ts +167 -0
  126. package/dist/runtime/devtools/types.js +1 -0
  127. package/dist/runtime/devtools/ui/dist/200.html +1 -0
  128. package/dist/runtime/devtools/ui/dist/404.html +1 -0
  129. package/dist/runtime/devtools/ui/dist/_nuxt/C4MASuCh.js +1 -0
  130. package/dist/runtime/devtools/ui/dist/_nuxt/DJHkqtZq.js +3 -0
  131. package/dist/runtime/devtools/ui/dist/_nuxt/DWwrCltl.js +2 -0
  132. package/dist/runtime/devtools/ui/dist/_nuxt/DZ_UiYoH.js +1 -0
  133. package/dist/runtime/devtools/ui/dist/_nuxt/_m9ujb-i.js +1 -0
  134. package/dist/runtime/devtools/ui/dist/_nuxt/builds/latest.json +1 -0
  135. package/dist/runtime/devtools/ui/dist/_nuxt/builds/meta/better-convex-nuxt-devtools.json +1 -0
  136. package/dist/runtime/devtools/ui/dist/_nuxt/entry.DpFDKYZ5.css +1 -0
  137. package/dist/runtime/devtools/ui/dist/_nuxt/error-404.DYUJo5xt.css +1 -0
  138. package/dist/runtime/devtools/ui/dist/_nuxt/error-500.DQdoJJXg.css +1 -0
  139. package/dist/runtime/devtools/ui/dist/convex-logo.svg +5 -0
  140. package/dist/runtime/devtools/ui/dist/index.html +1 -0
  141. package/dist/runtime/errors/index.d.ts +7 -0
  142. package/dist/runtime/errors/index.js +5 -0
  143. package/dist/runtime/middleware/convex-auth.global.d.ts +2 -0
  144. package/dist/runtime/middleware/convex-auth.global.js +31 -0
  145. package/dist/runtime/plugin.auth.client.d.ts +3 -0
  146. package/dist/runtime/plugin.auth.client.js +217 -0
  147. package/dist/runtime/plugin.client.d.ts +3 -0
  148. package/dist/runtime/plugin.client.js +43 -0
  149. package/dist/runtime/plugin.server.d.ts +12 -0
  150. package/dist/runtime/plugin.server.js +98 -0
  151. package/dist/runtime/plugins/convex-call-error-payload.d.ts +14 -0
  152. package/dist/runtime/plugins/convex-call-error-payload.js +12 -0
  153. package/dist/runtime/runtime-context.d.ts +26 -0
  154. package/dist/runtime/runtime-context.js +48 -0
  155. package/dist/runtime/server/api/auth/[...].d.ts +10 -0
  156. package/dist/runtime/server/api/auth/[...].js +509 -0
  157. package/dist/runtime/server/api/auth/authorization-server-metadata.d.ts +2 -0
  158. package/dist/runtime/server/api/auth/authorization-server-metadata.js +6 -0
  159. package/dist/runtime/server/api/auth/body-size.d.ts +15 -0
  160. package/dist/runtime/server/api/auth/body-size.js +179 -0
  161. package/dist/runtime/server/api/auth/headers.d.ts +6 -0
  162. package/dist/runtime/server/api/auth/headers.js +98 -0
  163. package/dist/runtime/server/api/auth/jwks.d.ts +2 -0
  164. package/dist/runtime/server/api/auth/jwks.js +6 -0
  165. package/dist/runtime/server/api/auth/security.d.ts +14 -0
  166. package/dist/runtime/server/api/auth/security.js +85 -0
  167. package/dist/runtime/server/api/release-fingerprint.d.ts +2 -0
  168. package/dist/runtime/server/api/release-fingerprint.js +36 -0
  169. package/dist/runtime/server/index.d.ts +1 -0
  170. package/dist/runtime/server/index.js +3 -0
  171. package/dist/runtime/server/plugins/runtime-config.d.ts +7 -0
  172. package/dist/runtime/server/plugins/runtime-config.js +7 -0
  173. package/dist/runtime/server/utils/auth-snapshot.d.ts +26 -0
  174. package/dist/runtime/server/utils/auth-snapshot.js +165 -0
  175. package/dist/runtime/server/utils/http.d.ts +16 -0
  176. package/dist/runtime/server/utils/http.js +133 -0
  177. package/dist/runtime/server/utils/server-convex-caller.d.ts +31 -0
  178. package/dist/runtime/server/utils/server-convex-caller.js +151 -0
  179. package/dist/runtime/server/utils/server-convex-options.d.ts +83 -0
  180. package/dist/runtime/server/utils/server-convex-options.js +69 -0
  181. package/dist/runtime/server/utils/signed-client-ip.d.ts +6 -0
  182. package/dist/runtime/server/utils/signed-client-ip.js +29 -0
  183. package/dist/runtime/server/utils/ssr-auth-headers.d.ts +26 -0
  184. package/dist/runtime/server/utils/ssr-auth-headers.js +49 -0
  185. package/dist/runtime/server/utils/token-exchange.d.ts +27 -0
  186. package/dist/runtime/server/utils/token-exchange.js +96 -0
  187. package/dist/runtime/shared/auth-cookie.d.ts +4 -0
  188. package/dist/runtime/shared/auth-cookie.js +25 -0
  189. package/dist/runtime/shared/auth-origin.d.ts +15 -0
  190. package/dist/runtime/shared/auth-origin.js +42 -0
  191. package/dist/runtime/shared/bounded-stream.d.ts +2 -0
  192. package/dist/runtime/shared/bounded-stream.js +50 -0
  193. package/dist/runtime/shared/client-ip.d.ts +21 -0
  194. package/dist/runtime/shared/client-ip.js +123 -0
  195. package/dist/runtime/shared/release-fingerprint.d.ts +5 -0
  196. package/dist/runtime/shared/release-fingerprint.js +17 -0
  197. package/dist/runtime/types.d.ts +19 -0
  198. package/dist/runtime/utils/auth-config.d.ts +24 -0
  199. package/dist/runtime/utils/auth-config.js +45 -0
  200. package/dist/runtime/utils/auth-contract.d.ts +22 -0
  201. package/dist/runtime/utils/auth-contract.js +0 -0
  202. package/dist/runtime/utils/auth-errors.d.ts +5 -0
  203. package/dist/runtime/utils/auth-errors.js +22 -0
  204. package/dist/runtime/utils/auth-identity-state.d.ts +4 -0
  205. package/dist/runtime/utils/auth-identity-state.js +8 -0
  206. package/dist/runtime/utils/auth-pending-state.d.ts +13 -0
  207. package/dist/runtime/utils/auth-pending-state.js +4 -0
  208. package/dist/runtime/utils/auth-pending.d.ts +10 -0
  209. package/dist/runtime/utils/auth-pending.js +30 -0
  210. package/dist/runtime/utils/auth-route-protection.d.ts +16 -0
  211. package/dist/runtime/utils/auth-route-protection.js +58 -0
  212. package/dist/runtime/utils/auth-status.d.ts +47 -0
  213. package/dist/runtime/utils/auth-status.js +8 -0
  214. package/dist/runtime/utils/bounded-convex-fetch.d.ts +18 -0
  215. package/dist/runtime/utils/bounded-convex-fetch.js +152 -0
  216. package/dist/runtime/utils/callable-devtools.d.ts +17 -0
  217. package/dist/runtime/utils/callable-devtools.js +49 -0
  218. package/dist/runtime/utils/callable-observer.d.ts +2 -0
  219. package/dist/runtime/utils/callable-observer.js +1 -0
  220. package/dist/runtime/utils/composable-scope.d.ts +2 -0
  221. package/dist/runtime/utils/composable-scope.js +8 -0
  222. package/dist/runtime/utils/config-defaults.d.ts +8 -0
  223. package/dist/runtime/utils/config-defaults.js +8 -0
  224. package/dist/runtime/utils/convex-cache.d.ts +68 -0
  225. package/dist/runtime/utils/convex-cache.js +47 -0
  226. package/dist/runtime/utils/convex-config.d.ts +16 -0
  227. package/dist/runtime/utils/convex-config.js +50 -0
  228. package/dist/runtime/utils/convex-shared.d.ts +67 -0
  229. package/dist/runtime/utils/convex-shared.js +134 -0
  230. package/dist/runtime/utils/identity-changed-error.d.ts +4 -0
  231. package/dist/runtime/utils/identity-changed-error.js +12 -0
  232. package/dist/runtime/utils/identity-key.d.ts +19 -0
  233. package/dist/runtime/utils/identity-key.js +10 -0
  234. package/dist/runtime/utils/integrated-auth-client.d.ts +5 -0
  235. package/dist/runtime/utils/integrated-auth-client.js +0 -0
  236. package/dist/runtime/utils/logger.d.ts +42 -0
  237. package/dist/runtime/utils/logger.js +190 -0
  238. package/dist/runtime/utils/mime-type.d.ts +33 -0
  239. package/dist/runtime/utils/mime-type.js +10 -0
  240. package/dist/runtime/utils/query-execution-gate.d.ts +47 -0
  241. package/dist/runtime/utils/query-execution-gate.js +63 -0
  242. package/dist/runtime/utils/query-execution.d.ts +8 -0
  243. package/dist/runtime/utils/query-execution.js +19 -0
  244. package/dist/runtime/utils/query-foundation.d.ts +20 -0
  245. package/dist/runtime/utils/query-foundation.js +39 -0
  246. package/dist/runtime/utils/query-state.d.ts +12 -0
  247. package/dist/runtime/utils/query-state.js +12 -0
  248. package/dist/runtime/utils/reactive-args.d.ts +5 -0
  249. package/dist/runtime/utils/reactive-args.js +42 -0
  250. package/dist/runtime/utils/runtime-config-normalize.d.ts +22 -0
  251. package/dist/runtime/utils/runtime-config-normalize.js +28 -0
  252. package/dist/runtime/utils/runtime-config.d.ts +4 -0
  253. package/dist/runtime/utils/runtime-config.js +8 -0
  254. package/dist/runtime/utils/sanitize-diagnostic.d.ts +6 -0
  255. package/dist/runtime/utils/sanitize-diagnostic.js +81 -0
  256. package/dist/runtime/utils/shared-helpers.d.ts +46 -0
  257. package/dist/runtime/utils/shared-helpers.js +139 -0
  258. package/dist/runtime/utils/site-url.d.ts +4 -0
  259. package/dist/runtime/utils/site-url.js +15 -0
  260. package/dist/runtime/utils/ssr-pagination-state.d.ts +3 -0
  261. package/dist/runtime/utils/ssr-pagination-state.js +3 -0
  262. package/dist/runtime/utils/types.d.ts +29 -0
  263. package/dist/runtime/utils/types.js +0 -0
  264. package/dist/runtime/utils/upload-core.d.ts +16 -0
  265. package/dist/runtime/utils/upload-core.js +116 -0
  266. package/dist/types.d.mts +21 -0
  267. package/package.json +253 -0
  268. package/security/upstream-convex-better-auth.json +477 -0
@@ -0,0 +1,509 @@
1
+ import {
2
+ appendResponseHeader,
3
+ createError,
4
+ defineEventHandler,
5
+ getRequestURL,
6
+ send,
7
+ setHeaders,
8
+ setResponseStatus
9
+ } from "h3";
10
+ import { normalizeClientIp } from "../../../shared/client-ip.js";
11
+ import {
12
+ getPackedRuntimeFingerprint,
13
+ PACKED_RUNTIME_FINGERPRINT_HEADER
14
+ } from "../../../shared/release-fingerprint.js";
15
+ import {
16
+ buildAuthProxyUnreachableMessage,
17
+ buildAuthProxyUpstreamStatusMessage,
18
+ buildBlockedOriginMessage,
19
+ buildMissingPublicOriginMessage,
20
+ buildMissingSiteUrlMessage
21
+ } from "../../../utils/auth-errors.js";
22
+ import { createLogger } from "../../../utils/logger.js";
23
+ import { getConvexRuntimeConfig } from "../../../utils/runtime-config.js";
24
+ import { hasSetCookieDomainAttribute, isBetterAuthSetCookie } from "../../../utils/shared-helpers.js";
25
+ import { normalizeConvexSiteUrl } from "../../../utils/site-url.js";
26
+ import { DEFAULT_SERVER_FETCH_TIMEOUT_MS } from "../../utils/http.js";
27
+ import {
28
+ cancelResponseBody,
29
+ DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES,
30
+ DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES,
31
+ getRequestBodySizeError,
32
+ getResponseBodySizeError,
33
+ readRequestBodyWithLimit,
34
+ readResponseBodyWithLimit
35
+ } from "./body-size.js";
36
+ import {
37
+ buildAuthProxyForwardHeaders,
38
+ isSupportedProxyResponseContentEncoding,
39
+ shouldSkipProxyResponseHeader
40
+ } from "./headers.js";
41
+ import {
42
+ OAUTH_TOKEN_CORS_MAX_BODY_BYTES,
43
+ hasPublicAuthCorsCredentials,
44
+ isAllowedPublicOAuthTokenCorsPost,
45
+ isAllowedPublicOAuthTokenCorsPreflight,
46
+ isCrossOriginAuthRequest
47
+ } from "./security.js";
48
+ const AUTH_ROUTE = "/api/auth";
49
+ const ALLOWED_METHODS = /* @__PURE__ */ new Set(["GET", "POST"]);
50
+ const SAFE_CAUGHT_PROXY_FAILURES = /* @__PURE__ */ new Map([
51
+ ["BCN_AUTH_PROXY_COOKIE_DOMAIN_UNSUPPORTED", 502],
52
+ ["BCN_AUTH_PROXY_COOKIE_NAME_UNSUPPORTED", 502],
53
+ ["BCN_AUTH_PROXY_METADATA_COOKIE_REJECTED", 502],
54
+ ["BCN_AUTH_PROXY_REQUEST_BODY_TOO_LARGE", 413],
55
+ ["BCN_AUTH_PROXY_TOKEN_COOKIE_REJECTED", 502],
56
+ ["BCN_AUTH_PROXY_UPSTREAM_BODY_TOO_LARGE", 502],
57
+ ["BCN_AUTH_PROXY_UPSTREAM_ENCODING_UNSUPPORTED", 502],
58
+ ["BCN_AUTH_PROXY_UPSTREAM_STATUS", 502]
59
+ ]);
60
+ function safeCaughtProxyFailure(error) {
61
+ if (!error || typeof error !== "object") return null;
62
+ const statusCode = "statusCode" in error ? error.statusCode : void 0;
63
+ const data = "data" in error ? error.data : void 0;
64
+ const code = data && typeof data === "object" && "code" in data && typeof data.code === "string" ? data.code : void 0;
65
+ if (!code || SAFE_CAUGHT_PROXY_FAILURES.get(code) !== statusCode) return null;
66
+ return { code, statusCode };
67
+ }
68
+ function toError(reason, fallback) {
69
+ return reason instanceof Error ? reason : new Error(fallback);
70
+ }
71
+ function closeRequestConnection(event) {
72
+ if (event.node.res.headersSent) return;
73
+ event.node.res.shouldKeepAlive = false;
74
+ setHeaders(event, { connection: "close" });
75
+ }
76
+ function hasFramedGetBody(headers) {
77
+ if (headers.has("transfer-encoding")) return true;
78
+ const contentLength = headers.get("content-length");
79
+ if (contentLength === null) return false;
80
+ try {
81
+ return BigInt(contentLength.trim()) !== 0n;
82
+ } catch {
83
+ return true;
84
+ }
85
+ }
86
+ function hasUnsupportedRequestContentEncoding(headers) {
87
+ const value = headers.get("content-encoding");
88
+ return value !== null && value.trim().toLowerCase() !== "identity";
89
+ }
90
+ function createAuthProxyLifecycle(event, startedAt) {
91
+ const controller = new AbortController();
92
+ const abort = (reason) => {
93
+ if (!controller.signal.aborted) controller.abort(reason);
94
+ };
95
+ const onRequestAborted = () => abort(new Error("Auth proxy client disconnected"));
96
+ const onRequestClose = () => {
97
+ if (!event.node.req.complete) onRequestAborted();
98
+ };
99
+ const onRequestError = (error) => abort(error);
100
+ const onResponseClose = () => {
101
+ if (!event.node.res.writableFinished) onRequestAborted();
102
+ };
103
+ const onWebAbort = () => abort(toError(event.web?.request?.signal.reason, "Auth proxy client disconnected"));
104
+ event.node.req.once("aborted", onRequestAborted);
105
+ event.node.req.once("close", onRequestClose);
106
+ event.node.req.once("error", onRequestError);
107
+ event.node.res.once("close", onResponseClose);
108
+ event.web?.request?.signal.addEventListener("abort", onWebAbort, { once: true });
109
+ const remainingMs = Math.max(0, DEFAULT_SERVER_FETCH_TIMEOUT_MS - (Date.now() - startedAt));
110
+ const timeout = setTimeout(() => abort(new Error("Auth proxy deadline exceeded")), remainingMs);
111
+ timeout.unref?.();
112
+ return {
113
+ controller,
114
+ cleanup() {
115
+ clearTimeout(timeout);
116
+ event.node.req.off("aborted", onRequestAborted);
117
+ event.node.req.off("close", onRequestClose);
118
+ event.node.req.off("error", onRequestError);
119
+ event.node.res.off("close", onResponseClose);
120
+ event.web?.request?.signal.removeEventListener("abort", onWebAbort);
121
+ }
122
+ };
123
+ }
124
+ async function sendAuthProxyBody(event, body, signal) {
125
+ if (!event.node.res.socket) {
126
+ await send(event, body);
127
+ return;
128
+ }
129
+ await new Promise((resolve, reject) => {
130
+ let settled = false;
131
+ const cleanup = () => {
132
+ signal.removeEventListener("abort", onAbort);
133
+ event.node.res.off("finish", onFinish);
134
+ event.node.res.off("close", onClose);
135
+ event.node.res.off("error", onError);
136
+ };
137
+ const succeed = () => {
138
+ if (settled) return;
139
+ settled = true;
140
+ cleanup();
141
+ resolve();
142
+ };
143
+ const fail = (error) => {
144
+ if (settled) return;
145
+ settled = true;
146
+ cleanup();
147
+ reject(toError(error, "Auth proxy response failed"));
148
+ };
149
+ const onFinish = () => succeed();
150
+ const onClose = () => {
151
+ if (event.node.res.writableFinished) succeed();
152
+ else fail(new Error("Auth proxy client disconnected during download"));
153
+ };
154
+ const onError = (error) => fail(error);
155
+ const onAbort = () => {
156
+ const error = toError(signal.reason, "Auth proxy response was aborted");
157
+ fail(error);
158
+ event.node.res.destroy(error);
159
+ };
160
+ event.node.res.once("finish", onFinish);
161
+ event.node.res.once("close", onClose);
162
+ event.node.res.once("error", onError);
163
+ signal.addEventListener("abort", onAbort, { once: true });
164
+ if (signal.aborted) {
165
+ onAbort();
166
+ return;
167
+ }
168
+ try {
169
+ event.node.res.end(body);
170
+ } catch (error) {
171
+ fail(error);
172
+ }
173
+ });
174
+ }
175
+ async function recordAuthProxyRequestInDev(request) {
176
+ if (!import.meta.dev) return;
177
+ try {
178
+ const { recordAuthProxyRequest } = await import("../../../devtools/auth-proxy-registry.js");
179
+ await recordAuthProxyRequest(request);
180
+ } catch {
181
+ }
182
+ }
183
+ export function createAuthProxyHandler(options = {}) {
184
+ const allowedMethods = new Set(options.allowedMethods ?? ALLOWED_METHODS);
185
+ const fixedAuthPath = options.fixedAuthPath;
186
+ const publicMetadataCors = options.publicMetadataCors === true;
187
+ if (fixedAuthPath !== void 0 && (!fixedAuthPath.startsWith("/") || fixedAuthPath.includes("?"))) {
188
+ throw new TypeError("Auth proxy fixed path must be one absolute path without a query");
189
+ }
190
+ return defineEventHandler(async (event) => {
191
+ setHeaders(event, { "cache-control": "private, no-store" });
192
+ const runtimeFingerprint = getPackedRuntimeFingerprint();
193
+ if (runtimeFingerprint) {
194
+ setHeaders(event, { [PACKED_RUNTIME_FINGERPRINT_HEADER]: runtimeFingerprint });
195
+ }
196
+ if (publicMetadataCors) setHeaders(event, { "access-control-allow-origin": "*" });
197
+ const startedAt = Date.now();
198
+ const requestUrl = getRequestURL(event);
199
+ const config = getConvexRuntimeConfig();
200
+ const auth = config.auth;
201
+ if (auth === false) {
202
+ if (event.method !== "GET" || !event.node.req.complete) closeRequestConnection(event);
203
+ throw createError({ statusCode: 404, message: "Authentication is disabled" });
204
+ }
205
+ const traceEnabled = config.logging === "debug";
206
+ const requestId = import.meta.dev || traceEnabled ? crypto.randomUUID() : "";
207
+ const logger = createLogger(traceEnabled ? "debug" : false);
208
+ const trace = (phase, outcome, details = {}) => {
209
+ if (!traceEnabled) return;
210
+ logger.auth({
211
+ phase,
212
+ outcome,
213
+ details: { component: "auth-proxy", requestId, method: event.method, ...details }
214
+ });
215
+ };
216
+ const rejected = (code, status) => trace("auth-proxy.request.rejected", "error", {
217
+ code,
218
+ durationMs: Date.now() - startedAt,
219
+ status
220
+ });
221
+ trace("auth-proxy.request.started", "success");
222
+ const publicOrigin = auth.origin;
223
+ if (!publicOrigin) {
224
+ if (event.method === "POST") closeRequestConnection(event);
225
+ rejected("BCN_AUTH_PROXY_PUBLIC_ORIGIN_MISSING", 500);
226
+ throw createError({
227
+ statusCode: 500,
228
+ message: buildMissingPublicOriginMessage(),
229
+ data: { code: "BCN_AUTH_PROXY_PUBLIC_ORIGIN_MISSING" }
230
+ });
231
+ }
232
+ const trustedClientIpHeader = publicMetadataCors ? null : auth.trustedClientIpHeader;
233
+ if (trustedClientIpHeader && !normalizeClientIp(event.headers.get(trustedClientIpHeader))) {
234
+ if (event.method === "POST") closeRequestConnection(event);
235
+ rejected("BCN_AUTH_PROXY_CLIENT_IP_INVALID", 400);
236
+ throw createError({
237
+ statusCode: 400,
238
+ message: "Auth proxy request is missing a valid ingress-owned client IP",
239
+ data: { code: "BCN_AUTH_PROXY_CLIENT_IP_INVALID" }
240
+ });
241
+ }
242
+ if (publicMetadataCors && hasPublicAuthCorsCredentials(event.headers)) {
243
+ rejected("BCN_AUTH_PROXY_METADATA_CREDENTIAL_REJECTED", 403);
244
+ throw createError({
245
+ statusCode: 403,
246
+ message: "Public auth metadata does not accept credentials",
247
+ data: { code: "BCN_AUTH_PROXY_METADATA_CREDENTIAL_REJECTED" }
248
+ });
249
+ }
250
+ if ((event.method === "GET" || event.method === "HEAD") && hasFramedGetBody(event.headers)) {
251
+ closeRequestConnection(event);
252
+ rejected("BCN_AUTH_PROXY_GET_BODY_REJECTED", 400);
253
+ throw createError({
254
+ statusCode: 400,
255
+ message: "Auth proxy GET requests must not contain a body",
256
+ data: { code: "BCN_AUTH_PROXY_GET_BODY_REJECTED" }
257
+ });
258
+ }
259
+ if (fixedAuthPath !== void 0 && (requestUrl.search || requestUrl.hash)) {
260
+ rejected("BCN_AUTH_PROXY_METADATA_QUERY_REJECTED", 400);
261
+ throw createError({ statusCode: 400, message: "Auth metadata does not accept a query" });
262
+ }
263
+ const path = fixedAuthPath ?? (requestUrl.pathname.startsWith(AUTH_ROUTE) ? requestUrl.pathname.slice(AUTH_ROUTE.length) || "/" : "/");
264
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
265
+ const hasQuery = Boolean(requestUrl.search || requestUrl.hash);
266
+ const isPublicTokenCorsPreflight = isAllowedPublicOAuthTokenCorsPreflight(
267
+ event.headers,
268
+ event.method,
269
+ publicOrigin,
270
+ normalizedPath,
271
+ hasQuery
272
+ );
273
+ if (isPublicTokenCorsPreflight) {
274
+ setResponseStatus(event, 204);
275
+ setHeaders(event, {
276
+ "access-control-allow-headers": "content-type",
277
+ "access-control-allow-methods": "POST",
278
+ "access-control-allow-origin": "*",
279
+ "access-control-max-age": 300
280
+ });
281
+ trace("auth-proxy.request.completed", "success", {
282
+ durationMs: Date.now() - startedAt,
283
+ status: 204
284
+ });
285
+ await send(event, "");
286
+ return;
287
+ }
288
+ if (!allowedMethods.has(event.method)) {
289
+ closeRequestConnection(event);
290
+ rejected("BCN_AUTH_PROXY_METHOD_REJECTED", 405);
291
+ throw createError({ statusCode: 405, message: "Auth proxy method is not permitted" });
292
+ }
293
+ const isPublicTokenCorsPost = isAllowedPublicOAuthTokenCorsPost(
294
+ event.headers,
295
+ event.method,
296
+ publicOrigin,
297
+ normalizedPath,
298
+ hasQuery
299
+ );
300
+ if (!isPublicTokenCorsPost && !publicMetadataCors && isCrossOriginAuthRequest(event.headers, event.method, publicOrigin, normalizedPath)) {
301
+ if (event.method === "POST") closeRequestConnection(event);
302
+ rejected("BCN_AUTH_PROXY_ORIGIN_BLOCKED", 403);
303
+ throw createError({
304
+ statusCode: 403,
305
+ message: buildBlockedOriginMessage(),
306
+ data: { code: "BCN_AUTH_PROXY_ORIGIN_BLOCKED" }
307
+ });
308
+ }
309
+ if (isPublicTokenCorsPost) setHeaders(event, { "access-control-allow-origin": "*" });
310
+ if (event.method === "POST" && hasUnsupportedRequestContentEncoding(event.headers)) {
311
+ closeRequestConnection(event);
312
+ rejected("BCN_AUTH_PROXY_REQUEST_ENCODING_UNSUPPORTED", 415);
313
+ throw createError({
314
+ statusCode: 415,
315
+ message: "Auth proxy accepts only identity-encoded request bodies",
316
+ data: { code: "BCN_AUTH_PROXY_REQUEST_ENCODING_UNSUPPORTED" }
317
+ });
318
+ }
319
+ if (!config.siteUrl) {
320
+ if (event.method === "POST") closeRequestConnection(event);
321
+ rejected("BCN_AUTH_PROXY_SITE_URL_MISSING", 500);
322
+ throw createError({
323
+ statusCode: 500,
324
+ message: buildMissingSiteUrlMessage(),
325
+ data: { code: "BCN_AUTH_PROXY_SITE_URL_MISSING" }
326
+ });
327
+ }
328
+ let siteUrl;
329
+ try {
330
+ siteUrl = normalizeConvexSiteUrl(config.siteUrl);
331
+ } catch {
332
+ if (event.method === "POST") closeRequestConnection(event);
333
+ rejected("BCN_AUTH_PROXY_SITE_URL_INVALID", 500);
334
+ throw createError({
335
+ statusCode: 500,
336
+ message: "Auth proxy site URL configuration is invalid",
337
+ data: { code: "BCN_AUTH_PROXY_SITE_URL_INVALID" }
338
+ });
339
+ }
340
+ const target = `${siteUrl}${AUTH_ROUTE}${normalizedPath}${fixedAuthPath ? "" : requestUrl.search}`;
341
+ const lifecycle = createAuthProxyLifecycle(event, startedAt);
342
+ const { controller } = lifecycle;
343
+ let response;
344
+ let requestBodyBytes = 0;
345
+ try {
346
+ const forwardHeaders = await buildAuthProxyForwardHeaders(event, {
347
+ trustedClientIpHeader
348
+ });
349
+ if (isPublicTokenCorsPost) {
350
+ forwardHeaders.origin = publicOrigin;
351
+ delete forwardHeaders.referer;
352
+ delete forwardHeaders["sec-fetch-site"];
353
+ }
354
+ let body;
355
+ if (event.method === "POST") {
356
+ const requestBodyLimit = isPublicTokenCorsPost ? Math.min(DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES, OAUTH_TOKEN_CORS_MAX_BODY_BYTES) : DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES;
357
+ const sizeError = getRequestBodySizeError(
358
+ event.headers.get("content-length"),
359
+ requestBodyLimit
360
+ );
361
+ if (sizeError)
362
+ throw createError({ statusCode: 413, message: sizeError.message, data: sizeError });
363
+ const requestBody = await readRequestBodyWithLimit(
364
+ event,
365
+ requestBodyLimit,
366
+ controller.signal
367
+ );
368
+ body = requestBody;
369
+ requestBodyBytes = requestBody?.byteLength ?? 0;
370
+ }
371
+ response = await fetch(target, {
372
+ method: event.method,
373
+ // Node fetch synthesizes `sec-fetch-mode: cors` from RequestInit.mode and
374
+ // overwrites the forwarded browser header. Better Auth uses that header
375
+ // to distinguish fetch calls (JSON redirects) from navigations (HTTP
376
+ // redirects), so preserve the only classification it consumes.
377
+ mode: event.headers.get("sec-fetch-mode") === "cors" ? "cors" : "same-origin",
378
+ headers: forwardHeaders,
379
+ body: body ? body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength) : void 0,
380
+ redirect: "manual",
381
+ signal: controller.signal
382
+ });
383
+ const responseCookies = response.headers.getSetCookie?.() ?? [];
384
+ if (publicMetadataCors && responseCookies.length > 0) {
385
+ throw createError({
386
+ statusCode: 502,
387
+ message: "Public auth metadata responses must not set cookies",
388
+ data: { code: "BCN_AUTH_PROXY_METADATA_COOKIE_REJECTED" }
389
+ });
390
+ }
391
+ if (isPublicTokenCorsPost && responseCookies.length > 0) {
392
+ throw createError({
393
+ statusCode: 502,
394
+ message: "Public OAuth token responses must not set cookies",
395
+ data: { code: "BCN_AUTH_PROXY_TOKEN_COOKIE_REJECTED" }
396
+ });
397
+ }
398
+ for (const cookie of responseCookies) {
399
+ if (!isBetterAuthSetCookie(cookie)) {
400
+ throw createError({
401
+ statusCode: 502,
402
+ message: "Auth proxy upstream returned a cookie outside the supported namespace",
403
+ data: { code: "BCN_AUTH_PROXY_COOKIE_NAME_UNSUPPORTED" }
404
+ });
405
+ }
406
+ if (hasSetCookieDomainAttribute(cookie)) {
407
+ throw createError({
408
+ statusCode: 502,
409
+ message: "Auth proxy does not support Domain-scoped Better Auth cookies",
410
+ data: { code: "BCN_AUTH_PROXY_COOKIE_DOMAIN_UNSUPPORTED" }
411
+ });
412
+ }
413
+ }
414
+ if (!isSupportedProxyResponseContentEncoding(response.headers.get("content-encoding"))) {
415
+ throw createError({
416
+ statusCode: 502,
417
+ message: "Auth proxy upstream returned an unsupported content encoding",
418
+ data: { code: "BCN_AUTH_PROXY_UPSTREAM_ENCODING_UNSUPPORTED" }
419
+ });
420
+ }
421
+ const critical = normalizedPath === "/convex/token" || normalizedPath === "/get-session";
422
+ if (critical && (response.status === 404 || response.status >= 500)) {
423
+ throw createError({
424
+ statusCode: 502,
425
+ message: buildAuthProxyUpstreamStatusMessage(response.status),
426
+ data: { code: "BCN_AUTH_PROXY_UPSTREAM_STATUS", upstreamStatus: response.status }
427
+ });
428
+ }
429
+ const responseSizeError = getResponseBodySizeError(
430
+ response.headers.get("content-length"),
431
+ DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES
432
+ );
433
+ if (responseSizeError) {
434
+ throw createError({
435
+ statusCode: 502,
436
+ message: responseSizeError.message,
437
+ data: responseSizeError
438
+ });
439
+ }
440
+ const responseBody = await readResponseBodyWithLimit(
441
+ response,
442
+ DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES,
443
+ controller.signal
444
+ );
445
+ setResponseStatus(event, response.status, response.statusText);
446
+ for (const cookie of responseCookies) {
447
+ appendResponseHeader(event, "set-cookie", cookie);
448
+ }
449
+ const responseConnection = response.headers.get("connection");
450
+ for (const [key, value] of response.headers.entries()) {
451
+ if (!shouldSkipProxyResponseHeader(key, responseConnection)) {
452
+ setHeaders(event, { [key]: value });
453
+ }
454
+ }
455
+ await recordAuthProxyRequestInDev({
456
+ id: requestId,
457
+ path: normalizedPath,
458
+ method: event.method,
459
+ timestamp: startedAt,
460
+ status: response.status,
461
+ duration: Date.now() - startedAt,
462
+ success: response.ok
463
+ });
464
+ trace("auth-proxy.request.completed", response.ok ? "success" : "error", {
465
+ durationMs: Date.now() - startedAt,
466
+ requestBodyBytes,
467
+ responseBodyBytes: responseBody.byteLength,
468
+ status: response.status
469
+ });
470
+ await sendAuthProxyBody(event, responseBody, controller.signal);
471
+ } catch (error) {
472
+ cancelResponseBody(response, error);
473
+ if (event.method === "POST" && (!event.node.req.complete || error && typeof error === "object" && "statusCode" in error && error.statusCode === 413) && !event.node.res.headersSent) {
474
+ closeRequestConnection(event);
475
+ }
476
+ const safeFailure = safeCaughtProxyFailure(error);
477
+ trace("auth-proxy.request.failed", "error", {
478
+ code: safeFailure?.code ?? "BCN_AUTH_PROXY_UNREACHABLE",
479
+ durationMs: Date.now() - startedAt,
480
+ requestBodyBytes,
481
+ status: safeFailure?.statusCode ?? 502
482
+ });
483
+ if (safeFailure) {
484
+ throw createError({
485
+ statusCode: safeFailure.statusCode,
486
+ message: "Auth proxy request failed",
487
+ data: { code: safeFailure.code }
488
+ });
489
+ }
490
+ await recordAuthProxyRequestInDev({
491
+ id: requestId,
492
+ path: normalizedPath,
493
+ method: event.method,
494
+ timestamp: startedAt,
495
+ status: 502,
496
+ duration: Date.now() - startedAt,
497
+ success: false
498
+ });
499
+ throw createError({
500
+ statusCode: 502,
501
+ message: buildAuthProxyUnreachableMessage(),
502
+ data: { code: "BCN_AUTH_PROXY_UNREACHABLE" }
503
+ });
504
+ } finally {
505
+ lifecycle.cleanup();
506
+ }
507
+ });
508
+ }
509
+ export default createAuthProxyHandler();
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
@@ -0,0 +1,6 @@
1
+ import { createAuthProxyHandler } from "./[...].js";
2
+ export default createAuthProxyHandler({
3
+ allowedMethods: ["GET", "HEAD"],
4
+ fixedAuthPath: "/.well-known/oauth-authorization-server",
5
+ publicMetadataCors: true
6
+ });
@@ -0,0 +1,15 @@
1
+ import type { H3Event } from 'h3';
2
+ export declare const DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES: 1048576;
3
+ export declare const DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES: 1048576;
4
+ export interface ProxyBodySizeErrorShape {
5
+ statusCode: 413 | 502;
6
+ code: 'BCN_AUTH_PROXY_REQUEST_BODY_TOO_LARGE' | 'BCN_AUTH_PROXY_UPSTREAM_BODY_TOO_LARGE';
7
+ message: string;
8
+ contentLengthBytes: number;
9
+ maxBytes: number;
10
+ }
11
+ export declare function getRequestBodySizeError(contentLengthHeader: string | null, maxBytes?: number): ProxyBodySizeErrorShape | null;
12
+ export declare function getResponseBodySizeError(contentLengthHeader: string | null, maxBytes?: number): ProxyBodySizeErrorShape | null;
13
+ export declare function readRequestBodyWithLimit(event: H3Event, maxBytes?: number, signal?: AbortSignal): Promise<Uint8Array | undefined>;
14
+ export declare function readResponseBodyWithLimit(response: Response, maxBytes?: number, signal?: AbortSignal): Promise<Uint8Array>;
15
+ export declare function cancelResponseBody(response: Response | undefined, reason: unknown): void;