@fluojs/graphql 1.1.0 → 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/README.ko.md +69 -21
- package/README.md +74 -21
- package/dist/dataloader/dataloader.d.ts.map +1 -1
- package/dist/dataloader/dataloader.js +2 -3
- package/dist/decorators.d.ts +14 -0
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +25 -4
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/instance-of-patch.d.ts +21 -0
- package/dist/instance-of-patch.d.ts.map +1 -0
- package/dist/instance-of-patch.js +126 -0
- package/dist/module.d.ts +14 -10
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +69 -14
- package/dist/node/graphql-websocket-transport.d.ts +17 -0
- package/dist/node/graphql-websocket-transport.d.ts.map +1 -1
- package/dist/node/graphql-websocket-transport.js +85 -22
- package/dist/pipeline/input-pipeline.js +1 -1
- package/dist/schema/object-field-resolvers.d.ts +5 -4
- package/dist/schema/object-field-resolvers.d.ts.map +1 -1
- package/dist/schema/object-field-resolvers.js +12 -4
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +3 -3
- package/dist/service.d.ts +9 -6
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +166 -170
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/transport/transport.js +1 -1
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -0
- package/package.json +11 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-of-patch.d.ts","sourceRoot":"","sources":["../src/instance-of-patch.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG;IAC1C,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC;KACxC,CAAC;CACH,CAAC;AAEF,oEAAoE;AACpE,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,kBAAkB,KAAK,OAAO,CAAC;AAE7F,iFAAiF;AACjF,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AA0IF;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,gBAAgB,EAAE,uBAAuB,EACzC,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,GAC9B,MAAM,IAAI,CAmCZ"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/** Represents a GraphQL constructor inspected by the private `instanceOf` helper. */
|
|
2
|
+
|
|
3
|
+
/** Represents the private GraphQL `instanceOf` helper signature. */
|
|
4
|
+
|
|
5
|
+
/** Represents the mutable private GraphQL module object that owns the helper. */
|
|
6
|
+
|
|
7
|
+
const graphqlInstanceOfPatchStateRegistryKey = Symbol.for('@fluojs/graphql.instance-of-patch-state-registry/v1');
|
|
8
|
+
function isGraphqlInstanceOfPatchStateRegistry(value) {
|
|
9
|
+
if (typeof value !== 'object' || value === null) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return Reflect.get(value, 'states') instanceof WeakMap;
|
|
13
|
+
}
|
|
14
|
+
function getGraphqlInstanceOfPatchStates() {
|
|
15
|
+
const registeredValue = Reflect.get(globalThis, graphqlInstanceOfPatchStateRegistryKey);
|
|
16
|
+
if (isGraphqlInstanceOfPatchStateRegistry(registeredValue)) {
|
|
17
|
+
return registeredValue.states;
|
|
18
|
+
}
|
|
19
|
+
const registry = {
|
|
20
|
+
states: new WeakMap()
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(globalThis, graphqlInstanceOfPatchStateRegistryKey, {
|
|
23
|
+
configurable: false,
|
|
24
|
+
enumerable: false,
|
|
25
|
+
value: registry,
|
|
26
|
+
writable: false
|
|
27
|
+
});
|
|
28
|
+
return registry.states;
|
|
29
|
+
}
|
|
30
|
+
function createGraphqlInstanceOfPatchState(originalInstanceOf) {
|
|
31
|
+
let patchState;
|
|
32
|
+
const allowedObjectSets = new Set();
|
|
33
|
+
const patchedInstanceOf = (value, constructor) => {
|
|
34
|
+
if (patchState.isEvaluatingDelegate) {
|
|
35
|
+
return isAllowedCrossRealmGraphqlObject(value, constructor, allowedObjectSets);
|
|
36
|
+
}
|
|
37
|
+
patchState.isEvaluatingDelegate = true;
|
|
38
|
+
try {
|
|
39
|
+
try {
|
|
40
|
+
if (patchState.originalInstanceOf(value, constructor)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (isAllowedCrossRealmGraphqlObject(value, constructor, allowedObjectSets)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
return isAllowedCrossRealmGraphqlObject(value, constructor, allowedObjectSets);
|
|
50
|
+
} finally {
|
|
51
|
+
patchState.isEvaluatingDelegate = false;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
patchState = {
|
|
55
|
+
allowedObjectSets,
|
|
56
|
+
isEvaluatingDelegate: false,
|
|
57
|
+
originalInstanceOf,
|
|
58
|
+
patchedInstanceOf
|
|
59
|
+
};
|
|
60
|
+
return patchState;
|
|
61
|
+
}
|
|
62
|
+
function getCrossRealmGraphqlTag(value, constructor) {
|
|
63
|
+
const prototypeTag = constructor.prototype?.[Symbol.toStringTag];
|
|
64
|
+
const className = typeof prototypeTag === 'string' ? prototypeTag : constructor.name;
|
|
65
|
+
if (typeof className !== 'string' || !className.startsWith('GraphQL')) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
if (typeof value !== 'object' || value === null) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const valueTag = Reflect.get(value, Symbol.toStringTag);
|
|
72
|
+
if (typeof valueTag === 'string') {
|
|
73
|
+
return valueTag === className ? className : undefined;
|
|
74
|
+
}
|
|
75
|
+
const valueConstructor = Reflect.get(value, 'constructor');
|
|
76
|
+
const valueClassName = typeof valueConstructor === 'object' && valueConstructor !== null || typeof valueConstructor === 'function' ? Reflect.get(valueConstructor, 'name') : undefined;
|
|
77
|
+
return typeof valueClassName === 'string' && valueClassName === className ? className : undefined;
|
|
78
|
+
}
|
|
79
|
+
function isAllowedCrossRealmGraphqlObject(value, constructor, allowedObjectSets) {
|
|
80
|
+
if (typeof value !== 'object' || value === null) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
for (const allowedObjects of allowedObjectSets) {
|
|
84
|
+
if (allowedObjects.has(value)) {
|
|
85
|
+
return getCrossRealmGraphqlTag(value, constructor) !== undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Installs and releases a cross-realm GraphQL `instanceOf` patch for one module object.
|
|
93
|
+
*
|
|
94
|
+
* @param instanceOfModule The GraphQL module object that owns the `instanceOf` helper.
|
|
95
|
+
* @param allowedObjects The active application's cross-realm GraphQL object allowlist.
|
|
96
|
+
* @returns A one-time release callback for the application's allowlist.
|
|
97
|
+
*/
|
|
98
|
+
export function installGraphqlInstanceOfPatch(instanceOfModule, allowedObjects) {
|
|
99
|
+
const patchStates = getGraphqlInstanceOfPatchStates();
|
|
100
|
+
let patchState = patchStates.get(instanceOfModule);
|
|
101
|
+
if (patchState === undefined) {
|
|
102
|
+
patchState = createGraphqlInstanceOfPatchState(instanceOfModule.instanceOf);
|
|
103
|
+
patchStates.set(instanceOfModule, patchState);
|
|
104
|
+
} else if (instanceOfModule.instanceOf !== patchState.patchedInstanceOf) {
|
|
105
|
+
patchState.originalInstanceOf = instanceOfModule.instanceOf;
|
|
106
|
+
}
|
|
107
|
+
instanceOfModule.instanceOf = patchState.patchedInstanceOf;
|
|
108
|
+
patchState.allowedObjectSets.add(allowedObjects);
|
|
109
|
+
let released = false;
|
|
110
|
+
return () => {
|
|
111
|
+
if (released) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
released = true;
|
|
115
|
+
patchState.allowedObjectSets.delete(allowedObjects);
|
|
116
|
+
if (patchState.allowedObjectSets.size > 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (instanceOfModule.instanceOf === patchState.patchedInstanceOf) {
|
|
120
|
+
instanceOfModule.instanceOf = patchState.originalInstanceOf;
|
|
121
|
+
}
|
|
122
|
+
if (patchStates.get(instanceOfModule) === patchState) {
|
|
123
|
+
patchStates.delete(instanceOfModule);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
package/dist/module.d.ts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InjectionToken } from '@fluojs/core';
|
|
2
2
|
import { type ModuleType } from '@fluojs/runtime';
|
|
3
|
-
import type { GraphqlModuleOptions } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Creates GraphQL runtime providers for module-level options and lifecycle wiring.
|
|
6
|
-
*
|
|
7
|
-
* @param options GraphQL module options used by the lifecycle service and endpoint controller.
|
|
8
|
-
* @returns Provider definitions that register only the internal options token and GraphQL lifecycle service; this helper
|
|
9
|
-
* does not register `GraphqlEndpointController` or mount the `/graphql` endpoint by itself.
|
|
10
|
-
*/
|
|
11
|
-
export declare function createGraphqlProviders(options: GraphqlModuleOptions): Provider[];
|
|
3
|
+
import type { GraphqlAsyncModuleOptions, GraphqlModuleOptions } from './types.js';
|
|
12
4
|
/**
|
|
13
5
|
* Represents the graphql module.
|
|
14
6
|
*/
|
|
@@ -21,5 +13,17 @@ export declare class GraphqlModule {
|
|
|
21
13
|
* module path (not `createGraphqlProviders(...)` alone) when the application should expose `/graphql`.
|
|
22
14
|
*/
|
|
23
15
|
static forRoot(options?: GraphqlModuleOptions): ModuleType;
|
|
16
|
+
/**
|
|
17
|
+
* Registers GraphQL from options resolved by explicitly injected application dependencies.
|
|
18
|
+
*
|
|
19
|
+
* The factory runs once in each application context. Only `inject` and `useFactory` are
|
|
20
|
+
* supported; NestJS-style `imports`, `useClass`, `useExisting`, and implicit discovery are rejected.
|
|
21
|
+
*
|
|
22
|
+
* @param options Injected dependency tokens and the factory that resolves GraphQL options.
|
|
23
|
+
* @returns A module definition that resolves GraphQL configuration before endpoint lifecycle wiring begins.
|
|
24
|
+
*
|
|
25
|
+
* @throws {TypeError} When the options shape requests unsupported registration behavior.
|
|
26
|
+
*/
|
|
27
|
+
static forRootAsync<const TTokens extends readonly InjectionToken[]>(options: GraphqlAsyncModuleOptions<TTokens>): ModuleType;
|
|
24
28
|
}
|
|
25
29
|
//# sourceMappingURL=module.d.ts.map
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAiDlF;;GAEG;AACH,qBAAa,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,oBAAyB,GAAG,UAAU;IAa9D;;;;;;;;;;OAUG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,cAAc,EAAE,EACjE,OAAO,EAAE,yBAAyB,CAAC,OAAO,CAAC,GAC1C,UAAU;CA4Bd"}
|
package/dist/module.js
CHANGED
|
@@ -1,18 +1,37 @@
|
|
|
1
|
+
import { isForwardRef, isOptionalToken } from '@fluojs/di';
|
|
1
2
|
import { defineModule } from '@fluojs/runtime';
|
|
3
|
+
import { RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
2
4
|
import { GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN } from './internal-tokens.js';
|
|
3
5
|
import { GraphqlEndpointController, GraphqlLifecycleService } from './service.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
function createGraphqlProviders(optionsProvider) {
|
|
7
|
+
return [optionsProvider, GraphqlLifecycleService];
|
|
8
|
+
}
|
|
9
|
+
function assertGraphqlAsyncModuleOptions(options) {
|
|
10
|
+
if (options === null || typeof options !== 'object') {
|
|
11
|
+
throw new TypeError('GraphqlModule.forRootAsync requires an options object.');
|
|
12
|
+
}
|
|
13
|
+
const unsupportedKey = Object.keys(options).find(key => key !== 'inject' && key !== 'useFactory');
|
|
14
|
+
if (unsupportedKey !== undefined) {
|
|
15
|
+
throw new TypeError(`GraphqlModule.forRootAsync does not support "${unsupportedKey}"; use only inject and useFactory.`);
|
|
16
|
+
}
|
|
17
|
+
if (typeof options.useFactory !== 'function') {
|
|
18
|
+
throw new TypeError('GraphqlModule.forRootAsync requires a useFactory function.');
|
|
19
|
+
}
|
|
20
|
+
if (options.inject !== undefined && !Array.isArray(options.inject)) {
|
|
21
|
+
throw new TypeError('GraphqlModule.forRootAsync inject must be an array of application tokens.');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isContainer(value) {
|
|
25
|
+
return value !== null && typeof value === 'object' && 'has' in value && 'resolve' in value;
|
|
26
|
+
}
|
|
27
|
+
async function resolveAsyncDependency(container, token) {
|
|
28
|
+
if (isForwardRef(token)) {
|
|
29
|
+
return await container.resolve(token.forwardRef());
|
|
30
|
+
}
|
|
31
|
+
if (isOptionalToken(token)) {
|
|
32
|
+
return container.has(token.token) ? await container.resolve(token.token) : undefined;
|
|
33
|
+
}
|
|
34
|
+
return await container.resolve(token);
|
|
16
35
|
}
|
|
17
36
|
|
|
18
37
|
/**
|
|
@@ -30,8 +49,44 @@ export class GraphqlModule {
|
|
|
30
49
|
class GraphqlRootModule extends GraphqlModule {}
|
|
31
50
|
return defineModule(GraphqlRootModule, {
|
|
32
51
|
controllers: [GraphqlEndpointController],
|
|
33
|
-
middleware: [],
|
|
34
|
-
providers: createGraphqlProviders(
|
|
52
|
+
middleware: [GraphqlLifecycleService],
|
|
53
|
+
providers: createGraphqlProviders({
|
|
54
|
+
provide: GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN,
|
|
55
|
+
useValue: options
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Registers GraphQL from options resolved by explicitly injected application dependencies.
|
|
62
|
+
*
|
|
63
|
+
* The factory runs once in each application context. Only `inject` and `useFactory` are
|
|
64
|
+
* supported; NestJS-style `imports`, `useClass`, `useExisting`, and implicit discovery are rejected.
|
|
65
|
+
*
|
|
66
|
+
* @param options Injected dependency tokens and the factory that resolves GraphQL options.
|
|
67
|
+
* @returns A module definition that resolves GraphQL configuration before endpoint lifecycle wiring begins.
|
|
68
|
+
*
|
|
69
|
+
* @throws {TypeError} When the options shape requests unsupported registration behavior.
|
|
70
|
+
*/
|
|
71
|
+
static forRootAsync(options) {
|
|
72
|
+
assertGraphqlAsyncModuleOptions(options);
|
|
73
|
+
class GraphqlAsyncRootModule extends GraphqlModule {}
|
|
74
|
+
return defineModule(GraphqlAsyncRootModule, {
|
|
75
|
+
controllers: [GraphqlEndpointController],
|
|
76
|
+
middleware: [GraphqlLifecycleService],
|
|
77
|
+
providers: createGraphqlProviders({
|
|
78
|
+
inject: [RUNTIME_CONTAINER],
|
|
79
|
+
provide: GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN,
|
|
80
|
+
scope: 'singleton',
|
|
81
|
+
useFactory: async (...dependencies) => {
|
|
82
|
+
const [runtimeContainer] = dependencies;
|
|
83
|
+
if (!isContainer(runtimeContainer)) {
|
|
84
|
+
throw new TypeError('GraphqlModule.forRootAsync could not resolve the application container.');
|
|
85
|
+
}
|
|
86
|
+
const injectedDependencies = await Promise.all((options.inject ?? []).map(async token => await resolveAsyncDependency(runtimeContainer, token)));
|
|
87
|
+
return Reflect.apply(options.useFactory, options, injectedDependencies);
|
|
88
|
+
}
|
|
89
|
+
})
|
|
35
90
|
});
|
|
36
91
|
}
|
|
37
92
|
}
|
|
@@ -10,6 +10,9 @@ interface GraphqlSubscribePayload {
|
|
|
10
10
|
query: string;
|
|
11
11
|
variables?: Record<string, unknown> | null;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Describes a GraphQL-over-WebSocket subscription forwarded to application hooks.
|
|
15
|
+
*/
|
|
13
16
|
export interface GraphqlNodeWebSocketSubscribeRequest {
|
|
14
17
|
connectionParams?: Record<string, unknown>;
|
|
15
18
|
operationId: string;
|
|
@@ -17,7 +20,15 @@ export interface GraphqlNodeWebSocketSubscribeRequest {
|
|
|
17
20
|
request: FrameworkRequest;
|
|
18
21
|
socket: object;
|
|
19
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Represents a registered Node GraphQL WebSocket transport.
|
|
25
|
+
*/
|
|
20
26
|
export interface GraphqlNodeWebSocketTransport {
|
|
27
|
+
/**
|
|
28
|
+
* Releases websocket listeners, clients, and GraphQL protocol resources.
|
|
29
|
+
*
|
|
30
|
+
* @returns A promise that resolves when cleanup completes or rejects with all current cleanup failures.
|
|
31
|
+
*/
|
|
21
32
|
dispose(): Promise<void>;
|
|
22
33
|
}
|
|
23
34
|
interface GraphqlNodeWebSocketTransportOptions {
|
|
@@ -31,6 +42,12 @@ interface GraphqlNodeWebSocketTransportOptions {
|
|
|
31
42
|
onSubscribe: (request: GraphqlNodeWebSocketSubscribeRequest) => Promise<ExecutionArgs | readonly GraphQLErrorType[]>;
|
|
32
43
|
subscribe: typeof subscribeGraphql;
|
|
33
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Registers GraphQL-over-WebSocket upgrade handling for a Node HTTP/S adapter.
|
|
47
|
+
*
|
|
48
|
+
* @param options Transport dependencies and WebSocket lifecycle hooks.
|
|
49
|
+
* @returns A transport that unregisters upgrade handling and disposes WebSocket clients.
|
|
50
|
+
*/
|
|
34
51
|
export declare function createNodeGraphqlWebSocketTransport(options: GraphqlNodeWebSocketTransportOptions): Promise<GraphqlNodeWebSocketTransport>;
|
|
35
52
|
export {};
|
|
36
53
|
//# sourceMappingURL=graphql-websocket-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-websocket-transport.d.ts","sourceRoot":"","sources":["../../src/node/graphql-websocket-transport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,KAAK,EACV,aAAa,EACb,OAAO,IAAI,cAAc,EACzB,YAAY,IAAI,gBAAgB,EAChC,SAAS,IAAI,gBAAgB,EAC9B,MAAM,SAAS,CAAC;AAgBjB,UAAU,0BAA0B;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B,EAAE,MAAM,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,uBAAuB;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,oCAAoC;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,uBAAuB,CAAC;IACjC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,UAAU,oCAAoC;IAC5C,OAAO,EAAE,sBAAsB,CAAC;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,OAAO,EAAE,OAAO,cAAc,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,WAAW,EAAE,CAAC,OAAO,EAAE,oCAAoC,KAAK,OAAO,CAAC,aAAa,GAAG,SAAS,gBAAgB,EAAE,CAAC,CAAC;IACrH,SAAS,EAAE,OAAO,gBAAgB,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"graphql-websocket-transport.d.ts","sourceRoot":"","sources":["../../src/node/graphql-websocket-transport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,KAAK,EACV,aAAa,EACb,OAAO,IAAI,cAAc,EACzB,YAAY,IAAI,gBAAgB,EAChC,SAAS,IAAI,gBAAgB,EAC9B,MAAM,SAAS,CAAC;AAgBjB,UAAU,0BAA0B;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B,EAAE,MAAM,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,uBAAuB;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,uBAAuB,CAAC;IACjC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,UAAU,oCAAoC;IAC5C,OAAO,EAAE,sBAAsB,CAAC;IAChC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,OAAO,EAAE,OAAO,cAAc,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,WAAW,EAAE,CAAC,OAAO,EAAE,oCAAoC,KAAK,OAAO,CAAC,aAAa,GAAG,SAAS,gBAAgB,EAAE,CAAC,CAAC;IACrH,SAAS,EAAE,OAAO,gBAAgB,CAAC;CACpC;AA2ID;;;;;GAKG;AACH,wBAAsB,mCAAmC,CACvD,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,6BAA6B,CAAC,CAkIxC"}
|
|
@@ -2,6 +2,15 @@ import { handleProtocols } from 'graphql-ws';
|
|
|
2
2
|
import { useServer } from 'graphql-ws/lib/use/ws';
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
4
|
import { isGraphqlPath } from '../transport/transport.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Describes a GraphQL-over-WebSocket subscription forwarded to application hooks.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a registered Node GraphQL WebSocket transport.
|
|
12
|
+
*/
|
|
13
|
+
|
|
5
14
|
function hasNodeUpgradeServer(value) {
|
|
6
15
|
if (typeof value !== 'object' || value === null) {
|
|
7
16
|
return false;
|
|
@@ -40,6 +49,18 @@ function closeWebSocketServer(server) {
|
|
|
40
49
|
});
|
|
41
50
|
});
|
|
42
51
|
}
|
|
52
|
+
function collectCleanupError(errors, error) {
|
|
53
|
+
if (error instanceof AggregateError) {
|
|
54
|
+
for (const nested of error.errors) {
|
|
55
|
+
collectCleanupError(errors, nested);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (errors.includes(error)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
errors.push(error);
|
|
63
|
+
}
|
|
43
64
|
function resolveUpgradeServer(adapter) {
|
|
44
65
|
if (typeof adapter.getServer !== 'function') {
|
|
45
66
|
throw new Error('GraphQL websocket subscriptions require an HTTP adapter with getServer(). Use the Node HTTP adapter or provide a compatible adapter implementation.');
|
|
@@ -83,17 +104,37 @@ function createSubscribeRequest(context, message) {
|
|
|
83
104
|
socket: context.extra.socket
|
|
84
105
|
};
|
|
85
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Registers GraphQL-over-WebSocket upgrade handling for a Node HTTP/S adapter.
|
|
110
|
+
*
|
|
111
|
+
* @param options Transport dependencies and WebSocket lifecycle hooks.
|
|
112
|
+
* @returns A transport that unregisters upgrade handling and disposes WebSocket clients.
|
|
113
|
+
*/
|
|
86
114
|
export async function createNodeGraphqlWebSocketTransport(options) {
|
|
87
115
|
const upgradeServer = resolveUpgradeServer(options.adapter);
|
|
88
116
|
const disconnectErrors = [];
|
|
117
|
+
const disconnectedSockets = new Set();
|
|
89
118
|
const pendingDisconnects = new Set();
|
|
119
|
+
let websocketDisposableDisposed = false;
|
|
120
|
+
let websocketServerClosed = false;
|
|
121
|
+
let inFlightDispose;
|
|
90
122
|
const websocketServer = new WebSocketServer({
|
|
91
123
|
handleProtocols: protocols => handleProtocols(protocols),
|
|
92
124
|
maxPayload: options.limits?.maxPayloadBytes ?? 0,
|
|
93
125
|
noServer: true
|
|
94
126
|
});
|
|
95
127
|
const upgradeListener = createUpgradeListener(websocketServer, options.limits);
|
|
128
|
+
const drainDisconnectErrors = cleanupErrors => {
|
|
129
|
+
for (const error of disconnectErrors.splice(0, disconnectErrors.length)) {
|
|
130
|
+
collectCleanupError(cleanupErrors, error);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
96
133
|
const trackDisconnect = socketKey => {
|
|
134
|
+
if (disconnectedSockets.has(socketKey)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
disconnectedSockets.add(socketKey);
|
|
97
138
|
const pendingDisconnect = Promise.resolve(options.onDisconnect(socketKey)).catch(error => {
|
|
98
139
|
disconnectErrors.push(error);
|
|
99
140
|
}).finally(() => {
|
|
@@ -110,47 +151,69 @@ export async function createNodeGraphqlWebSocketTransport(options) {
|
|
|
110
151
|
onComplete: async (context, message) => {
|
|
111
152
|
await options.onComplete(context.extra.socket, message.id);
|
|
112
153
|
},
|
|
113
|
-
onDisconnect:
|
|
114
|
-
|
|
154
|
+
onDisconnect: context => {
|
|
155
|
+
trackDisconnect(context.extra.socket);
|
|
115
156
|
},
|
|
116
157
|
onSubscribe: async (context, message) => options.onSubscribe(createSubscribeRequest(context, message)),
|
|
117
158
|
subscribe: options.subscribe
|
|
118
159
|
}, websocketServer, options.keepAliveMs);
|
|
119
160
|
websocketServer.on('connection', trackConnection);
|
|
120
161
|
upgradeServer.on('upgrade', upgradeListener);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
disposeError ??= error;
|
|
132
|
-
}
|
|
162
|
+
const runDispose = async () => {
|
|
163
|
+
const cleanupErrors = [];
|
|
164
|
+
drainDisconnectErrors(cleanupErrors);
|
|
165
|
+
websocketServer.off('connection', trackConnection);
|
|
166
|
+
upgradeServer.off('upgrade', upgradeListener);
|
|
167
|
+
for (const client of websocketServer.clients) {
|
|
168
|
+
client.terminate();
|
|
169
|
+
}
|
|
170
|
+
while (pendingDisconnects.size > 0) {
|
|
171
|
+
const disconnectResults = await Promise.allSettled([...pendingDisconnects]);
|
|
133
172
|
for (const result of disconnectResults) {
|
|
134
173
|
if (result.status === 'rejected') {
|
|
135
|
-
|
|
174
|
+
collectCleanupError(cleanupErrors, result.reason);
|
|
136
175
|
}
|
|
137
176
|
}
|
|
177
|
+
}
|
|
178
|
+
drainDisconnectErrors(cleanupErrors);
|
|
179
|
+
if (!websocketDisposableDisposed) {
|
|
138
180
|
try {
|
|
139
181
|
await websocketDisposable.dispose();
|
|
182
|
+
websocketDisposableDisposed = true;
|
|
140
183
|
} catch (error) {
|
|
141
|
-
|
|
184
|
+
collectCleanupError(cleanupErrors, error);
|
|
142
185
|
}
|
|
186
|
+
}
|
|
187
|
+
if (!websocketServerClosed) {
|
|
143
188
|
try {
|
|
144
189
|
await closeWebSocketServer(websocketServer);
|
|
190
|
+
websocketServerClosed = true;
|
|
145
191
|
} catch (error) {
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
if (disposeError instanceof Error) {
|
|
149
|
-
throw disposeError;
|
|
192
|
+
collectCleanupError(cleanupErrors, error);
|
|
150
193
|
}
|
|
151
|
-
|
|
152
|
-
|
|
194
|
+
}
|
|
195
|
+
while (pendingDisconnects.size > 0) {
|
|
196
|
+
const lateDisconnectResults = await Promise.allSettled([...pendingDisconnects]);
|
|
197
|
+
for (const result of lateDisconnectResults) {
|
|
198
|
+
if (result.status === 'rejected') {
|
|
199
|
+
collectCleanupError(cleanupErrors, result.reason);
|
|
200
|
+
}
|
|
153
201
|
}
|
|
154
202
|
}
|
|
203
|
+
drainDisconnectErrors(cleanupErrors);
|
|
204
|
+
if (cleanupErrors.length === 1) {
|
|
205
|
+
throw cleanupErrors[0];
|
|
206
|
+
}
|
|
207
|
+
if (cleanupErrors.length > 1) {
|
|
208
|
+
throw new AggregateError(cleanupErrors, 'Failed to dispose GraphQL websocket transport resources.');
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
async dispose() {
|
|
213
|
+
inFlightDispose ??= runDispose().finally(() => {
|
|
214
|
+
inFlightDispose = undefined;
|
|
215
|
+
});
|
|
216
|
+
await inFlightDispose;
|
|
217
|
+
}
|
|
155
218
|
};
|
|
156
219
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDtoValidationSchema } from '@fluojs/core/
|
|
1
|
+
import { getDtoValidationSchema } from '@fluojs/core/request-pipeline';
|
|
2
2
|
import { DefaultValidator } from '@fluojs/validation';
|
|
3
3
|
import { isGraphqlListTypeRef } from '../types.js';
|
|
4
4
|
const defaultValidator = new DefaultValidator();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { GraphQLFieldConfigMap, GraphQLOutputType } from 'graphql';
|
|
1
|
+
import type { GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLOutputType } from 'graphql';
|
|
2
2
|
import type { GraphQLContext as FluoGraphQLContext, GraphqlRootOutputType, ResolverDescriptor, ResolverHandlerDescriptor } from '../types.js';
|
|
3
3
|
type ResolveOutputType = (outputType: GraphqlRootOutputType) => GraphQLOutputType;
|
|
4
|
-
type
|
|
4
|
+
type ResolveInputArgs = (handler: ResolverHandlerDescriptor) => GraphQLFieldConfigArgumentMap;
|
|
5
|
+
type InvokeObjectFieldResolver = (descriptor: ResolverDescriptor, handler: ResolverHandlerDescriptor, args: Record<string, unknown>, source: unknown, contextValue: FluoGraphQLContext) => Promise<unknown>;
|
|
5
6
|
/**
|
|
6
7
|
* Indexes object field resolver descriptors and attaches them to matching code-first object types.
|
|
7
8
|
*/
|
|
@@ -9,8 +10,8 @@ export declare class ObjectFieldResolverRegistry {
|
|
|
9
10
|
private readonly attachedTypeNames;
|
|
10
11
|
private readonly entriesByTypeName;
|
|
11
12
|
constructor(descriptors: readonly ResolverDescriptor[]);
|
|
12
|
-
attach(typeName: string, fields: GraphQLFieldConfigMap<unknown, FluoGraphQLContext>, resolveOutputType: ResolveOutputType, invokeResolver: InvokeObjectFieldResolver): GraphQLFieldConfigMap<unknown, FluoGraphQLContext>;
|
|
13
|
-
createMethodArguments(handler: ResolverHandlerDescriptor, parent: unknown, contextValue: FluoGraphQLContext): unknown[];
|
|
13
|
+
attach(typeName: string, fields: GraphQLFieldConfigMap<unknown, FluoGraphQLContext>, resolveOutputType: ResolveOutputType, resolveInputArgs: ResolveInputArgs, invokeResolver: InvokeObjectFieldResolver): GraphQLFieldConfigMap<unknown, FluoGraphQLContext>;
|
|
14
|
+
createMethodArguments(handler: ResolverHandlerDescriptor, input: unknown, parent: unknown, contextValue: FluoGraphQLContext): unknown[];
|
|
14
15
|
assertAllTargetsAttached(): void;
|
|
15
16
|
}
|
|
16
17
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-field-resolvers.d.ts","sourceRoot":"","sources":["../../src/schema/object-field-resolvers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"object-field-resolvers.d.ts","sourceRoot":"","sources":["../../src/schema/object-field-resolvers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEvG,OAAO,KAAK,EACV,cAAc,IAAI,kBAAkB,EACpC,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAOrB,KAAK,iBAAiB,GAAG,CAAC,UAAU,EAAE,qBAAqB,KAAK,iBAAiB,CAAC;AAClF,KAAK,gBAAgB,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,6BAA6B,CAAC;AAE9F,KAAK,yBAAyB,GAAG,CAC/B,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,yBAAyB,EAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,kBAAkB,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;AAMtB;;GAEG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IACvD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4D;gBAElF,WAAW,EAAE,SAAS,kBAAkB,EAAE;IAqBtD,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAC1D,iBAAiB,EAAE,iBAAiB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,yBAAyB,GACxC,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAmCrD,qBAAqB,CACnB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,kBAAkB,GAC/B,OAAO,EAAE;IAuBZ,wBAAwB,IAAI,IAAI;CASjC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GraphQLNonNull } from 'graphql';
|
|
1
2
|
function assertNever(value) {
|
|
2
3
|
throw new Error(`Unsupported GraphQL field resolver parameter binding: ${String(value)}`);
|
|
3
4
|
}
|
|
@@ -26,7 +27,7 @@ export class ObjectFieldResolverRegistry {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
attach(typeName, fields, resolveOutputType, invokeResolver) {
|
|
30
|
+
attach(typeName, fields, resolveOutputType, resolveInputArgs, invokeResolver) {
|
|
30
31
|
const resolverFields = this.entriesByTypeName.get(typeName);
|
|
31
32
|
if (!resolverFields) {
|
|
32
33
|
return fields;
|
|
@@ -41,21 +42,28 @@ export class ObjectFieldResolverRegistry {
|
|
|
41
42
|
if (!outputType) {
|
|
42
43
|
throw new Error(`GraphQL object field resolver "${typeName}.${fieldName}" must target an existing field or declare a type.`);
|
|
43
44
|
}
|
|
45
|
+
const hasExplicitNonNullableNewField = existingField === undefined && entry.handler.outputType !== undefined && entry.handler.nullable === false;
|
|
44
46
|
attachedFields[fieldName] = {
|
|
45
47
|
...existingField,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
...(entry.handler.inputClass ? {
|
|
49
|
+
args: resolveInputArgs(entry.handler)
|
|
50
|
+
} : {}),
|
|
51
|
+
resolve: async (source, args, contextValue) => invokeResolver(entry.descriptor, entry.handler, args, source, contextValue),
|
|
52
|
+
type: hasExplicitNonNullableNewField ? new GraphQLNonNull(outputType) : outputType
|
|
48
53
|
};
|
|
49
54
|
}
|
|
50
55
|
return attachedFields;
|
|
51
56
|
}
|
|
52
|
-
createMethodArguments(handler, parent, contextValue) {
|
|
57
|
+
createMethodArguments(handler, input, parent, contextValue) {
|
|
53
58
|
const lastBinding = handler.parameterBindings.at(-1);
|
|
54
59
|
const methodArguments = Array.from({
|
|
55
60
|
length: (lastBinding?.index ?? -1) + 1
|
|
56
61
|
});
|
|
57
62
|
for (const binding of handler.parameterBindings) {
|
|
58
63
|
switch (binding.kind) {
|
|
64
|
+
case 'input':
|
|
65
|
+
methodArguments[binding.index] = input;
|
|
66
|
+
break;
|
|
59
67
|
case 'parent':
|
|
60
68
|
methodArguments[binding.index] = parent;
|
|
61
69
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAEV,YAAY,IAAI,gBAAgB,EAMhC,WAAW,IAAI,eAAe,EAC9B,cAAc,IAAI,kBAAkB,EACpC,iBAAiB,IAAI,qBAAqB,EAE1C,iBAAiB,EACjB,aAAa,IAAI,iBAAiB,EAClC,gBAAgB,IAAI,oBAAoB,EACzC,MAAM,SAAS,CAAC;AAGjB,OAAO,EAOL,KAAK,kBAAkB,EAGxB,MAAM,aAAa,CAAC;AAGrB,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,OAAO,gBAAgB,CAAC;IACtC,cAAc,EAAE,iBAAiB,CAAC;IAClC,YAAY,EAAE,iBAAiB,CAAC;IAChC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,WAAW,EAAE,OAAO,eAAe,CAAC;IACpC,cAAc,EAAE,OAAO,kBAAkB,CAAC;IAC1C,iBAAiB,EAAE,OAAO,qBAAqB,CAAC;IAChD,aAAa,EAAE,OAAO,iBAAiB,CAAC;IACxC,aAAa,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,EAAE,OAAO,oBAAoB,CAAC;IAC9C,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;IACnD,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,gBAAgB,CAAC;CAC9G,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAEV,YAAY,IAAI,gBAAgB,EAMhC,WAAW,IAAI,eAAe,EAC9B,cAAc,IAAI,kBAAkB,EACpC,iBAAiB,IAAI,qBAAqB,EAE1C,iBAAiB,EACjB,aAAa,IAAI,iBAAiB,EAClC,gBAAgB,IAAI,oBAAoB,EACzC,MAAM,SAAS,CAAC;AAGjB,OAAO,EAOL,KAAK,kBAAkB,EAGxB,MAAM,aAAa,CAAC;AAGrB,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,OAAO,gBAAgB,CAAC;IACtC,cAAc,EAAE,iBAAiB,CAAC;IAClC,YAAY,EAAE,iBAAiB,CAAC;IAChC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,WAAW,EAAE,OAAO,eAAe,CAAC;IACpC,cAAc,EAAE,OAAO,kBAAkB,CAAC;IAC1C,iBAAiB,EAAE,OAAO,qBAAqB,CAAC;IAChD,aAAa,EAAE,OAAO,iBAAiB,CAAC;IACxC,aAAa,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,EAAE,OAAO,oBAAoB,CAAC;IAC9C,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;IACnD,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,gBAAgB,CAAC;CAC9G,CAAC;AA4fF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,EACrB,aAAa,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,EACrD,qBAAqB,EAAE,MAAM,iBAAiB,EAC9C,mCAAmC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAC5D,iBAAiB,CAWnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,EACrB,gBAAgB,EAAE,SAAS,EAC3B,mBAAmB,EAAE,kBAAkB,EAAE,EACzC,mCAAmC,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAe,GACvE,iBAAiB,CA6EnB"}
|
package/dist/schema/schema.js
CHANGED
|
@@ -234,7 +234,7 @@ function createResolverInvoker(deps, runtimeContainer, markAllowedCrossRealmGrap
|
|
|
234
234
|
if (descriptor.scope === 'singleton') {
|
|
235
235
|
const instance = await runtimeContainer.resolve(descriptor.token);
|
|
236
236
|
const resolverMethod = resolveResolverMethod(instance, descriptor, handler);
|
|
237
|
-
const methodArguments = handler.type === 'field' ? objectFieldResolvers.createMethodArguments(handler, source, contextValue) : [await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), contextValue];
|
|
237
|
+
const methodArguments = handler.type === 'field' ? objectFieldResolvers.createMethodArguments(handler, await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), source, contextValue) : [await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), contextValue];
|
|
238
238
|
return resolverMethod.call(instance, ...methodArguments);
|
|
239
239
|
}
|
|
240
240
|
const operationContainer = contextValue[GRAPHQL_OPERATION_CONTAINER] ?? runtimeContainer.createRequestScope();
|
|
@@ -242,7 +242,7 @@ function createResolverInvoker(deps, runtimeContainer, markAllowedCrossRealmGrap
|
|
|
242
242
|
try {
|
|
243
243
|
const instance = await operationContainer.resolve(descriptor.token);
|
|
244
244
|
const resolverMethod = resolveResolverMethod(instance, descriptor, handler);
|
|
245
|
-
const methodArguments = handler.type === 'field' ? objectFieldResolvers.createMethodArguments(handler, source, contextValue) : [await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), contextValue];
|
|
245
|
+
const methodArguments = handler.type === 'field' ? objectFieldResolvers.createMethodArguments(handler, await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), source, contextValue) : [await createResolverInput(deps, handler, args, markAllowedCrossRealmGraphqlObjects), contextValue];
|
|
246
246
|
return await resolverMethod.call(instance, ...methodArguments);
|
|
247
247
|
} finally {
|
|
248
248
|
if (disposeOperationContainer) {
|
|
@@ -315,7 +315,7 @@ export function createCodeFirstSchema(deps, runtimeContainer, resolverDescriptor
|
|
|
315
315
|
const invokeResolver = createResolverInvoker(deps, runtimeContainer, markAllowedCrossRealmGraphqlObjects, objectFieldResolvers);
|
|
316
316
|
const outputTypeCache = new Map();
|
|
317
317
|
function attachObjectFieldResolvers(typeName, fields) {
|
|
318
|
-
return objectFieldResolvers.attach(typeName, fields, outputType => resolveRootOutputType(deps, outputTypeCache, markAllowedCrossRealmGraphqlObjects, outputType, attachObjectFieldResolvers), (descriptor, handler, source, contextValue) => invokeResolver(descriptor, handler,
|
|
318
|
+
return objectFieldResolvers.attach(typeName, fields, outputType => resolveRootOutputType(deps, outputTypeCache, markAllowedCrossRealmGraphqlObjects, outputType, attachObjectFieldResolvers), handler => createFieldArgs(deps, handler), (descriptor, handler, args, source, contextValue) => invokeResolver(descriptor, handler, args, contextValue, source));
|
|
319
319
|
}
|
|
320
320
|
const queryFields = pickFieldsByType(deps, resolverDescriptors, 'query', markAllowedCrossRealmGraphqlObjects, outputTypeCache, attachObjectFieldResolvers, invokeResolver);
|
|
321
321
|
const mutationFields = pickFieldsByType(deps, resolverDescriptors, 'mutation', markAllowedCrossRealmGraphqlObjects, outputTypeCache, attachObjectFieldResolvers, invokeResolver);
|