@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,38 @@
1
+ import { I as ExtensionRef, Qn as BetterAuthInfrastructureError, Yn as AuthGraphqlExtensions, Zn as BetterAuthConfigurationError, c as AuthTransport, qn as AuthFailure } from "./auth-contracts-Brh_Qko9.cjs";
2
+ import { IntrinsicException } from "@nestjs/common";
3
+ //#region src/graphql-transport.d.ts
4
+ interface GraphqlTransportOptions {
5
+ /** Case-insensitive connection-init credential keys; defaults to authorization and cookie. */
6
+ connectionParamHeaders?: readonly string[];
7
+ /**
8
+ * Replaces socket credentials, preserving absent host and forwarded-host/proto headers.
9
+ * Returning undefined presents no credentials: neither connectionParamHeaders nor the
10
+ * upgrade request's credential headers are used.
11
+ */
12
+ subscriptionCredentials?: (connectionContext: unknown) => HeadersInit | undefined;
13
+ /** Connection principal reuse; zero by default. Authoritative plans bypass the TTL. */
14
+ subscriptionPrincipalTtlMs?: number;
15
+ fieldResolverCoverage?: "error" | "warn" | "off";
16
+ federationCoverage?: "error" | "warn" | "off";
17
+ }
18
+ export declare class BetterAuthGraphqlDenial extends IntrinsicException {
19
+ readonly extensions: AuthGraphqlExtensions;
20
+ constructor(failure: AuthFailure);
21
+ }
22
+ export declare class BetterAuthGraphqlInternalError extends Error {
23
+ readonly extensions: AuthGraphqlExtensions;
24
+ constructor(error: BetterAuthInfrastructureError | BetterAuthConfigurationError);
25
+ }
26
+ export declare class BetterAuthGraphqlRepeatedInternalError extends IntrinsicException {
27
+ readonly extensions: AuthGraphqlExtensions;
28
+ constructor(error: BetterAuthInfrastructureError | BetterAuthConfigurationError);
29
+ }
30
+ /** Keeps the upgrade request and its original browser headers across Mercurius operation spreads. */
31
+ export declare function mercuriusSubscriptionContext(): (_connection: unknown, request: {
32
+ headers: Record<string, unknown>;
33
+ }) => Record<string | symbol, unknown>;
34
+ export declare function apolloTransport(options?: GraphqlTransportOptions): ExtensionRef<AuthTransport>;
35
+ export declare function mercuriusTransport(options?: GraphqlTransportOptions): ExtensionRef<AuthTransport>;
36
+ //#endregion
37
+ export type { GraphqlTransportOptions };
38
+ //# sourceMappingURL=graphql.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql.d.cts","names":[],"sources":["../src/graphql-transport.ts"],"mappings":";;;UAyDiB;;EAEf;;;;;;EAMA,2BACE,+BACG;;EAEL;EACA;EACA;;qBAEW,gCAAgC;WAClC,YAAY;EAErB,YAAY,SAAS;;qBAoBV,uCAAuC;WACzC,YAAY;EAErB,YACE,OAAO,gCAAgC;;qBAM9B,+CAA+C;WACjD,YAAY;EAErB,YACE,OAAO,gCAAgC;;;wBAO3B,iCAA4B,sBAEpB;EACT,SAAS;MACnB;wBAmtBW,gBACd,UAAS,0BACR,aAAa;wBAGA,mBACd,UAAS,0BACR,aAAa"}
@@ -0,0 +1,38 @@
1
+ import { I as ExtensionRef, Qn as BetterAuthInfrastructureError, Yn as AuthGraphqlExtensions, Zn as BetterAuthConfigurationError, c as AuthTransport, qn as AuthFailure } from "./auth-contracts-Cz7C4_Ch.mjs";
2
+ import { IntrinsicException } from "@nestjs/common";
3
+ //#region src/graphql-transport.d.ts
4
+ interface GraphqlTransportOptions {
5
+ /** Case-insensitive connection-init credential keys; defaults to authorization and cookie. */
6
+ connectionParamHeaders?: readonly string[];
7
+ /**
8
+ * Replaces socket credentials, preserving absent host and forwarded-host/proto headers.
9
+ * Returning undefined presents no credentials: neither connectionParamHeaders nor the
10
+ * upgrade request's credential headers are used.
11
+ */
12
+ subscriptionCredentials?: (connectionContext: unknown) => HeadersInit | undefined;
13
+ /** Connection principal reuse; zero by default. Authoritative plans bypass the TTL. */
14
+ subscriptionPrincipalTtlMs?: number;
15
+ fieldResolverCoverage?: "error" | "warn" | "off";
16
+ federationCoverage?: "error" | "warn" | "off";
17
+ }
18
+ export declare class BetterAuthGraphqlDenial extends IntrinsicException {
19
+ readonly extensions: AuthGraphqlExtensions;
20
+ constructor(failure: AuthFailure);
21
+ }
22
+ export declare class BetterAuthGraphqlInternalError extends Error {
23
+ readonly extensions: AuthGraphqlExtensions;
24
+ constructor(error: BetterAuthInfrastructureError | BetterAuthConfigurationError);
25
+ }
26
+ export declare class BetterAuthGraphqlRepeatedInternalError extends IntrinsicException {
27
+ readonly extensions: AuthGraphqlExtensions;
28
+ constructor(error: BetterAuthInfrastructureError | BetterAuthConfigurationError);
29
+ }
30
+ /** Keeps the upgrade request and its original browser headers across Mercurius operation spreads. */
31
+ export declare function mercuriusSubscriptionContext(): (_connection: unknown, request: {
32
+ headers: Record<string, unknown>;
33
+ }) => Record<string | symbol, unknown>;
34
+ export declare function apolloTransport(options?: GraphqlTransportOptions): ExtensionRef<AuthTransport>;
35
+ export declare function mercuriusTransport(options?: GraphqlTransportOptions): ExtensionRef<AuthTransport>;
36
+ //#endregion
37
+ export type { GraphqlTransportOptions };
38
+ //# sourceMappingURL=graphql.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql.d.mts","names":[],"sources":["../src/graphql-transport.ts"],"mappings":";;;UAyDiB;;EAEf;;;;;;EAMA,2BACE,+BACG;;EAEL;EACA;EACA;;qBAEW,gCAAgC;WAClC,YAAY;EAErB,YAAY,SAAS;;qBAoBV,uCAAuC;WACzC,YAAY;EAErB,YACE,OAAO,gCAAgC;;qBAM9B,+CAA+C;WACjD,YAAY;EAErB,YACE,OAAO,gCAAgC;;;wBAO3B,iCAA4B,sBAEpB;EACT,SAAS;MACnB;wBAmtBW,gBACd,UAAS,0BACR,aAAa;wBAGA,mBACd,UAAS,0BACR,aAAa"}
@@ -0,0 +1,503 @@
1
+ import { c as isConfigurationError, n as BetterAuthConfigurationError, t as AuthFailures } from "./auth-errors-C3rbTV9p.mjs";
2
+ import { E as REQUIREMENTS_METADATA, a as ACCESS_METADATA, i as ACCEPT_PRINCIPALS_METADATA, s as AUTH_ENHANCER } from "./decorate-Dt0e9K6R.mjs";
3
+ import { t as BetterAuthScopeInterceptor } from "./auth-scope-interceptor-DYPn3b8M.mjs";
4
+ import { t as BetterAuthGuard } from "./auth-guard-h9QB_l11.mjs";
5
+ import { o as toWebHeaders, s as upgradeRequestUrl } from "./platform-CZl7TY8j.mjs";
6
+ import { IntrinsicException } from "@nestjs/common";
7
+ import { ApplicationConfig, MetadataScanner } from "@nestjs/core";
8
+ import { Args, GRAPHQL_MODULE_OPTIONS, PARAM_ARGS_METADATA, Query, RESOLVER_PROPERTY_METADATA, RESOLVER_REFERENCE_METADATA, RESOLVER_TYPE_METADATA, ResolveField, ResolveReference } from "@nestjs/graphql";
9
+ //#region src/graphql-lineage.ts
10
+ const OPERATIONS = Symbol.for("@nestjs-kit/better-auth:graphql-operations");
11
+ function record(value) {
12
+ return typeof value === "object" && value !== null ? value : void 0;
13
+ }
14
+ /** Apollo reference resolvers omit the argument object; parameter readers see the original array. */
15
+ function graphqlArgs(args) {
16
+ const reference = args.length === 3;
17
+ return {
18
+ root: record(args[0]),
19
+ args: reference ? void 0 : record(args[1]),
20
+ context: record(args[reference ? 1 : 2]) ?? args,
21
+ info: record(args[reference ? 2 : 3])
22
+ };
23
+ }
24
+ function operationState(carrier, operation) {
25
+ let operations = Reflect.get(carrier, OPERATIONS);
26
+ if (!operations) {
27
+ operations = /* @__PURE__ */ new Map();
28
+ Object.defineProperty(carrier, OPERATIONS, { value: operations });
29
+ }
30
+ let state = operations.get(operation);
31
+ if (state === void 0) {
32
+ state = {
33
+ id: operations.size + 1,
34
+ references: /* @__PURE__ */ new Set()
35
+ };
36
+ operations.set(operation, state);
37
+ }
38
+ return state;
39
+ }
40
+ function keys(path) {
41
+ return path ? [...keys(path.prev), path.key] : [];
42
+ }
43
+ function position(id, path) {
44
+ return `${id}:${JSON.stringify(keys(path))}`;
45
+ }
46
+ function graphqlInvocation(args, reference = false) {
47
+ const normalized = graphqlArgs(args);
48
+ return (reference ? normalized.root : normalized.info) ?? args;
49
+ }
50
+ function graphqlLineage(args, reference = false) {
51
+ const normalized = graphqlArgs(args);
52
+ const carrier = normalized.context;
53
+ const state = operationState(carrier, normalized.info?.operation ?? carrier);
54
+ const { id } = state;
55
+ if (reference) state.references.add(JSON.stringify(keys(normalized.info?.path)));
56
+ return {
57
+ carrier,
58
+ position: reference ? `${id}:_entities#${String(normalized.root?.__typename ?? "")}` : position(id, normalized.info?.path),
59
+ *enclosing(currentArgs) {
60
+ const current = graphqlArgs(currentArgs);
61
+ const operation = operationState(current.context, current.info?.operation ?? current.context);
62
+ const path = current.info?.path;
63
+ for (let child = path, parent = path?.prev; parent; child = parent, parent = parent.prev) {
64
+ if (typeof parent.key === "number" && parent.prev && (parent.prev.key === "_entities" || operation.references.has(JSON.stringify(keys(parent.prev))))) yield `${operation.id}:_entities#${child?.typename ?? String(current.root?.__typename ?? "")}`;
65
+ yield position(operation.id, parent);
66
+ }
67
+ }
68
+ };
69
+ }
70
+ //#endregion
71
+ //#region src/graphql-transport.ts
72
+ const MERCURIUS_AMBIENT = Symbol.for("@nestjs-kit/better-auth:mercurius-ambient");
73
+ const MERCURIUS_UPGRADE = Symbol.for("@nestjs-kit/better-auth:mercurius-upgrade");
74
+ var BetterAuthGraphqlDenial = class extends IntrinsicException {
75
+ extensions;
76
+ constructor(failure) {
77
+ super(failure.message);
78
+ this.extensions = {
79
+ code: failure.code,
80
+ statusCode: failure.status,
81
+ ...failure.reason ? { reason: failure.reason } : {}
82
+ };
83
+ }
84
+ };
85
+ function internalExtensions(error) {
86
+ return {
87
+ code: "INTERNAL_SERVER_ERROR",
88
+ reason: isConfigurationError(error) ? "AUTH_MISCONFIGURED" : "AUTH_UNAVAILABLE",
89
+ statusCode: 500
90
+ };
91
+ }
92
+ var BetterAuthGraphqlInternalError = class extends Error {
93
+ extensions;
94
+ constructor(error) {
95
+ super("Internal server error", { cause: error });
96
+ this.extensions = internalExtensions(error);
97
+ }
98
+ };
99
+ var BetterAuthGraphqlRepeatedInternalError = class extends IntrinsicException {
100
+ extensions;
101
+ constructor(error) {
102
+ super("Internal server error", { cause: error });
103
+ this.extensions = internalExtensions(error);
104
+ }
105
+ };
106
+ /** Keeps the upgrade request and its original browser headers across Mercurius operation spreads. */
107
+ function mercuriusSubscriptionContext() {
108
+ return (_connection, request) => ({
109
+ [MERCURIUS_UPGRADE]: request,
110
+ [MERCURIUS_AMBIENT]: ambientHeaders(request)
111
+ });
112
+ }
113
+ function upgrade(value) {
114
+ const candidate = record(value);
115
+ return candidate && record(candidate.headers) ? candidate : void 0;
116
+ }
117
+ /** The WebSocket of a graphql-ws `extra` ({ socket, request }): a socket with function-typed send and close. */
118
+ function graphqlWsSocket(value) {
119
+ const socket = record(record(value)?.socket);
120
+ return socket && typeof socket.send === "function" && typeof socket.close === "function" ? socket : void 0;
121
+ }
122
+ /**
123
+ * The upgrade request of a graphql-ws `extra` ({ socket, request }) whose socket is a
124
+ * WebSocket. Only the graphql-ws server creates that pair; parsed request data cannot carry
125
+ * functions, so a client-sent header or field never selects the socket path. The socket's
126
+ * state does not change this recognition: the transport classifies it once per operation
127
+ * (GraphqlTransport.openAtStart).
128
+ */
129
+ function graphqlWsUpgrade(value) {
130
+ return graphqlWsSocket(value) ? upgrade(record(value)?.request) : void 0;
131
+ }
132
+ /** WebSocket.OPEN of the `ws` sockets that Nest's graphql-ws server creates. */
133
+ const WEBSOCKET_OPEN = 1;
134
+ /** Upgrade-request headers that locate the server for Better Auth; none of them is a credential. */
135
+ const HOST_METADATA = [
136
+ "host",
137
+ "x-forwarded-host",
138
+ "x-forwarded-proto"
139
+ ];
140
+ /**
141
+ * The upgrade request's URL without the target's query string and fragment. A query string can
142
+ * carry a connection's credential (`?access_token=`), which an operation that reads no credential
143
+ * of its connection must not expose to principal sources or policies.
144
+ */
145
+ function upgradePathUrl(request) {
146
+ const target = request.url ?? "/";
147
+ const end = target.search(/[?#]/);
148
+ return upgradeRequestUrl({
149
+ headers: request.headers,
150
+ url: end === -1 ? target : target.slice(0, end),
151
+ secure: request.secure,
152
+ socket: request.socket
153
+ });
154
+ }
155
+ /** Copies the host metadata of `ambient` into `into` where `into` has none of its own. */
156
+ function withHostMetadata(into, ambient) {
157
+ for (const name of HOST_METADATA) {
158
+ const value = ambient.get(name);
159
+ if (!into.has(name) && value !== null) into.set(name, value);
160
+ }
161
+ return into;
162
+ }
163
+ /**
164
+ * The identity of one GraphQL execution, shared by every resolver of that execution. graphql-js
165
+ * coerces the variable values into a fresh object for every execution, including one
166
+ * subscription and its events; a parsed operation can be cached across executions, so it
167
+ * serves only as the fallback.
168
+ */
169
+ function executionOf(info) {
170
+ const value = record(info);
171
+ return record(value?.variableValues) ?? record(value?.operation);
172
+ }
173
+ function ambientHeaders(request) {
174
+ const value = record(request);
175
+ const rawHeaders = (record(value?.raw) ?? value)?.rawHeaders;
176
+ if (Array.isArray(rawHeaders)) {
177
+ const headers = new Headers();
178
+ for (let index = 0; index + 1 < rawHeaders.length; index += 2) if (typeof rawHeaders[index] === "string" && typeof rawHeaders[index + 1] === "string") headers.append(rawHeaders[index], rawHeaders[index + 1]);
179
+ return headers;
180
+ }
181
+ return toWebHeaders(value?.headers ?? {});
182
+ }
183
+ /**
184
+ * Mercurius assigns the route's Fastify reply to context.reply for HTTP operations. Its
185
+ * subscription contexts carry the platform-recognized upgrade request inside a plain reply
186
+ * object instead, so the reply's identity, not the request alone, marks an HTTP operation.
187
+ */
188
+ function platformReply(http, value) {
189
+ const request = record(value)?.request;
190
+ if (http?.isRequest(request) !== true) return false;
191
+ return http.responseFor ? http.responseFor(request) === value : true;
192
+ }
193
+ function carrierDetails(context, driver, http) {
194
+ const carrier = record(context) ?? {};
195
+ const req = record(carrier.req);
196
+ const extra = record(carrier.extra);
197
+ const httpRequest = driver === "apollo" ? http?.isRequest(req) === true || http?.isRequest(extra?.request) === true : platformReply(http, carrier.reply);
198
+ const wsContext = driver === "apollo" && !httpRequest && graphqlWsUpgrade(req?.extra) ? req : void 0;
199
+ const wsExtra = driver === "apollo" && !httpRequest ? wsContext ? wsContext.extra : extra : void 0;
200
+ const socket = httpRequest ? void 0 : driver === "apollo" ? graphqlWsUpgrade(wsExtra) : upgrade(carrier[MERCURIUS_UPGRADE]) ?? ("_connectionInit" in carrier ? upgrade(carrier.request) ?? upgrade(record(carrier.reply)?.request) ?? upgrade(carrier.req) : void 0);
201
+ const connection = wsContext ? req : carrier;
202
+ const params = record(wsContext ? req?.connectionParams : carrier.connectionParams ?? carrier._connectionInit);
203
+ const request = driver === "apollo" ? carrier.req : record(carrier.reply)?.request ?? carrier.req;
204
+ const ambient = () => carrier[MERCURIUS_AMBIENT] instanceof Headers ? new Headers(carrier[MERCURIUS_AMBIENT]) : ambientHeaders(socket);
205
+ return {
206
+ carrier,
207
+ socket,
208
+ webSocket: socket ? graphqlWsSocket(wsExtra) : void 0,
209
+ connection,
210
+ params,
211
+ request,
212
+ ambient
213
+ };
214
+ }
215
+ var GraphqlTransport = class {
216
+ id;
217
+ options;
218
+ requires = { hostlessCalls: false };
219
+ connectionTtlMs;
220
+ kit;
221
+ plans = [];
222
+ enhancerAdvice;
223
+ filterAdvice;
224
+ /** Whether each execution's graphql-ws socket was open when the execution first reached the transport. */
225
+ socketsAtStart = /* @__PURE__ */ new WeakMap();
226
+ constructor(id, options) {
227
+ this.id = id;
228
+ this.options = options;
229
+ this.connectionTtlMs = options.subscriptionPrincipalTtlMs ?? 0;
230
+ if (!Number.isFinite(this.connectionTtlMs) || this.connectionTtlMs < 0) throw new BetterAuthConfigurationError("INVALID_SUBSCRIPTION_TTL", "subscriptionPrincipalTtlMs must be a finite nonnegative number");
231
+ }
232
+ handles(context) {
233
+ return context.getType() === "graphql";
234
+ }
235
+ reference(context) {
236
+ return Reflect.getMetadata(RESOLVER_REFERENCE_METADATA, context.getHandler()) === true;
237
+ }
238
+ defaultAccessFor(target, method) {
239
+ const handler = Reflect.get(Reflect.get(target, "prototype") ?? target, method);
240
+ return typeof handler === "function" && !Reflect.getMetadata(RESOLVER_REFERENCE_METADATA, handler) && Reflect.getMetadata(RESOLVER_PROPERTY_METADATA, handler) ? "inherit" : void 0;
241
+ }
242
+ lineage(context) {
243
+ const args = context.getArgs();
244
+ const normalized = graphqlArgs(args);
245
+ this.openAtStart(carrierDetails(normalized.context, this.id, this.kit?.http ?? null).webSocket, normalized.info);
246
+ return {
247
+ ...graphqlLineage(args, this.reference(context)),
248
+ assertReadable: (args) => {
249
+ if (this.kit) this.assertRequest(args, this.kit);
250
+ }
251
+ };
252
+ }
253
+ /**
254
+ * Whether the operation's graphql-ws socket was open when the operation started. The first
255
+ * classification of an execution holds for every later reader of it, so a connection that
256
+ * closes during authentication keeps its credentials. A socket that is not open when an
257
+ * operation starts belongs either to a connection that closed while graphql-ws prepared the
258
+ * operation or to an earlier connection that a cached context carries; its state cannot tell
259
+ * the two apart, so the operation reads no credential of that connection in either case.
260
+ */
261
+ openAtStart(webSocket, info) {
262
+ if (!webSocket) return true;
263
+ const execution = executionOf(info);
264
+ const known = execution ? this.socketsAtStart.get(execution) : void 0;
265
+ if (known !== void 0) return known;
266
+ const open = webSocket.readyState === WEBSOCKET_OPEN;
267
+ if (execution) this.socketsAtStart.set(execution, open);
268
+ return open;
269
+ }
270
+ assertRequest(args, kit) {
271
+ const details = carrierDetails(graphqlArgs(args).context, this.id, kit.http);
272
+ if (details.socket) return details;
273
+ if (!kit.http?.isRequest(details.request)) throw BetterAuthConfigurationError.atRequest("GRAPHQL_CONTEXT_UNRECOGNIZED", "GraphQL context has no recognized platform or upgrade request", { hint: "Keep the native request at context.req or context.extra.request; use mercuriusSubscriptionContext() for Mercurius sockets." });
274
+ if (!kit.http.isLive(details.request)) throw BetterAuthConfigurationError.atRequest("GRAPHQL_CONTEXT_STALE_REQUEST", "GraphQL context contains a completed request", { hint: "Return a fresh context object for every operation and every graphql-ws connection." });
275
+ return details;
276
+ }
277
+ describe(context, kit) {
278
+ this.kit = kit;
279
+ const args = context.getArgs();
280
+ const normalized = graphqlArgs(args);
281
+ const initial = carrierDetails(normalized.context, this.id, kit.http);
282
+ const open = this.openAtStart(initial.webSocket, normalized.info);
283
+ const key = !initial.socket && kit.http?.isRequest(initial.request) ? kit.http.key(initial.request) : open ? normalized.context : executionOf(normalized.info) ?? args;
284
+ const checked = () => this.assertRequest(args, kit);
285
+ const headers = () => {
286
+ const details = checked();
287
+ if (!details.socket) return kit.http.headers(details.request);
288
+ const ambient = details.ambient();
289
+ if (!open) return withHostMetadata(new Headers(), ambient);
290
+ if (this.options.subscriptionCredentials) {
291
+ const input = this.options.subscriptionCredentials(details.connection);
292
+ let mapped;
293
+ try {
294
+ mapped = new Headers(input);
295
+ } catch {
296
+ throw AuthFailures.rejected({
297
+ status: 401,
298
+ reason: "MALFORMED_CREDENTIALS"
299
+ });
300
+ }
301
+ return withHostMetadata(mapped, ambient);
302
+ }
303
+ const credentials = new Headers(ambient);
304
+ const allow = new Set((this.options.connectionParamHeaders ?? ["authorization", "cookie"]).map((name) => name.toLowerCase()));
305
+ for (const [name, value] of Object.entries(details.params ?? {})) {
306
+ if (!allow.has(name.toLowerCase())) continue;
307
+ if (typeof value !== "string" || /[\r\n\0]/.test(value)) throw AuthFailures.rejected({
308
+ status: 401,
309
+ reason: "MALFORMED_CREDENTIALS"
310
+ });
311
+ try {
312
+ credentials.set(name, value);
313
+ } catch {
314
+ throw AuthFailures.rejected({
315
+ status: 401,
316
+ reason: "MALFORMED_CREDENTIALS"
317
+ });
318
+ }
319
+ }
320
+ return credentials;
321
+ };
322
+ return {
323
+ key,
324
+ invocation: graphqlInvocation(args, this.reference(context)),
325
+ lineage: this.lineage(context),
326
+ ...initial.socket && open ? {
327
+ connection: initial.socket,
328
+ principalTtlMs: this.connectionTtlMs
329
+ } : {},
330
+ headers,
331
+ get clientIp() {
332
+ const details = checked();
333
+ return details.socket ? null : kit.http.clientIp(details.request);
334
+ },
335
+ get cookies() {
336
+ const details = checked();
337
+ return details.socket ? null : kit.http.cookieSink(details.request, details.carrier.reply ?? record(details.request)?.res ?? kit.http.responseFor?.(details.request));
338
+ },
339
+ get request() {
340
+ const details = checked();
341
+ if (!details.socket) return kit.http.request(details.request);
342
+ return {
343
+ method: "GET",
344
+ url: open ? upgradeRequestUrl(details.socket) : upgradePathUrl(details.socket)
345
+ };
346
+ },
347
+ param: (name) => (this.reference(context) ? normalized.root?.[name] : normalized.args?.[name]) ?? (!initial.socket && kit.http?.isRequest(initial.request) ? kit.http.param(initial.request, name) : void 0),
348
+ get browser() {
349
+ const details = checked();
350
+ return details.socket ? {
351
+ enforce: true,
352
+ headers: details.ambient,
353
+ url: upgradeRequestUrl(details.socket),
354
+ key: details.socket
355
+ } : {
356
+ enforce: normalized.info?.operation.operation === "mutation",
357
+ headers: () => kit.http.headers(details.request),
358
+ url: kit.http.request(details.request).url,
359
+ key
360
+ };
361
+ }
362
+ };
363
+ }
364
+ toException(failure) {
365
+ return new BetterAuthGraphqlDenial(failure);
366
+ }
367
+ toInternalException(error, _context, info) {
368
+ return info.repeated ? new BetterAuthGraphqlRepeatedInternalError(error) : new BetterAuthGraphqlInternalError(error);
369
+ }
370
+ validate(context) {
371
+ const options = context.moduleRef.get(GRAPHQL_MODULE_OPTIONS, { strict: false });
372
+ const names = [];
373
+ for (let driver = options.driver; typeof driver === "function"; driver = Object.getPrototypeOf(driver)) names.push(driver.name);
374
+ if (names.some((name) => name.startsWith(this.id === "apollo" ? "Mercurius" : "Apollo"))) throw new BetterAuthConfigurationError("GRAPHQL_DRIVER_MISMATCH", `${this.id} transport does not match ${names.join(" / ")}`);
375
+ if (options.context !== void 0 && typeof options.context !== "function") throw new BetterAuthConfigurationError("GRAPHQL_STATIC_CONTEXT", "GraphQL context must be a function returning a fresh object", "context: ({ req }) => ({ req, loaders: createLoaders() })");
376
+ class Probe {
377
+ query() {}
378
+ field() {}
379
+ reference() {}
380
+ }
381
+ for (const [name, decorator, key] of [
382
+ [
383
+ "query",
384
+ Query(() => String),
385
+ RESOLVER_TYPE_METADATA
386
+ ],
387
+ [
388
+ "field",
389
+ ResolveField(() => String),
390
+ RESOLVER_PROPERTY_METADATA
391
+ ],
392
+ [
393
+ "reference",
394
+ ResolveReference(),
395
+ RESOLVER_REFERENCE_METADATA
396
+ ]
397
+ ]) {
398
+ decorator(Probe.prototype, name, Object.getOwnPropertyDescriptor(Probe.prototype, name));
399
+ if (!Reflect.getMetadata(key, Probe.prototype[name])) throw new BetterAuthConfigurationError("NEST_METADATA_KEY_CHANGED", `GraphQL metadata canary failed: ${key}`);
400
+ }
401
+ Args("probe", { type: () => String })(Probe.prototype, "query", 0);
402
+ const argumentMetadata = record(Reflect.getMetadata(PARAM_ARGS_METADATA, Probe, "query"));
403
+ if (!argumentMetadata || !Object.entries(argumentMetadata).some(([key, value]) => key.startsWith("3:") && record(value)?.data === "probe")) throw new BetterAuthConfigurationError("NEST_METADATA_KEY_CHANGED", "GraphQL argument metadata failed its parameter canary");
404
+ const guards = options.fieldResolverEnhancers?.includes("guards") === true;
405
+ const scanner = new MetadataScanner();
406
+ this.plans = [];
407
+ for (const wrapper of context.discovery.getProviders()) {
408
+ const target = wrapper.metatype;
409
+ if (!target?.prototype || wrapper.isAlias) continue;
410
+ for (const method of scanner.getAllMethodNames(target.prototype)) {
411
+ const handler = Reflect.get(target.prototype, method);
412
+ const field = Reflect.getMetadata(RESOLVER_PROPERTY_METADATA, handler) === true;
413
+ const reference = Reflect.getMetadata(RESOLVER_REFERENCE_METADATA, handler) === true;
414
+ if (!field && !reference && !Reflect.getMetadata(RESOLVER_TYPE_METADATA, handler)) continue;
415
+ const metadata = record(Reflect.getMetadata(PARAM_ARGS_METADATA, target, method));
416
+ const inputs = reference ? [] : Object.entries(metadata ?? {}).flatMap(([key, entry]) => key.startsWith("3:") && typeof record(entry)?.data === "string" ? [String(record(entry).data)] : []);
417
+ context.claim(target, method, field || reference ? guards ? "global" : "none" : "global", {
418
+ code: reference ? "REFERENCE_RESOLVER_UNGUARDED" : field ? "FIELD_RESOLVER_UNGUARDED" : "GRAPHQL_OPERATION_UNGUARDED",
419
+ hint: "Set fieldResolverEnhancers: ['guards', 'interceptors'], or declare @Public() where appropriate.",
420
+ coverage: reference ? this.options.federationCoverage : field ? this.options.fieldResolverCoverage : "error",
421
+ everyHandler: reference,
422
+ inputs
423
+ });
424
+ this.plans.push({
425
+ plan: context.planOf(target, method),
426
+ field,
427
+ reference,
428
+ target,
429
+ method
430
+ });
431
+ }
432
+ }
433
+ const federation = names.some((name) => name.includes("Federation")) || this.plans.some((entry) => entry.reference);
434
+ const needsGuards = this.plans.some((entry) => entry.field || entry.reference);
435
+ if (federation && needsGuards && !guards && this.options.federationCoverage !== "off") {
436
+ const message = "Federation field and reference resolvers require fieldResolverEnhancers: ['guards', 'interceptors']; this runs every global guard once per field invocation.";
437
+ if (this.options.federationCoverage === "warn") context.logger.warn(`FEDERATION_FIELD_GUARDS_REQUIRED: ${message}`);
438
+ else throw new BetterAuthConfigurationError("FEDERATION_FIELD_GUARDS_REQUIRED", message);
439
+ }
440
+ if (needsGuards && !options.fieldResolverEnhancers?.includes("filters")) this.filterAdvice = {
441
+ level: "warn",
442
+ code: "W_FIELD_EXCEPTION_FILTERS_DISABLED",
443
+ message: "Nested GraphQL errors bypass Nest exception filters and ERROR logging while fieldResolverEnhancers omits filters.",
444
+ hint: "Include 'filters' with 'guards' in fieldResolverEnhancers to deliver nested authentication errors through Nest's exception pipeline; 'interceptors' enables per-field scopes."
445
+ };
446
+ if (needsGuards) {
447
+ const config = context.moduleRef.get(ApplicationConfig, { strict: false });
448
+ const owned = /* @__PURE__ */ new Set([context.moduleRef.get(BetterAuthGuard, { strict: false }), context.moduleRef.get(BetterAuthScopeInterceptor, { strict: false })]);
449
+ const names = [...config.getGlobalGuards(), ...config.getGlobalInterceptors()].filter((value) => !owned.has(value) && !["guard", "scope"].includes(Reflect.get(value, AUTH_ENHANCER))).map((value) => value.constructor.name);
450
+ if (names.length) this.enhancerAdvice = {
451
+ level: "warn",
452
+ code: "W_FIELD_GUARDS_MULTIPLY_GLOBAL_ENHANCERS",
453
+ message: `${names.join(", ")} run once per field-resolver invocation when their corresponding field enhancer is enabled: guards for global guards, interceptors for global interceptors.`,
454
+ hint: "Use @SkipThrottle() or equivalent, move global guards to controllers, or use coverage: 'warn' behind an authenticating router."
455
+ };
456
+ }
457
+ }
458
+ advise(context) {
459
+ const advice = [this.enhancerAdvice, this.filterAdvice].filter((value) => value !== void 0);
460
+ const entries = this.plans;
461
+ const publicEntries = entries.filter(({ plan, field }) => !field && ["public", "optional"].includes(plan.access));
462
+ const inheriting = entries.filter(({ plan }) => plan.access === "inherit");
463
+ if (publicEntries.length && inheriting.length) advice.push({
464
+ level: "warn",
465
+ code: "W_FIELD_RESOLVER_INHERITS",
466
+ message: `${inheriting.map(({ plan }) => plan.site).slice(0, 20).join(", ")} inherit readings from entry points including ${publicEntries.map(({ plan }) => plan.site).slice(0, 20).join(", ")}.`,
467
+ hint: "Use @RequireAuth() and fieldResolverEnhancers: ['guards'] for sensitive fields."
468
+ });
469
+ for (const { plan } of inheriting) if (plan.principalParams.some((param) => entries.some((entry) => [...entry.plan.accepts].some((kind) => kind !== param.kind)))) advice.push({
470
+ level: "warn",
471
+ code: "W_NESTED_PRINCIPAL_PARAM",
472
+ message: `${plan.site} can inherit a different principal kind from another schema entry point.`,
473
+ hint: "Use @CurrentPrincipal() and narrow p.kind, or declare field access and acceptance."
474
+ });
475
+ const targets = new Set(entries.filter(({ field }) => field).map(({ target }) => target));
476
+ for (const target of targets) if ([
477
+ ACCESS_METADATA,
478
+ ACCEPT_PRINCIPALS_METADATA,
479
+ REQUIREMENTS_METADATA
480
+ ].some((key) => Reflect.hasMetadata(key, target))) advice.push({
481
+ level: "info",
482
+ code: "I_CLASS_METADATA_OPERATIONS_ONLY",
483
+ message: `Class metadata of ${target.name} excludes inherited fields ${entries.filter((entry) => entry.target === target && entry.plan.access === "inherit").map((entry) => entry.method).join(", ")}; it applies to operations and reference resolvers ${entries.filter((entry) => entry.target === target && entry.reference).map((entry) => entry.method).join(", ") || "(none)"}.`
484
+ });
485
+ if (!this.connectionTtlMs && context.sources.some((source) => source.effects?.consumesQuota || source.effects?.writes)) advice.push({
486
+ level: "warn",
487
+ code: "W_QUOTA_PER_MESSAGE",
488
+ message: "Each socket operation resolves quota-consuming or writing principal sources.",
489
+ hint: "Consider subscriptionPrincipalTtlMs and its revocation delay."
490
+ });
491
+ return advice;
492
+ }
493
+ };
494
+ function apolloTransport(options = {}) {
495
+ return new GraphqlTransport("apollo", options);
496
+ }
497
+ function mercuriusTransport(options = {}) {
498
+ return new GraphqlTransport("mercurius", options);
499
+ }
500
+ //#endregion
501
+ export { BetterAuthGraphqlDenial, BetterAuthGraphqlInternalError, BetterAuthGraphqlRepeatedInternalError, apolloTransport, mercuriusSubscriptionContext, mercuriusTransport };
502
+
503
+ //# sourceMappingURL=graphql.mjs.map