@fluojs/graphql 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/metadata.js CHANGED
@@ -3,9 +3,11 @@ void ensureSymbolMetadataPolyfill();
3
3
  const standardResolverMetadataKey = Symbol.for('fluo.graphql.standard.resolver');
4
4
  const standardHandlerMetadataKey = Symbol.for('fluo.graphql.standard.handler');
5
5
  const standardArgFieldMetadataKey = Symbol.for('fluo.graphql.standard.arg-field');
6
+ const standardFieldResolverParameterMetadataKey = Symbol.for('fluo.graphql.standard.field-resolver-parameter');
6
7
  const resolverMetadataStore = new WeakMap();
7
8
  const handlerMetadataStore = new WeakMap();
8
9
  const argFieldMetadataStore = new WeakMap();
10
+ const fieldResolverParameterMetadataStore = new WeakMap();
9
11
  function cloneResolverMetadata(metadata) {
10
12
  return {
11
13
  typeName: metadata.typeName
@@ -16,10 +18,17 @@ function cloneHandlerMetadata(metadata) {
16
18
  argTypes: metadata.argTypes,
17
19
  fieldName: metadata.fieldName,
18
20
  inputClass: metadata.inputClass,
21
+ nullable: metadata.nullable,
19
22
  outputType: metadata.outputType,
20
23
  type: metadata.type
21
24
  };
22
25
  }
26
+ function cloneFieldResolverParameterMetadata(metadata) {
27
+ return {
28
+ index: metadata.index,
29
+ kind: metadata.kind
30
+ };
31
+ }
23
32
  function cloneArgFieldMetadata(metadata) {
24
33
  return {
25
34
  argName: metadata.argName,
@@ -39,6 +48,9 @@ function getStandardHandlerMap(target) {
39
48
  function getStandardArgFieldMap(target) {
40
49
  return getStandardConstructorMetadataBag(target)?.[standardArgFieldMetadataKey];
41
50
  }
51
+ function getStandardFieldResolverParameterMap(target) {
52
+ return getStandardConstructorMetadataBag(target)?.[standardFieldResolverParameterMetadataKey];
53
+ }
42
54
  function getOrCreateHandlerMetadataMap(target) {
43
55
  let map = handlerMetadataStore.get(target);
44
56
  if (!map) {
@@ -55,6 +67,14 @@ function getOrCreateArgFieldMetadataMap(target) {
55
67
  }
56
68
  return map;
57
69
  }
70
+ function getOrCreateFieldResolverParameterMetadataMap(target) {
71
+ let map = fieldResolverParameterMetadataStore.get(target);
72
+ if (!map) {
73
+ map = new Map();
74
+ fieldResolverParameterMetadataStore.set(target, map);
75
+ }
76
+ return map;
77
+ }
58
78
  function getMergedMetadataEntries(target, stored, standard, resolve) {
59
79
  const storedMap = stored ?? new Map();
60
80
  const standardMap = standard ?? new Map();
@@ -84,10 +104,11 @@ export function defineResolverMetadata(target, metadata) {
84
104
  export function getResolverMetadata(target) {
85
105
  const stored = resolverMetadataStore.get(target);
86
106
  const standard = getStandardResolverMetadata(target);
87
- if (!stored && !standard) {
107
+ const metadata = stored ?? standard;
108
+ if (!metadata) {
88
109
  return undefined;
89
110
  }
90
- return cloneResolverMetadata(stored ?? standard);
111
+ return cloneResolverMetadata(metadata);
91
112
  }
92
113
 
93
114
  /**
@@ -111,10 +132,11 @@ export function defineResolverHandlerMetadata(target, propertyKey, metadata) {
111
132
  export function getResolverHandlerMetadata(target, propertyKey) {
112
133
  const stored = handlerMetadataStore.get(target)?.get(propertyKey);
113
134
  const standard = getStandardHandlerMap(target)?.get(propertyKey);
114
- if (!stored && !standard) {
135
+ const metadata = stored ?? standard;
136
+ if (!metadata) {
115
137
  return undefined;
116
138
  }
117
- return cloneHandlerMetadata(stored ?? standard);
139
+ return cloneHandlerMetadata(metadata);
118
140
  }
119
141
 
120
142
  /**
@@ -148,10 +170,11 @@ export function defineArgFieldMetadata(target, propertyKey, metadata) {
148
170
  export function getArgFieldMetadata(target, propertyKey) {
149
171
  const stored = argFieldMetadataStore.get(target)?.get(propertyKey);
150
172
  const standard = getStandardArgFieldMap(target)?.get(propertyKey);
151
- if (!stored && !standard) {
173
+ const metadata = stored ?? standard;
174
+ if (!metadata) {
152
175
  return undefined;
153
176
  }
154
- return cloneArgFieldMetadata(stored ?? standard);
177
+ return cloneArgFieldMetadata(metadata);
155
178
  }
156
179
 
157
180
  /**
@@ -164,6 +187,40 @@ export function getArgFieldMetadataEntries(target) {
164
187
  return getMergedMetadataEntries(target, argFieldMetadataStore.get(target), getStandardArgFieldMap(target), getArgFieldMetadata);
165
188
  }
166
189
 
190
+ /**
191
+ * Define one positional parameter binding for an object field resolver.
192
+ *
193
+ * @param target Resolver prototype that owns the decorated method.
194
+ * @param propertyKey Decorated method key.
195
+ * @param metadata Positional binding metadata to store.
196
+ */
197
+ export function defineFieldResolverParameterMetadata(target, propertyKey, metadata) {
198
+ const methods = getOrCreateFieldResolverParameterMetadataMap(target);
199
+ const bindings = methods.get(propertyKey) ?? new Map();
200
+ bindings.set(metadata.index, cloneFieldResolverParameterMetadata(metadata));
201
+ methods.set(propertyKey, bindings);
202
+ }
203
+
204
+ /**
205
+ * Get the positional parameter bindings declared for one resolver method.
206
+ *
207
+ * @param target Resolver prototype that owns the decorated method.
208
+ * @param propertyKey Decorated method key.
209
+ * @returns Parameter bindings ordered by their method parameter index.
210
+ */
211
+ export function getFieldResolverParameterMetadataEntries(target, propertyKey) {
212
+ const stored = fieldResolverParameterMetadataStore.get(target)?.get(propertyKey);
213
+ const standard = getStandardFieldResolverParameterMap(target)?.get(propertyKey);
214
+ const merged = new Map();
215
+ for (const [index, metadata] of standard ?? []) {
216
+ merged.set(index, cloneFieldResolverParameterMetadata(metadata));
217
+ }
218
+ for (const [index, metadata] of stored ?? []) {
219
+ merged.set(index, cloneFieldResolverParameterMetadata(metadata));
220
+ }
221
+ return Array.from(merged.values()).sort((left, right) => left.index - right.index);
222
+ }
223
+
167
224
  /**
168
225
  * Provides the resolver metadata symbol value.
169
226
  */
@@ -175,4 +232,8 @@ export const handlerMetadataSymbol = standardHandlerMetadataKey;
175
232
  /**
176
233
  * Provides the arg metadata symbol value.
177
234
  */
178
- export const argMetadataSymbol = standardArgFieldMetadataKey;
235
+ export const argMetadataSymbol = standardArgFieldMetadataKey;
236
+ /**
237
+ * Provides the object field-resolver parameter metadata symbol value.
238
+ */
239
+ export const fieldResolverParameterMetadataSymbol = standardFieldResolverParameterMetadataKey;
@@ -0,0 +1,36 @@
1
+ import type { FrameworkRequest, HttpApplicationAdapter } from '@fluojs/http';
2
+ import type { ExecutionArgs, execute as executeGraphql, GraphQLError as GraphQLErrorType, subscribe as subscribeGraphql } from 'graphql';
3
+ interface GraphqlNodeWebSocketLimits {
4
+ maxConnections: number;
5
+ maxOperationsPerConnection: number;
6
+ maxPayloadBytes: number;
7
+ }
8
+ interface GraphqlSubscribePayload {
9
+ operationName?: string | null;
10
+ query: string;
11
+ variables?: Record<string, unknown> | null;
12
+ }
13
+ export interface GraphqlNodeWebSocketSubscribeRequest {
14
+ connectionParams?: Record<string, unknown>;
15
+ operationId: string;
16
+ payload: GraphqlSubscribePayload;
17
+ request: FrameworkRequest;
18
+ socket: object;
19
+ }
20
+ export interface GraphqlNodeWebSocketTransport {
21
+ dispose(): Promise<void>;
22
+ }
23
+ interface GraphqlNodeWebSocketTransportOptions {
24
+ adapter: HttpApplicationAdapter;
25
+ connectionInitWaitTimeoutMs?: number;
26
+ execute: typeof executeGraphql;
27
+ keepAliveMs?: number;
28
+ limits?: GraphqlNodeWebSocketLimits;
29
+ onComplete: (socketKey: object, operationId: string) => Promise<void> | void;
30
+ onDisconnect: (socketKey: object) => Promise<void> | void;
31
+ onSubscribe: (request: GraphqlNodeWebSocketSubscribeRequest) => Promise<ExecutionArgs | readonly GraphQLErrorType[]>;
32
+ subscribe: typeof subscribeGraphql;
33
+ }
34
+ export declare function createNodeGraphqlWebSocketTransport(options: GraphqlNodeWebSocketTransportOptions): Promise<GraphqlNodeWebSocketTransport>;
35
+ export {};
36
+ //# sourceMappingURL=graphql-websocket-transport.d.ts.map
@@ -0,0 +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;AA2HD,wBAAsB,mCAAmC,CACvD,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,6BAA6B,CAAC,CAsFxC"}
@@ -0,0 +1,156 @@
1
+ import { handleProtocols } from 'graphql-ws';
2
+ import { useServer } from 'graphql-ws/lib/use/ws';
3
+ import { WebSocketServer } from 'ws';
4
+ import { isGraphqlPath } from '../transport/transport.js';
5
+ function hasNodeUpgradeServer(value) {
6
+ if (typeof value !== 'object' || value === null) {
7
+ return false;
8
+ }
9
+ const server = value;
10
+ return typeof server.on === 'function' && typeof server.off === 'function';
11
+ }
12
+ function isConnectionParamsRecord(value) {
13
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
14
+ }
15
+ function buildFrameworkRequestFromIncomingMessage(request) {
16
+ const requestUrl = new URL(request.url ?? '/graphql', 'http://localhost');
17
+ return {
18
+ cookies: {},
19
+ headers: request.headers,
20
+ method: request.method ?? 'GET',
21
+ params: {},
22
+ path: requestUrl.pathname,
23
+ query: Object.fromEntries(requestUrl.searchParams.entries()),
24
+ raw: request,
25
+ url: requestUrl.pathname + requestUrl.search
26
+ };
27
+ }
28
+ function closeWebSocketServer(server) {
29
+ return new Promise((resolve, reject) => {
30
+ server.close(error => {
31
+ if (error?.message === 'The server is not running') {
32
+ resolve();
33
+ return;
34
+ }
35
+ if (error) {
36
+ reject(error);
37
+ return;
38
+ }
39
+ resolve();
40
+ });
41
+ });
42
+ }
43
+ function resolveUpgradeServer(adapter) {
44
+ if (typeof adapter.getServer !== 'function') {
45
+ throw new Error('GraphQL websocket subscriptions require an HTTP adapter with getServer(). Use the Node HTTP adapter or provide a compatible adapter implementation.');
46
+ }
47
+ const server = adapter.getServer();
48
+ if (!hasNodeUpgradeServer(server)) {
49
+ throw new Error('GraphQL websocket subscriptions require adapter.getServer() to return a Node HTTP/S server that supports upgrade listeners.');
50
+ }
51
+ return server;
52
+ }
53
+ function rejectWebSocketUpgrade(socket, statusCode, message) {
54
+ if (!socket.writable) {
55
+ socket.destroy();
56
+ return;
57
+ }
58
+ const body = `${message}\n`;
59
+ socket.write([`HTTP/1.1 ${String(statusCode)} ${statusCode === 503 ? 'Service Unavailable' : 'Bad Request'}`, 'Connection: close', 'Content-Type: text/plain; charset=utf-8', `Content-Length: ${String(new TextEncoder().encode(body).byteLength)}`, '', body].join('\r\n'));
60
+ socket.destroy();
61
+ }
62
+ function createUpgradeListener(websocketServer, limits) {
63
+ return (request, socket, head) => {
64
+ const targetPath = new URL(request.url ?? '/', 'http://localhost').pathname;
65
+ if (!isGraphqlPath(targetPath)) {
66
+ return;
67
+ }
68
+ if (limits && websocketServer.clients.size >= limits.maxConnections) {
69
+ rejectWebSocketUpgrade(socket, 503, 'GraphQL websocket connection count exceeds the configured limit.');
70
+ return;
71
+ }
72
+ websocketServer.handleUpgrade(request, socket, head, websocket => {
73
+ websocketServer.emit('connection', websocket, request);
74
+ });
75
+ };
76
+ }
77
+ function createSubscribeRequest(context, message) {
78
+ return {
79
+ connectionParams: isConnectionParamsRecord(context.connectionParams) ? context.connectionParams : undefined,
80
+ operationId: message.id,
81
+ payload: message.payload,
82
+ request: buildFrameworkRequestFromIncomingMessage(context.extra.request),
83
+ socket: context.extra.socket
84
+ };
85
+ }
86
+ export async function createNodeGraphqlWebSocketTransport(options) {
87
+ const upgradeServer = resolveUpgradeServer(options.adapter);
88
+ const disconnectErrors = [];
89
+ const pendingDisconnects = new Set();
90
+ const websocketServer = new WebSocketServer({
91
+ handleProtocols: protocols => handleProtocols(protocols),
92
+ maxPayload: options.limits?.maxPayloadBytes ?? 0,
93
+ noServer: true
94
+ });
95
+ const upgradeListener = createUpgradeListener(websocketServer, options.limits);
96
+ const trackDisconnect = socketKey => {
97
+ const pendingDisconnect = Promise.resolve(options.onDisconnect(socketKey)).catch(error => {
98
+ disconnectErrors.push(error);
99
+ }).finally(() => {
100
+ pendingDisconnects.delete(pendingDisconnect);
101
+ });
102
+ pendingDisconnects.add(pendingDisconnect);
103
+ };
104
+ const trackConnection = websocket => {
105
+ websocket.once('close', () => trackDisconnect(websocket));
106
+ };
107
+ const websocketDisposable = useServer({
108
+ connectionInitWaitTimeout: options.connectionInitWaitTimeoutMs,
109
+ execute: options.execute,
110
+ onComplete: async (context, message) => {
111
+ await options.onComplete(context.extra.socket, message.id);
112
+ },
113
+ onDisconnect: async context => {
114
+ await options.onDisconnect(context.extra.socket);
115
+ },
116
+ onSubscribe: async (context, message) => options.onSubscribe(createSubscribeRequest(context, message)),
117
+ subscribe: options.subscribe
118
+ }, websocketServer, options.keepAliveMs);
119
+ websocketServer.on('connection', trackConnection);
120
+ upgradeServer.on('upgrade', upgradeListener);
121
+ return {
122
+ async dispose() {
123
+ let disposeError;
124
+ websocketServer.off('connection', trackConnection);
125
+ upgradeServer.off('upgrade', upgradeListener);
126
+ for (const client of websocketServer.clients) {
127
+ client.terminate();
128
+ }
129
+ const disconnectResults = await Promise.allSettled(pendingDisconnects);
130
+ for (const error of disconnectErrors) {
131
+ disposeError ??= error;
132
+ }
133
+ for (const result of disconnectResults) {
134
+ if (result.status === 'rejected') {
135
+ disposeError ??= result.reason;
136
+ }
137
+ }
138
+ try {
139
+ await websocketDisposable.dispose();
140
+ } catch (error) {
141
+ disposeError = error;
142
+ }
143
+ try {
144
+ await closeWebSocketServer(websocketServer);
145
+ } catch (error) {
146
+ disposeError ??= error;
147
+ }
148
+ if (disposeError instanceof Error) {
149
+ throw disposeError;
150
+ }
151
+ if (disposeError !== undefined) {
152
+ throw new Error(String(disposeError));
153
+ }
154
+ }
155
+ };
156
+ }
@@ -0,0 +1,17 @@
1
+ import type { GraphQLFieldConfigMap, GraphQLOutputType } from 'graphql';
2
+ import type { GraphQLContext as FluoGraphQLContext, GraphqlRootOutputType, ResolverDescriptor, ResolverHandlerDescriptor } from '../types.js';
3
+ type ResolveOutputType = (outputType: GraphqlRootOutputType) => GraphQLOutputType;
4
+ type InvokeObjectFieldResolver = (descriptor: ResolverDescriptor, handler: ResolverHandlerDescriptor, source: unknown, contextValue: FluoGraphQLContext) => Promise<unknown>;
5
+ /**
6
+ * Indexes object field resolver descriptors and attaches them to matching code-first object types.
7
+ */
8
+ export declare class ObjectFieldResolverRegistry {
9
+ private readonly attachedTypeNames;
10
+ private readonly entriesByTypeName;
11
+ 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[];
14
+ assertAllTargetsAttached(): void;
15
+ }
16
+ export {};
17
+ //# sourceMappingURL=object-field-resolvers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-field-resolvers.d.ts","sourceRoot":"","sources":["../../src/schema/object-field-resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAExE,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;AAElF,KAAK,yBAAyB,GAAG,CAC/B,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,yBAAyB,EAClC,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,cAAc,EAAE,yBAAyB,GACxC,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,CAAC;IA+BrD,qBAAqB,CACnB,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,kBAAkB,GAC/B,OAAO,EAAE;IAoBZ,wBAAwB,IAAI,IAAI;CASjC"}
@@ -0,0 +1,78 @@
1
+ function assertNever(value) {
2
+ throw new Error(`Unsupported GraphQL field resolver parameter binding: ${String(value)}`);
3
+ }
4
+
5
+ /**
6
+ * Indexes object field resolver descriptors and attaches them to matching code-first object types.
7
+ */
8
+ export class ObjectFieldResolverRegistry {
9
+ attachedTypeNames = new Set();
10
+ entriesByTypeName = new Map();
11
+ constructor(descriptors) {
12
+ for (const descriptor of descriptors) {
13
+ for (const handler of descriptor.handlers) {
14
+ if (handler.type !== 'field') {
15
+ continue;
16
+ }
17
+ const fields = this.entriesByTypeName.get(descriptor.typeName) ?? new Map();
18
+ if (fields.has(handler.fieldName)) {
19
+ throw new Error(`GraphQL schema conflict: object field resolver "${descriptor.typeName}.${handler.fieldName}" is registered more than once.`);
20
+ }
21
+ fields.set(handler.fieldName, {
22
+ descriptor,
23
+ handler
24
+ });
25
+ this.entriesByTypeName.set(descriptor.typeName, fields);
26
+ }
27
+ }
28
+ }
29
+ attach(typeName, fields, resolveOutputType, invokeResolver) {
30
+ const resolverFields = this.entriesByTypeName.get(typeName);
31
+ if (!resolverFields) {
32
+ return fields;
33
+ }
34
+ this.attachedTypeNames.add(typeName);
35
+ const attachedFields = {
36
+ ...fields
37
+ };
38
+ for (const [fieldName, entry] of resolverFields) {
39
+ const existingField = attachedFields[fieldName];
40
+ const outputType = entry.handler.outputType ? resolveOutputType(entry.handler.outputType) : existingField?.type;
41
+ if (!outputType) {
42
+ throw new Error(`GraphQL object field resolver "${typeName}.${fieldName}" must target an existing field or declare a type.`);
43
+ }
44
+ attachedFields[fieldName] = {
45
+ ...existingField,
46
+ resolve: async (source, _args, contextValue) => invokeResolver(entry.descriptor, entry.handler, source, contextValue),
47
+ type: outputType
48
+ };
49
+ }
50
+ return attachedFields;
51
+ }
52
+ createMethodArguments(handler, parent, contextValue) {
53
+ const lastBinding = handler.parameterBindings.at(-1);
54
+ const methodArguments = Array.from({
55
+ length: (lastBinding?.index ?? -1) + 1
56
+ });
57
+ for (const binding of handler.parameterBindings) {
58
+ switch (binding.kind) {
59
+ case 'parent':
60
+ methodArguments[binding.index] = parent;
61
+ break;
62
+ case 'context':
63
+ methodArguments[binding.index] = contextValue;
64
+ break;
65
+ default:
66
+ assertNever(binding.kind);
67
+ }
68
+ }
69
+ return methodArguments;
70
+ }
71
+ assertAllTargetsAttached() {
72
+ for (const typeName of this.entriesByTypeName.keys()) {
73
+ if (!this.attachedTypeNames.has(typeName)) {
74
+ throw new Error(`GraphQL object field resolver target type "${typeName}" is not reachable from a code-first root operation output type.`);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Container } from '@fluojs/di';
2
- import type { GraphQLError as GraphQLErrorType, GraphQLList as GraphQLListType, GraphQLObjectType as GraphQLObjectTypeType, GraphQLSchema as GraphQLSchemaType, GraphQLScalarType, GraphQLUnionType as GraphQLUnionTypeType } from 'graphql';
2
+ import type { GraphQLError as GraphQLErrorType, GraphQLList as GraphQLListType, GraphQLNonNull as GraphQLNonNullType, GraphQLObjectType as GraphQLObjectTypeType, GraphQLScalarType, GraphQLSchema as GraphQLSchemaType, GraphQLUnionType as GraphQLUnionTypeType } from 'graphql';
3
3
  import { type ResolverDescriptor } from '../types.js';
4
4
  type YogaGraphqlDeps = {
5
5
  GraphQLError: typeof GraphQLErrorType;
@@ -8,11 +8,15 @@ type YogaGraphqlDeps = {
8
8
  GraphQLID: GraphQLScalarType;
9
9
  GraphQLInt: GraphQLScalarType;
10
10
  GraphQLList: typeof GraphQLListType;
11
+ GraphQLNonNull: typeof GraphQLNonNullType;
11
12
  GraphQLObjectType: typeof GraphQLObjectTypeType;
12
13
  GraphQLSchema: typeof GraphQLSchemaType;
13
14
  GraphQLString: GraphQLScalarType;
14
15
  GraphQLUnionType: typeof GraphQLUnionTypeType;
15
16
  buildSchema: (source: string) => GraphQLSchemaType;
17
+ createGraphQLError: (message: string, options: {
18
+ extensions?: Record<string, unknown>;
19
+ }) => GraphQLErrorType;
16
20
  };
17
21
  /**
18
22
  * Resolve schema.
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAGV,YAAY,IAAI,gBAAgB,EAGhC,WAAW,IAAI,eAAe,EAC9B,iBAAiB,IAAI,qBAAqB,EAE1C,aAAa,IAAI,iBAAiB,EAClC,iBAAiB,EACjB,gBAAgB,IAAI,oBAAoB,EACzC,MAAM,SAAS,CAAC;AAIjB,OAAO,EAOL,KAAK,kBAAkB,EAGxB,MAAM,aAAa,CAAC;AAErB,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,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;CACpD,CAAC;AAiaF;;;;;;;;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,CA0CnB"}
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;AAkfF;;;;;;;;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,CA4EnB"}