@leaven-graphql/nestjs 0.1.0 → 0.2.1
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 +1 -1
- package/README.md +408 -23
- package/dist/decorators.d.ts +92 -3
- package/dist/decorators.d.ts.map +1 -1
- package/dist/driver.d.ts +107 -8
- package/dist/driver.d.ts.map +1 -1
- package/dist/execution-context.d.ts +46 -2
- package/dist/execution-context.d.ts.map +1 -1
- package/dist/graphql-driver.d.ts +180 -0
- package/dist/graphql-driver.d.ts.map +1 -0
- package/dist/guards.d.ts +57 -11
- package/dist/guards.d.ts.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1577 -792
- package/dist/interceptors.d.ts +41 -5
- package/dist/interceptors.d.ts.map +1 -1
- package/dist/middleware.d.ts +100 -4
- package/dist/middleware.d.ts.map +1 -1
- package/dist/module.d.ts +77 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/schema-builder.d.ts +39 -10
- package/dist/schema-builder.d.ts.map +1 -1
- package/dist/subscriptions.d.ts +346 -22
- package/dist/subscriptions.d.ts.map +1 -1
- package/dist/types.d.ts +188 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -12
package/dist/interceptors.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @leaven-graphql/nestjs - Interceptors
|
|
3
3
|
*
|
|
4
|
-
* Copyright 2026
|
|
4
|
+
* Copyright 2026 Joseph Quinn
|
|
5
5
|
* Licensed under the Apache License, Version 2.0
|
|
6
6
|
*/
|
|
7
7
|
import { type NestInterceptor, type ExecutionContext, type CallHandler } from '@nestjs/common';
|
|
@@ -10,7 +10,9 @@ import { Reflector } from '@nestjs/core';
|
|
|
10
10
|
/**
|
|
11
11
|
* Logging interceptor for GraphQL operations
|
|
12
12
|
*
|
|
13
|
-
* Logs timing and operation information for debugging.
|
|
13
|
+
* Logs timing and operation information for debugging. Successful
|
|
14
|
+
* resolutions are logged via `console.log`; failures are logged via
|
|
15
|
+
* `console.error` with the error attached, then rethrown unchanged.
|
|
14
16
|
*
|
|
15
17
|
* @example
|
|
16
18
|
* ```typescript
|
|
@@ -27,7 +29,12 @@ export declare class LoggingInterceptor implements NestInterceptor {
|
|
|
27
29
|
/**
|
|
28
30
|
* Error formatting interceptor
|
|
29
31
|
*
|
|
30
|
-
* Catches errors and formats them consistently
|
|
32
|
+
* Catches errors and formats them consistently by delegating to
|
|
33
|
+
* `@leaven-graphql/errors`. Leaven errors keep their message and error
|
|
34
|
+
* code; unexpected errors are masked in production (message replaced,
|
|
35
|
+
* code set to `INTERNAL_ERROR`) and carry their stack trace in
|
|
36
|
+
* `extensions.stackTrace` in development. The caught error is never
|
|
37
|
+
* mutated — a new `GraphQLError` is thrown instead.
|
|
31
38
|
*
|
|
32
39
|
* @example
|
|
33
40
|
* ```typescript
|
|
@@ -42,13 +49,35 @@ export declare class ErrorFormattingInterceptor implements NestInterceptor {
|
|
|
42
49
|
intercept(_context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
43
50
|
/**
|
|
44
51
|
* Format an error for GraphQL response
|
|
52
|
+
*
|
|
53
|
+
* Returns a new `GraphQLError` built from the formatted representation
|
|
54
|
+
* rather than mutating the input error.
|
|
55
|
+
*
|
|
56
|
+
* `GraphQLError` derives `locations` from the `nodes`, or the
|
|
57
|
+
* `source`/`positions`, handed to its constructor — never from a `locations`
|
|
58
|
+
* field — so those are carried over from the converted error. Without them a
|
|
59
|
+
* client would lose the source position that the driver's own formatting
|
|
60
|
+
* path (`formatError`) preserves. A masked error reports no locations, and
|
|
61
|
+
* must not leak them here either.
|
|
45
62
|
*/
|
|
46
63
|
private formatError;
|
|
47
64
|
}
|
|
48
65
|
/**
|
|
49
66
|
* Complexity tracking interceptor
|
|
50
67
|
*
|
|
51
|
-
* Tracks query complexity for monitoring.
|
|
68
|
+
* Tracks query complexity for monitoring. Field complexity declared via
|
|
69
|
+
* `@Complexity()` is accumulated onto the request context's
|
|
70
|
+
* `_resolvedFieldComplexity` key, so multiple fields resolved in one request
|
|
71
|
+
* sum rather than overwrite each other.
|
|
72
|
+
*
|
|
73
|
+
* This measurement is **observational only**. It deliberately does not touch
|
|
74
|
+
* `_queryComplexity`, the key the driver assigns per request and
|
|
75
|
+
* `ComplexityGuard` compares: NestJS runs guards before interceptors, so a
|
|
76
|
+
* value accumulated here can never influence the guard for its own request,
|
|
77
|
+
* and writing to that key would only corrupt the driver's static estimate —
|
|
78
|
+
* making later fields of a query answer for work they did not do. Read
|
|
79
|
+
* `_resolvedFieldComplexity` from logging, metrics, or a plugin after
|
|
80
|
+
* execution.
|
|
52
81
|
*
|
|
53
82
|
* @example
|
|
54
83
|
* ```typescript
|
|
@@ -71,7 +100,14 @@ export declare class ComplexityInterceptor implements NestInterceptor {
|
|
|
71
100
|
/**
|
|
72
101
|
* Caching interceptor
|
|
73
102
|
*
|
|
74
|
-
*
|
|
103
|
+
* Forwards a `@CacheHint()` to `info.cacheControl.setCacheHint()`.
|
|
104
|
+
*
|
|
105
|
+
* @deprecated Has no effect; removal target 0.3.0. `info.cacheControl` is an
|
|
106
|
+
* Apollo Server construct, and nothing in Leaven's execution path attaches it,
|
|
107
|
+
* so in every supported configuration this interceptor does nothing and
|
|
108
|
+
* `@CacheHint` has no observable effect. Emit `Cache-Control` from the HTTP
|
|
109
|
+
* layer instead. Retained only so existing configurations keep compiling, and
|
|
110
|
+
* so a resolver executed under an Apollo-compatible `info` still gets its hint.
|
|
75
111
|
*
|
|
76
112
|
* @example
|
|
77
113
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAA+B,MAAM,MAAM,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAA+B,MAAM,MAAM,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMzC;;;;;;;;;;;;;;;GAeG;AACH,qBACa,kBAAmB,YAAW,eAAe;IACjD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAiBpF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,0BAA2B,YAAW,eAAe;IACzD,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;IAUpF;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,WAAW;CAiBpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBACa,qBAAsB,YAAW,eAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAE1C,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAqBpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,kBAAmB,YAAW,eAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAE1C,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAuBpF;AAED;;;;;;;;;;;;;GAaG;AACH,qBACa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAExD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;IAmBnF;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;OAEG;IACI,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAIlD;;OAEG;IACI,UAAU,IAAI,cAAc,EAAE;IASrC;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @leaven-graphql/nestjs - Middleware
|
|
3
3
|
*
|
|
4
|
-
* Copyright 2026
|
|
4
|
+
* Copyright 2026 Joseph Quinn
|
|
5
5
|
* Licensed under the Apache License, Version 2.0
|
|
6
6
|
*/
|
|
7
7
|
import { type NestMiddleware, type Type } from '@nestjs/common';
|
|
8
8
|
interface Request {
|
|
9
9
|
method: string;
|
|
10
10
|
path: string;
|
|
11
|
+
/** Full URL including the query string, as populated by Express */
|
|
12
|
+
originalUrl?: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
secure?: boolean;
|
|
11
15
|
body?: Record<string, unknown>;
|
|
12
16
|
headers: Record<string, string | string[] | undefined>;
|
|
13
17
|
}
|
|
@@ -26,6 +30,24 @@ import type { LeavenModuleOptions } from './types';
|
|
|
26
30
|
*
|
|
27
31
|
* This middleware intercepts requests to the GraphQL endpoint
|
|
28
32
|
* and processes them through the Leaven driver.
|
|
33
|
+
*
|
|
34
|
+
* ## Scope of the transport this middleware implements
|
|
35
|
+
*
|
|
36
|
+
* It calls {@link LeavenDriver.execute} directly and deliberately does NOT go
|
|
37
|
+
* through {@link LeavenDriver.handleRequest}, which is an alternative
|
|
38
|
+
* Fetch-native entry point for callers that already hold a `Request`/`Response`
|
|
39
|
+
* pair (a Bun `fetch` handler, for example). Two consequences follow, and both
|
|
40
|
+
* are intentional rather than oversights:
|
|
41
|
+
*
|
|
42
|
+
* - Only `POST` with a JSON body is served. `GET ?query=` is reserved for the
|
|
43
|
+
* playground, and `application/graphql` bodies — which `handleRequest`'s
|
|
44
|
+
* parser does support — are not accepted here.
|
|
45
|
+
* - The context's `req`/`res` are the **Express** request and response, not the
|
|
46
|
+
* Fetch `Request`/`Response` that `handleRequest` stores. This is what makes
|
|
47
|
+
* `ctx.req.user` work under Passport. See {@link GqlContext} for the full
|
|
48
|
+
* contract; a resolver that must work behind either entry point should read
|
|
49
|
+
* values placed on the context by the `context` factory rather than reaching
|
|
50
|
+
* into `ctx.req`.
|
|
29
51
|
*/
|
|
30
52
|
export declare class GraphQLMiddleware implements NestMiddleware {
|
|
31
53
|
private readonly driver;
|
|
@@ -40,7 +62,10 @@ export declare class GraphQLMiddleware implements NestMiddleware {
|
|
|
40
62
|
*/
|
|
41
63
|
private handleGraphQLRequest;
|
|
42
64
|
/**
|
|
43
|
-
* Serve
|
|
65
|
+
* Serve GraphiQL HTML
|
|
66
|
+
*
|
|
67
|
+
* Delegates to `@leaven-graphql/playground`, which owns the template and
|
|
68
|
+
* its escaping, rather than maintaining a second copy here.
|
|
44
69
|
*/
|
|
45
70
|
private servePlayground;
|
|
46
71
|
/**
|
|
@@ -48,9 +73,80 @@ export declare class GraphQLMiddleware implements NestMiddleware {
|
|
|
48
73
|
*/
|
|
49
74
|
private handleCorsPreFlight;
|
|
50
75
|
/**
|
|
51
|
-
*
|
|
76
|
+
* Resolve the effective CORS configuration, or `null` when this middleware
|
|
77
|
+
* must not emit CORS headers at all.
|
|
78
|
+
*
|
|
79
|
+
* CORS is **opt-in**, matching the `cors` option's documented "Enable CORS"
|
|
80
|
+
* semantics: leaving it unset emits no `Access-Control-*` headers and leaves
|
|
81
|
+
* `OPTIONS` preflights to the application. Only an explicit `true` (or an
|
|
82
|
+
* options object) turns it on — a stock `LeavenModule.forRoot({ schema })`
|
|
83
|
+
* must never answer every GraphQL POST with `Access-Control-Allow-Origin: *`.
|
|
84
|
+
* `false` is equivalent to unset and is accepted for explicitness.
|
|
85
|
+
*/
|
|
86
|
+
private resolveCorsOptions;
|
|
87
|
+
/**
|
|
88
|
+
* Apply CORS headers to a response
|
|
89
|
+
*
|
|
90
|
+
* Called for both preflight (OPTIONS) responses and actual GraphQL
|
|
91
|
+
* responses — browsers require `Access-Control-Allow-Origin` on the
|
|
92
|
+
* actual response as well as the preflight. No-op when CORS was not
|
|
93
|
+
* enabled (see {@link resolveCorsOptions}).
|
|
94
|
+
*
|
|
95
|
+
* The allowed origin is *reflected*, never defaulted to `*` when an
|
|
96
|
+
* allowlist is configured: `origin: false` emits no origin header at all,
|
|
97
|
+
* an array emits the request's `Origin` only when the allowlist contains
|
|
98
|
+
* it, and `origin: true` echoes the request's `Origin`. `Vary: Origin` is
|
|
99
|
+
* emitted whenever the value depends on the request so caches cannot serve
|
|
100
|
+
* one origin's response to another, and `*` is never paired with
|
|
101
|
+
* `credentials: true` (browsers reject that combination outright).
|
|
102
|
+
*/
|
|
103
|
+
private applyCorsHeaders;
|
|
104
|
+
/**
|
|
105
|
+
* Resolve the `Access-Control-Allow-Origin` value for a request
|
|
106
|
+
*
|
|
107
|
+
* Returns `value: undefined` to mean "emit no origin header", and
|
|
108
|
+
* `varies: true` when the value was derived from the request's `Origin`
|
|
109
|
+
* header and therefore requires `Vary: Origin`.
|
|
110
|
+
*/
|
|
111
|
+
private resolveAllowedOrigin;
|
|
112
|
+
/**
|
|
113
|
+
* Adapt an Express-style request into a Fetch API `Request`
|
|
114
|
+
*
|
|
115
|
+
* The `ContextFactory` contract (types.ts) is declared against the global
|
|
116
|
+
* Fetch API types, and `driver.createContext` passes genuine Fetch objects.
|
|
117
|
+
* Adapting here keeps that contract intact **for the factory's first
|
|
118
|
+
* parameter only**, so factories may call `request.headers.get()`,
|
|
119
|
+
* `request.json()`, or read `request.url` regardless of how the request
|
|
120
|
+
* arrived.
|
|
121
|
+
*
|
|
122
|
+
* The factory's second parameter is NOT adapted: it is the transport-native
|
|
123
|
+
* response object, which under this middleware is the Express response.
|
|
124
|
+
* `response.status(...)` is therefore a method rather than a number and
|
|
125
|
+
* `response.headers` does not exist — use `response.setHeader(name, value)`
|
|
126
|
+
* when writing a factory that must work behind `GraphQLMiddleware`.
|
|
127
|
+
*
|
|
128
|
+
* The URL's authority is never taken from an untrusted `Host` header
|
|
129
|
+
* unchecked: `options.publicUrl` wins when configured, otherwise `Host` is
|
|
130
|
+
* accepted only if it looks like a plain authority, and anything else falls
|
|
131
|
+
* back to the canonical default. A factory resolving tenancy from
|
|
132
|
+
* `new URL(request.url).hostname` therefore cannot be steered by a
|
|
133
|
+
* spoofed header, and a hostile value cannot make `new Request()` throw
|
|
134
|
+
* and turn every request into a 500.
|
|
135
|
+
*/
|
|
136
|
+
private toFetchRequest;
|
|
137
|
+
/**
|
|
138
|
+
* Resolve the origin (scheme + authority) for the synthesized request URL
|
|
139
|
+
*
|
|
140
|
+
* A configured `publicUrl` always wins; otherwise the `Host` header is used
|
|
141
|
+
* only when it is a plain authority, and anything else falls back to the
|
|
142
|
+
* canonical origin.
|
|
143
|
+
*/
|
|
144
|
+
private resolveOrigin;
|
|
145
|
+
/**
|
|
146
|
+
* The trusted origin used when no configured or trustworthy authority is
|
|
147
|
+
* available
|
|
52
148
|
*/
|
|
53
|
-
private
|
|
149
|
+
private canonicalOrigin;
|
|
54
150
|
}
|
|
55
151
|
/**
|
|
56
152
|
* Create middleware module with proper configuration
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;AAKxB,UAAU,OAAO;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;CACxD;AAED,UAAU,QAAQ;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACjD,GAAG,IAAI,QAAQ,CAAC;CACjB;AAED,KAAK,YAAY,GAAG,MAAM,IAAI,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAUhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,iBAAkB,YAAW,cAAc;IAE7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADf,MAAM,EAAE,YAAY,EACZ,OAAO,EAAE,mBAAmB;IAG9E;;OAEG;IACU,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiChF;;OAEG;YACW,oBAAoB;IA4DlC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,gBAAgB;IAiDxB;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IA2C5B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,OAAO,CAAC,cAAc;IAoCtB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAarB;;;OAGG;IACH,OAAO,CAAC,eAAe;CAIxB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAAC,cAAc,CAAC,CAE9D"}
|
package/dist/module.d.ts
CHANGED
|
@@ -1,25 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @leaven-graphql/nestjs - NestJS Module
|
|
3
3
|
*
|
|
4
|
-
* Copyright 2026
|
|
4
|
+
* Copyright 2026 Joseph Quinn
|
|
5
5
|
* Licensed under the Apache License, Version 2.0
|
|
6
6
|
*/
|
|
7
|
-
import { DynamicModule } from '@nestjs/common';
|
|
8
|
-
import type
|
|
7
|
+
import { DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common';
|
|
8
|
+
import { LEAVEN_MODULE_OPTIONS, LEAVEN_DRIVER, LEAVEN_PUBSUB, type LeavenModuleOptions, type LeavenModuleAsyncOptions } from './types';
|
|
9
9
|
/**
|
|
10
|
-
* Injection
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
10
|
+
* Injection tokens for the Leaven module options and driver.
|
|
11
|
+
*
|
|
12
|
+
* Defined in `./types` (see the note there) and re-exported here so that
|
|
13
|
+
* existing `import { LEAVEN_MODULE_OPTIONS, LEAVEN_DRIVER } from './module'`
|
|
14
|
+
* sites keep working.
|
|
15
15
|
*/
|
|
16
|
-
export
|
|
16
|
+
export { LEAVEN_MODULE_OPTIONS, LEAVEN_DRIVER, LEAVEN_PUBSUB };
|
|
17
17
|
/**
|
|
18
18
|
* Leaven GraphQL Module for NestJS
|
|
19
19
|
*
|
|
20
20
|
* This module provides integration between NestJS and Leaven GraphQL.
|
|
21
21
|
* It can be used with both schema-first and code-first approaches.
|
|
22
22
|
*
|
|
23
|
+
* Configuring the module via {@link forRoot} or {@link forRootAsync}
|
|
24
|
+
* registers the {@link LeavenDriver}, the {@link SchemaBuilderService}
|
|
25
|
+
* (which builds the schema from `schema` or `typeDefs`/`resolvers` and
|
|
26
|
+
* hands it to the driver), the {@link SubscriptionManager}, and the
|
|
27
|
+
* {@link GraphQLMiddleware} serving the HTTP endpoint, which is applied
|
|
28
|
+
* automatically at `options.path` (default `/graphql`).
|
|
29
|
+
*
|
|
30
|
+
* ## What this module does NOT wire
|
|
31
|
+
*
|
|
32
|
+
* - **The WebSocket transport.** {@link SubscriptionManager} is registered as a
|
|
33
|
+
* provider, but registering it does not open a socket: opening one requires
|
|
34
|
+
* `server.upgrade()` on the underlying HTTP server, and this module only has
|
|
35
|
+
* a `MiddlewareConsumer`, which cannot express an upgrade route. The manager
|
|
36
|
+
* deliberately owns the graphql-ws protocol and nothing else. Callers
|
|
37
|
+
* register the upgrade route at `subscriptions.path` themselves and hand each
|
|
38
|
+
* socket to the manager — see the package README's "Wiring the WebSocket
|
|
39
|
+
* transport".
|
|
40
|
+
* - **The NestJS execution pipeline around resolvers.** Resolvers supplied via
|
|
41
|
+
* `resolvers` (or baked into a pre-built `schema`) are plain functions
|
|
42
|
+
* invoked by graphql-js, not Nest handlers, so `@UseGuards`,
|
|
43
|
+
* `@UseInterceptors`, and parameter decorators such as `@Args()` never fire
|
|
44
|
+
* for them. That requires a `@nestjs/graphql` `AbstractGraphQLDriver` bridge,
|
|
45
|
+
* which this package does not ship. `maxComplexity` is unaffected — the
|
|
46
|
+
* executor enforces it directly — but `maxDepth`, which is only surfaced for
|
|
47
|
+
* {@link DepthGuard}, is not enforced on this path.
|
|
48
|
+
*
|
|
23
49
|
* @example
|
|
24
50
|
* ```typescript
|
|
25
51
|
* // Schema-first approach
|
|
@@ -59,17 +85,56 @@ export declare const LEAVEN_DRIVER = "LEAVEN_DRIVER";
|
|
|
59
85
|
* export class AppModule {}
|
|
60
86
|
* ```
|
|
61
87
|
*/
|
|
62
|
-
export declare class LeavenModule {
|
|
88
|
+
export declare class LeavenModule implements NestModule {
|
|
89
|
+
private readonly options?;
|
|
90
|
+
constructor(options?: LeavenModuleOptions | undefined);
|
|
63
91
|
/**
|
|
64
|
-
*
|
|
92
|
+
* Register the {@link GraphQLMiddleware} at the configured GraphQL
|
|
93
|
+
* endpoint (`options.path`, default `/graphql`).
|
|
94
|
+
*
|
|
95
|
+
* Called automatically by NestJS during application initialization. When
|
|
96
|
+
* the module is imported without `forRoot()`/`forRootAsync()` no options
|
|
97
|
+
* provider exists (and no GraphQL providers are registered), so nothing
|
|
98
|
+
* is wired.
|
|
99
|
+
*/
|
|
100
|
+
configure(consumer: MiddlewareConsumer): void;
|
|
101
|
+
/**
|
|
102
|
+
* Configure the module synchronously.
|
|
103
|
+
*
|
|
104
|
+
* Registers the options and driver providers along with the
|
|
105
|
+
* {@link SchemaBuilderService}, {@link SubscriptionManager}, and
|
|
106
|
+
* {@link GraphQLMiddleware} so that importing this module yields a
|
|
107
|
+
* working GraphQL endpoint.
|
|
65
108
|
*/
|
|
66
109
|
static forRoot(options?: LeavenModuleOptions): DynamicModule;
|
|
67
110
|
/**
|
|
68
|
-
*
|
|
111
|
+
* Build the providers backing {@link ComplexityGuard} and
|
|
112
|
+
* {@link DepthGuard}.
|
|
113
|
+
*
|
|
114
|
+
* The guards inject their limits by token, so the tokens must resolve
|
|
115
|
+
* even when the corresponding option is absent; `Infinity` expresses
|
|
116
|
+
* "no limit" without the guards having to special-case `undefined`.
|
|
117
|
+
*/
|
|
118
|
+
private static createLimitProviders;
|
|
119
|
+
/**
|
|
120
|
+
* Build the shared {@link PubSub} provider resolved by `@InjectPubSub()`.
|
|
121
|
+
*
|
|
122
|
+
* One instance per module so that a publisher and a subscriber in
|
|
123
|
+
* different providers reach the same topics.
|
|
124
|
+
*/
|
|
125
|
+
private static createPubSubProvider;
|
|
126
|
+
/**
|
|
127
|
+
* Configure the module asynchronously.
|
|
128
|
+
*
|
|
129
|
+
* Registers the same providers as {@link forRoot}, with the options
|
|
130
|
+
* resolved via `useFactory`, `useClass`, or `useExisting`.
|
|
69
131
|
*/
|
|
70
132
|
static forRootAsync(options: LeavenModuleAsyncOptions): DynamicModule;
|
|
71
133
|
/**
|
|
72
134
|
* Create async providers based on configuration
|
|
135
|
+
*
|
|
136
|
+
* @throws Error when none of `useFactory`, `useClass`, or `useExisting`
|
|
137
|
+
* is supplied.
|
|
73
138
|
*/
|
|
74
139
|
private static createAsyncProviders;
|
|
75
140
|
/**
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,aAAa,
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,aAAa,EAKb,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAE9B,MAAM,SAAS,CAAC;AAQjB;;;;;;GAMG;AACH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,qBAEa,YAAa,YAAW,UAAU;IAI3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAR,OAAO,CAAC,EAAE,mBAAmB,YAAA;IAGhD;;;;;;;;OAQG;IACI,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAUpD;;;;;;;OAOG;WACW,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa;IAmCvE;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAiBnC;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IASnC;;;;;OAKG;WACW,YAAY,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa;IAiC5E;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAuBnC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;CAsB1C"}
|
package/dist/schema-builder.d.ts
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @leaven-graphql/nestjs - Schema Builder Integration
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Builds the module's `GraphQLSchema` from a pre-built `schema` or from SDL
|
|
5
|
+
* `typeDefs` (optionally merged with a `resolvers` map) and hands it to the
|
|
6
|
+
* driver. Code-first generation (`autoSchemaFile`) is not implemented and
|
|
7
|
+
* fails at bootstrap rather than silently.
|
|
5
8
|
*
|
|
6
|
-
* Copyright 2026
|
|
9
|
+
* Copyright 2026 Joseph Quinn
|
|
7
10
|
* Licensed under the Apache License, Version 2.0
|
|
8
11
|
*/
|
|
9
12
|
import { type OnModuleInit, type Type } from '@nestjs/common';
|
|
10
|
-
import type
|
|
13
|
+
import { type DocumentNode, type GraphQLSchema } from 'graphql';
|
|
11
14
|
import { LeavenDriver } from './driver';
|
|
12
15
|
import type { LeavenModuleOptions, BuildSchemaOptions } from './types';
|
|
16
|
+
/**
|
|
17
|
+
* Resolver map as accepted by {@link LeavenModuleOptions.resolvers}.
|
|
18
|
+
*/
|
|
19
|
+
type ResolverMap = Record<string, unknown> | Array<Record<string, unknown>>;
|
|
13
20
|
/**
|
|
14
21
|
* Schema source type - determines how to build the schema
|
|
22
|
+
*
|
|
23
|
+
* {@link SchemaBuilderService.buildSchema} narrows on a value of this type,
|
|
24
|
+
* so every supported configuration is enumerated here exactly once.
|
|
15
25
|
*/
|
|
16
26
|
export type SchemaSource = {
|
|
17
27
|
type: 'provided';
|
|
18
28
|
schema: GraphQLSchema;
|
|
19
29
|
} | {
|
|
20
30
|
type: 'typeDefs';
|
|
21
|
-
typeDefs: string
|
|
22
|
-
resolvers
|
|
31
|
+
typeDefs: string | DocumentNode | Array<string | DocumentNode>;
|
|
32
|
+
resolvers?: ResolverMap;
|
|
23
33
|
} | {
|
|
24
34
|
type: 'autoSchema';
|
|
25
35
|
options: BuildSchemaOptions;
|
|
@@ -39,22 +49,36 @@ export declare class SchemaBuilderService implements OnModuleInit {
|
|
|
39
49
|
* Initialize the schema on module init
|
|
40
50
|
*/
|
|
41
51
|
onModuleInit(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Classify the configured options into a {@link SchemaSource}.
|
|
54
|
+
*
|
|
55
|
+
* `schema` wins over `typeDefs`, which wins over `autoSchemaFile`.
|
|
56
|
+
* Returns `null` when no schema source is configured at all.
|
|
57
|
+
*/
|
|
58
|
+
private resolveSchemaSource;
|
|
42
59
|
/**
|
|
43
60
|
* Build the schema from configured sources
|
|
61
|
+
*
|
|
62
|
+
* @throws {Error} When only `autoSchemaFile` is configured. Leaven has no
|
|
63
|
+
* code-first pipeline, so returning `null` here would leave the driver
|
|
64
|
+
* without a schema and fail every request at runtime; failing at bootstrap
|
|
65
|
+
* points at the actual misconfiguration instead.
|
|
44
66
|
*/
|
|
45
67
|
buildSchema(): Promise<GraphQLSchema | null>;
|
|
46
68
|
/**
|
|
47
69
|
* Build schema from type definitions (SDL)
|
|
70
|
+
*
|
|
71
|
+
* SDL alone is a complete schema and is built with graphql-js directly.
|
|
72
|
+
* When a resolver map is supplied it is merged in with
|
|
73
|
+
* `makeExecutableSchema`, after which any `@Description`/`@Deprecated`
|
|
74
|
+
* metadata recorded on the resolver functions is applied to the matching
|
|
75
|
+
* schema fields.
|
|
48
76
|
*/
|
|
49
77
|
private buildFromTypeDefs;
|
|
50
78
|
/**
|
|
51
|
-
*
|
|
79
|
+
* Normalize type definitions to a single SDL string
|
|
52
80
|
*/
|
|
53
81
|
private mergeTypeDefs;
|
|
54
|
-
/**
|
|
55
|
-
* Merge multiple resolver objects
|
|
56
|
-
*/
|
|
57
|
-
private mergeResolvers;
|
|
58
82
|
/**
|
|
59
83
|
* Get the built schema
|
|
60
84
|
*/
|
|
@@ -87,6 +111,10 @@ export interface SchemaFileOptions {
|
|
|
87
111
|
}
|
|
88
112
|
/**
|
|
89
113
|
* Generate a schema file from the current schema
|
|
114
|
+
*
|
|
115
|
+
* Creates the parent directory if it does not exist. When
|
|
116
|
+
* `includeDescriptions` is `false`, all type, field, and argument
|
|
117
|
+
* descriptions are stripped from the emitted SDL.
|
|
90
118
|
*/
|
|
91
119
|
export declare function generateSchemaFile(schema: GraphQLSchema, options: SchemaFileOptions): Promise<void>;
|
|
92
120
|
/**
|
|
@@ -116,4 +144,5 @@ export declare function registerResolverMetadata(metadata: ResolverMetadata): vo
|
|
|
116
144
|
* Clear resolver metadata (for testing)
|
|
117
145
|
*/
|
|
118
146
|
export declare function clearResolverMetadata(): void;
|
|
147
|
+
export {};
|
|
119
148
|
//# sourceMappingURL=schema-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-builder.d.ts","sourceRoot":"","sources":["../src/schema-builder.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schema-builder.d.ts","sourceRoot":"","sources":["../src/schema-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAc,KAAK,YAAY,EAAU,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAOL,KAAK,YAAY,EAGjB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEvE;;GAEG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAC3C;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC;IAC/D,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB,GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAExD;;;;;GAKG;AACH,qBACa,oBAAqB,YAAW,YAAY;IAItB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJhD,OAAO,CAAC,WAAW,CAA8B;gBAGC,OAAO,EAAE,mBAAmB,EACpC,MAAM,EAAE,YAAY;IAG9D;;OAEG;IACU,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;;;;;;OAOG;IACU,WAAW,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAqBzD;;;;;;;;OAQG;YACW,iBAAiB;IAqB/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAiBrB;;OAEG;IACI,SAAS,IAAI,aAAa,GAAG,IAAI;IAIxC;;OAEG;IACI,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAK7C;;OAEG;IACI,aAAa,IAAI,OAAO;CAGhC;AA2ED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAmBD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,cAAc,GAAG,OAAO,CAAC;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;IACnC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;QAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;CACJ;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,EAAE,CAExD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEzE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|