@nestjs-kit/better-auth 0.0.0-stage → 2.0.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.
- package/LICENSE +7 -0
- package/README.md +1078 -2
- package/dist/admin.cjs +88 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +14 -0
- package/dist/admin.d.cts.map +1 -0
- package/dist/admin.d.mts +14 -0
- package/dist/admin.d.mts.map +1 -0
- package/dist/admin.mjs +85 -0
- package/dist/admin.mjs.map +1 -0
- package/dist/api-key.cjs +164 -0
- package/dist/api-key.cjs.map +1 -0
- package/dist/api-key.d.cts +42 -0
- package/dist/api-key.d.cts.map +1 -0
- package/dist/api-key.d.mts +42 -0
- package/dist/api-key.d.mts.map +1 -0
- package/dist/api-key.mjs +160 -0
- package/dist/api-key.mjs.map +1 -0
- package/dist/auth-contracts-Brh_Qko9.d.cts +1654 -0
- package/dist/auth-contracts-Brh_Qko9.d.cts.map +1 -0
- package/dist/auth-contracts-Cz7C4_Ch.d.mts +1654 -0
- package/dist/auth-contracts-Cz7C4_Ch.d.mts.map +1 -0
- package/dist/auth-decorators-B1mFnGJ6.mjs +284 -0
- package/dist/auth-decorators-B1mFnGJ6.mjs.map +1 -0
- package/dist/auth-decorators-Cu_nxWnF.cjs +421 -0
- package/dist/auth-decorators-Cu_nxWnF.cjs.map +1 -0
- package/dist/auth-errors-C3rbTV9p.mjs +301 -0
- package/dist/auth-errors-C3rbTV9p.mjs.map +1 -0
- package/dist/auth-errors-DmiKl0L_.cjs +378 -0
- package/dist/auth-errors-DmiKl0L_.cjs.map +1 -0
- package/dist/auth-guard-CLyhAEEj.cjs +136 -0
- package/dist/auth-guard-CLyhAEEj.cjs.map +1 -0
- package/dist/auth-guard-h9QB_l11.mjs +125 -0
- package/dist/auth-guard-h9QB_l11.mjs.map +1 -0
- package/dist/auth-module-BgcY2HpA.cjs +2809 -0
- package/dist/auth-module-BgcY2HpA.cjs.map +1 -0
- package/dist/auth-module-CtHx3gRU.mjs +2708 -0
- package/dist/auth-module-CtHx3gRU.mjs.map +1 -0
- package/dist/auth-scope-interceptor-BjxAL1-S.cjs +290 -0
- package/dist/auth-scope-interceptor-BjxAL1-S.cjs.map +1 -0
- package/dist/auth-scope-interceptor-DYPn3b8M.mjs +231 -0
- package/dist/auth-scope-interceptor-DYPn3b8M.mjs.map +1 -0
- package/dist/bridge-protocol-BDw8opAG.cjs +25 -0
- package/dist/bridge-protocol-BDw8opAG.cjs.map +1 -0
- package/dist/bridge-protocol-c66aEkr5.mjs +8 -0
- package/dist/bridge-protocol-c66aEkr5.mjs.map +1 -0
- package/dist/decorate-Cr4Q7bNE.cjs +319 -0
- package/dist/decorate-Cr4Q7bNE.cjs.map +1 -0
- package/dist/decorate-Dt0e9K6R.mjs +80 -0
- package/dist/decorate-Dt0e9K6R.mjs.map +1 -0
- package/dist/express.cjs +256 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +37 -0
- package/dist/express.d.cts.map +1 -0
- package/dist/express.d.mts +37 -0
- package/dist/express.d.mts.map +1 -0
- package/dist/express.mjs +254 -0
- package/dist/express.mjs.map +1 -0
- package/dist/fastify.cjs +218 -0
- package/dist/fastify.cjs.map +1 -0
- package/dist/fastify.d.cts +28 -0
- package/dist/fastify.d.cts.map +1 -0
- package/dist/fastify.d.mts +28 -0
- package/dist/fastify.d.mts.map +1 -0
- package/dist/fastify.mjs +216 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/graphql.cjs +509 -0
- package/dist/graphql.cjs.map +1 -0
- package/dist/graphql.d.cts +38 -0
- package/dist/graphql.d.cts.map +1 -0
- package/dist/graphql.d.mts +38 -0
- package/dist/graphql.d.mts.map +1 -0
- package/dist/graphql.mjs +503 -0
- package/dist/graphql.mjs.map +1 -0
- package/dist/index.cjs +86 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +8 -0
- package/dist/microservices.cjs +231 -0
- package/dist/microservices.cjs.map +1 -0
- package/dist/microservices.d.cts +39 -0
- package/dist/microservices.d.cts.map +1 -0
- package/dist/microservices.d.mts +39 -0
- package/dist/microservices.d.mts.map +1 -0
- package/dist/microservices.mjs +222 -0
- package/dist/microservices.mjs.map +1 -0
- package/dist/organization.cjs +191 -0
- package/dist/organization.cjs.map +1 -0
- package/dist/organization.d.cts +40 -0
- package/dist/organization.d.cts.map +1 -0
- package/dist/organization.d.mts +40 -0
- package/dist/organization.d.mts.map +1 -0
- package/dist/organization.mjs +177 -0
- package/dist/organization.mjs.map +1 -0
- package/dist/platform-CZl7TY8j.mjs +414 -0
- package/dist/platform-CZl7TY8j.mjs.map +1 -0
- package/dist/platform-YICqqYv6.cjs +473 -0
- package/dist/platform-YICqqYv6.cjs.map +1 -0
- package/dist/platform.cjs +10 -0
- package/dist/platform.d.cts +43 -0
- package/dist/platform.d.cts.map +1 -0
- package/dist/platform.d.mts +43 -0
- package/dist/platform.d.mts.map +1 -0
- package/dist/platform.mjs +1 -0
- package/dist/plugin.cjs +323 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +24 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +24 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +321 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/principal-readings-Chmt6rQV.cjs +208 -0
- package/dist/principal-readings-Chmt6rQV.cjs.map +1 -0
- package/dist/principal-readings-Ied2staw.mjs +191 -0
- package/dist/principal-readings-Ied2staw.mjs.map +1 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/testing/conformance.cjs +6214 -0
- package/dist/testing/conformance.cjs.map +1 -0
- package/dist/testing/conformance.d.cts +528 -0
- package/dist/testing/conformance.d.cts.map +1 -0
- package/dist/testing/conformance.d.mts +528 -0
- package/dist/testing/conformance.d.mts.map +1 -0
- package/dist/testing/conformance.mjs +6204 -0
- package/dist/testing/conformance.mjs.map +1 -0
- package/dist/testing.cjs +221 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +64 -0
- package/dist/testing.d.cts.map +1 -0
- package/dist/testing.d.mts +64 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +214 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/websockets.cjs +396 -0
- package/dist/websockets.cjs.map +1 -0
- package/dist/websockets.d.cts +67 -0
- package/dist/websockets.d.cts.map +1 -0
- package/dist/websockets.d.mts +67 -0
- package/dist/websockets.d.mts.map +1 -0
- package/dist/websockets.mjs +383 -0
- package/dist/websockets.mjs.map +1 -0
- 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"}
|
package/dist/graphql.mjs
ADDED
|
@@ -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
|