@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/service.js CHANGED
@@ -4,14 +4,9 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
4
4
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
5
  function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
6
  function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
- import { AsyncLocalStorage } from 'node:async_hooks';
8
- import { createRequire } from 'node:module';
9
- import { Controller, Get, Post } from '@fluojs/http';
10
7
  import { Inject } from '@fluojs/core';
8
+ import { Controller, Get, Post } from '@fluojs/http';
11
9
  import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
12
- import { handleProtocols } from 'graphql-ws';
13
- import { useServer } from 'graphql-ws/lib/use/ws';
14
- import { WebSocketServer } from 'ws';
15
10
  import { discoverResolverDescriptors } from './discovery.js';
16
11
  import { createGraphqlValidationPlugin, resolveGraphqlRequestLimits } from './guardrails.js';
17
12
  import { GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN } from './internal-tokens.js';
@@ -24,13 +19,6 @@ const DEFAULT_GRAPHQL_WEBSOCKET_LIMITS = {
24
19
  maxOperationsPerConnection: 25,
25
20
  maxPayloadBytes: 64 * 1024
26
21
  };
27
- function hasNodeUpgradeServer(value) {
28
- if (typeof value !== 'object' || value === null) {
29
- return false;
30
- }
31
- const server = value;
32
- return typeof server.on === 'function' && typeof server.off === 'function';
33
- }
34
22
  function buildFrameworkRequestFromFetchRequest(request) {
35
23
  const requestUrl = new URL(request.url);
36
24
  return {
@@ -45,39 +33,6 @@ function buildFrameworkRequestFromFetchRequest(request) {
45
33
  url: requestUrl.pathname + requestUrl.search
46
34
  };
47
35
  }
48
- function buildFrameworkRequestFromIncomingMessage(request) {
49
- const requestUrl = new URL(request.url ?? '/graphql', 'http://localhost');
50
- return {
51
- cookies: {},
52
- headers: request.headers,
53
- method: request.method ?? 'GET',
54
- params: {},
55
- path: requestUrl.pathname,
56
- query: Object.fromEntries(requestUrl.searchParams.entries()),
57
- raw: request,
58
- url: requestUrl.pathname + requestUrl.search
59
- };
60
- }
61
- function isConnectionParamsRecord(value) {
62
- return typeof value === 'object' && value !== null && !Array.isArray(value);
63
- }
64
- function closeWebSocketServer(server) {
65
- return new Promise((resolve, reject) => {
66
- server.close(error => {
67
- if (error?.message === 'The server is not running') {
68
- resolve();
69
- return;
70
- }
71
- if (error) {
72
- reject(error);
73
- return;
74
- }
75
- resolve();
76
- });
77
- });
78
- }
79
- const graphqlRequestContextStorage = new AsyncLocalStorage();
80
- const runtimeRequire = createRequire(import.meta.url);
81
36
  let graphqlInstanceOfPatchRefCount = 0;
82
37
  let restoreGraphqlInstanceOfPatch;
83
38
  const allowedCrossRealmGraphqlObjects = new WeakSet();
@@ -108,16 +63,17 @@ class GraphqlEndpointController {
108
63
  }
109
64
  export { _GraphqlEndpointContr as GraphqlEndpointController };
110
65
  function getCrossRealmGraphqlTag(value, constructor) {
111
- const className = constructor.prototype?.[Symbol.toStringTag];
66
+ const prototypeTag = constructor.prototype?.[Symbol.toStringTag];
67
+ const className = typeof prototypeTag === 'string' ? prototypeTag : constructor.name;
112
68
  if (typeof className !== 'string' || !className.startsWith('GraphQL')) {
113
69
  return undefined;
114
70
  }
115
71
  if (typeof value !== 'object' || value === null) {
116
72
  return undefined;
117
73
  }
118
- if (Symbol.toStringTag in value) {
119
- const valueClassName = value[Symbol.toStringTag];
120
- return valueClassName === className ? className : undefined;
74
+ const valueTag = value[Symbol.toStringTag];
75
+ if (typeof valueTag === 'string') {
76
+ return valueTag === className ? className : undefined;
121
77
  }
122
78
  const valueClassName = value.constructor?.name;
123
79
  return valueClassName === className ? className : undefined;
@@ -131,7 +87,8 @@ function markAllowedCrossRealmGraphqlObjects(value, visited = new WeakSet()) {
131
87
  }
132
88
  visited.add(value);
133
89
  const tag = value[Symbol.toStringTag];
134
- if (typeof tag === 'string' && tag.startsWith('GraphQL')) {
90
+ const constructorName = value.constructor?.name;
91
+ if (typeof tag === 'string' && tag.startsWith('GraphQL') || typeof constructorName === 'string' && constructorName.startsWith('GraphQL')) {
135
92
  allowedCrossRealmGraphqlObjects.add(value);
136
93
  }
137
94
  if (Array.isArray(value)) {
@@ -150,8 +107,7 @@ function isAllowedCrossRealmGraphqlObject(value, constructor) {
150
107
  }
151
108
  return allowedCrossRealmGraphqlObjects.has(value) && getCrossRealmGraphqlTag(value, constructor) !== undefined;
152
109
  }
153
- function installGraphqlInstanceOfPatch() {
154
- const instanceOfModule = runtimeRequire('graphql/jsutils/instanceOf.js');
110
+ function installGraphqlInstanceOfPatch(instanceOfModule) {
155
111
  if (restoreGraphqlInstanceOfPatch) {
156
112
  graphqlInstanceOfPatchRefCount += 1;
157
113
  return releaseGraphqlInstanceOfPatch;
@@ -192,8 +148,10 @@ function releaseGraphqlInstanceOfPatch() {
192
148
  restoreGraphqlInstanceOfPatch = undefined;
193
149
  }
194
150
  async function loadGraphqlDeps() {
195
- const graphqlMod = runtimeRequire('graphql');
196
- const yogaMod = runtimeRequire('graphql-yoga');
151
+ const graphqlSpecifier = 'graphql';
152
+ const yogaSpecifier = 'graphql-yoga';
153
+ const instanceOfSpecifier = 'graphql/jsutils/instanceOf.js';
154
+ const [graphqlMod, yogaMod, instanceOfModule] = await Promise.all([import(/* @vite-ignore */graphqlSpecifier), import(/* @vite-ignore */yogaSpecifier), import(/* @vite-ignore */instanceOfSpecifier)]);
197
155
  return {
198
156
  GraphQLError: graphqlMod.GraphQLError,
199
157
  GraphQLBoolean: graphqlMod.GraphQLBoolean,
@@ -201,13 +159,16 @@ async function loadGraphqlDeps() {
201
159
  GraphQLID: graphqlMod.GraphQLID,
202
160
  GraphQLInt: graphqlMod.GraphQLInt,
203
161
  GraphQLList: graphqlMod.GraphQLList,
162
+ GraphQLNonNull: graphqlMod.GraphQLNonNull,
204
163
  GraphQLObjectType: graphqlMod.GraphQLObjectType,
205
164
  GraphQLSchema: graphqlMod.GraphQLSchema,
206
165
  GraphQLString: graphqlMod.GraphQLString,
207
166
  GraphQLUnionType: graphqlMod.GraphQLUnionType,
208
167
  buildSchema: graphqlMod.buildSchema,
168
+ createGraphQLError: yogaMod.createGraphQLError,
209
169
  createYoga: yogaMod.createYoga,
210
170
  execute: graphqlMod.execute,
171
+ instanceOfModule,
211
172
  subscribe: graphqlMod.subscribe
212
173
  };
213
174
  }
@@ -223,11 +184,9 @@ class GraphqlLifecycleService {
223
184
  graphQLErrorConstructor;
224
185
  middlewareRegistered = false;
225
186
  operationContainers = new WeakMap();
187
+ requestContexts = new WeakMap();
226
188
  websocketOperationContainers = new Map();
227
- websocketDisposable;
228
- websocketServer;
229
- websocketUpgradeListener;
230
- websocketUpgradeServer;
189
+ websocketTransport;
231
190
  executeGraphqlOperation;
232
191
  releaseGraphqlInstanceOfPatch;
233
192
  subscribeGraphqlOperation;
@@ -251,13 +210,15 @@ class GraphqlLifecycleService {
251
210
  }
252
211
  try {
253
212
  const fetchRequest = toFetchRequest(context.request);
213
+ this.requestContexts.set(fetchRequest, {
214
+ principal: context.requestContext.principal,
215
+ request: context.request
216
+ });
254
217
  try {
255
- const fetchResponse = await graphqlRequestContextStorage.run({
256
- principal: context.requestContext.principal,
257
- request: context.request
258
- }, () => yoga.fetch(fetchRequest));
218
+ const fetchResponse = await yoga.fetch(fetchRequest);
259
219
  await writeFetchResponse(fetchResponse, context.response);
260
220
  } finally {
221
+ this.requestContexts.delete(fetchRequest);
261
222
  await this.disposeOperationContainer(fetchRequest);
262
223
  }
263
224
  } catch (error) {
@@ -304,7 +265,7 @@ class GraphqlLifecycleService {
304
265
  } : {}),
305
266
  schema
306
267
  });
307
- this.registerWebSocketTransport();
268
+ await this.registerWebSocketTransport();
308
269
  this.registerMiddleware();
309
270
  this.middlewareRegistered = true;
310
271
  } catch (error) {
@@ -348,7 +309,7 @@ class GraphqlLifecycleService {
348
309
  };
349
310
  }
350
311
  resolveSchema(deps) {
351
- this.releaseGraphqlInstanceOfPatch ??= installGraphqlInstanceOfPatch();
312
+ this.releaseGraphqlInstanceOfPatch ??= installGraphqlInstanceOfPatch(deps.instanceOfModule);
352
313
  return resolveSchema(deps, this.options.schema, () => this.createCodeFirstSchema(deps), markAllowedCrossRealmGraphqlObjects);
353
314
  }
354
315
  createCodeFirstSchema(deps) {
@@ -386,7 +347,7 @@ class GraphqlLifecycleService {
386
347
  }
387
348
  }
388
349
  buildGraphqlContext(request, requestContextOverride, operationContainerOverride) {
389
- const storedContext = graphqlRequestContextStorage.getStore();
350
+ const storedContext = this.requestContexts.get(request);
390
351
  const requestContext = {
391
352
  connectionParams: requestContextOverride?.connectionParams,
392
353
  principal: requestContextOverride?.principal ?? storedContext?.principal,
@@ -404,85 +365,44 @@ class GraphqlLifecycleService {
404
365
  [GRAPHQL_OPERATION_CONTAINER]: operationContainer
405
366
  };
406
367
  }
407
- registerWebSocketTransport() {
408
- if (!this.isWebSocketTransportEnabled() || this.yoga === undefined || this.websocketUpgradeListener !== undefined) {
368
+ async registerWebSocketTransport() {
369
+ if (!this.isWebSocketTransportEnabled() || this.yoga === undefined || this.websocketTransport !== undefined) {
409
370
  return;
410
371
  }
411
- const upgradeServer = this.resolveUpgradeServer();
412
- const websocketLimits = this.resolveWebSocketLimits();
413
- const websocketServer = new WebSocketServer({
414
- handleProtocols: protocols => handleProtocols(protocols),
415
- maxPayload: websocketLimits?.maxPayloadBytes ?? 0,
416
- noServer: true
417
- });
418
- const upgradeListener = (request, socket, head) => {
419
- const targetPath = new URL(request.url ?? '/', 'http://localhost').pathname;
420
- if (!isGraphqlPath(targetPath)) {
421
- return;
422
- }
423
- if (websocketLimits && websocketServer.clients.size >= websocketLimits.maxConnections) {
424
- this.rejectWebSocketUpgrade(socket, 503, 'GraphQL websocket connection count exceeds the configured limit.');
425
- return;
426
- }
427
- websocketServer.handleUpgrade(request, socket, head, websocket => {
428
- websocketServer.emit('connection', websocket, request);
429
- });
430
- };
431
- const websocketDisposable = useServer({
432
- connectionInitWaitTimeout: this.options.subscriptions?.websocket?.connectionInitWaitTimeoutMs,
372
+ const {
373
+ createNodeGraphqlWebSocketTransport
374
+ } = await import('./node/graphql-websocket-transport.js');
375
+ this.websocketTransport = await createNodeGraphqlWebSocketTransport({
376
+ adapter: this.adapter,
377
+ connectionInitWaitTimeoutMs: this.options.subscriptions?.websocket?.connectionInitWaitTimeoutMs,
433
378
  execute: args => {
434
379
  if (!this.executeGraphqlOperation) {
435
380
  throw new Error('GraphQL execute function not initialized.');
436
381
  }
437
382
  return this.executeGraphqlOperation(args);
438
383
  },
439
- onComplete: async (context, message) => {
440
- await this.disposeWebSocketOperationContainer(context.extra.socket, message.id);
441
- },
442
- onDisconnect: async context => {
443
- await this.disposeAllWebSocketOperationContainers(context.extra.socket);
444
- },
445
- onSubscribe: async (context, message) => this.handleWebSocketSubscribe(context, message.id, message.payload),
384
+ keepAliveMs: this.options.subscriptions?.websocket?.keepAliveMs,
385
+ limits: this.resolveWebSocketLimits(),
386
+ onComplete: (socketKey, operationId) => this.disposeWebSocketOperationContainer(socketKey, operationId),
387
+ onDisconnect: socketKey => this.disposeAllWebSocketOperationContainers(socketKey),
388
+ onSubscribe: request => this.handleWebSocketSubscribe(request),
446
389
  subscribe: args => {
447
390
  if (!this.subscribeGraphqlOperation) {
448
391
  throw new Error('GraphQL subscribe function not initialized.');
449
392
  }
450
393
  return this.subscribeGraphqlOperation(args);
451
394
  }
452
- }, websocketServer, this.options.subscriptions?.websocket?.keepAliveMs);
453
- upgradeServer.on('upgrade', upgradeListener);
454
- this.websocketDisposable = websocketDisposable;
455
- this.websocketServer = websocketServer;
456
- this.websocketUpgradeListener = upgradeListener;
457
- this.websocketUpgradeServer = upgradeServer;
395
+ });
458
396
  }
459
397
  async unregisterWebSocketTransport() {
460
- if (this.websocketUpgradeListener && this.websocketUpgradeServer) {
461
- this.websocketUpgradeServer.off('upgrade', this.websocketUpgradeListener);
462
- }
463
- this.websocketUpgradeListener = undefined;
464
- this.websocketUpgradeServer = undefined;
465
- if (this.websocketServer) {
466
- for (const client of this.websocketServer.clients) {
467
- client.terminate();
468
- }
469
- }
470
- if (this.websocketDisposable) {
398
+ if (this.websocketTransport) {
471
399
  try {
472
- await this.websocketDisposable.dispose();
400
+ await this.websocketTransport.dispose();
473
401
  } catch (error) {
474
402
  this.logger.error('Failed to dispose GraphQL websocket transport.', error, 'GraphqlLifecycleService');
475
403
  }
476
404
  }
477
- this.websocketDisposable = undefined;
478
- if (this.websocketServer) {
479
- try {
480
- await closeWebSocketServer(this.websocketServer);
481
- } catch (error) {
482
- this.logger.error('Failed to close GraphQL websocket server.', error, 'GraphqlLifecycleService');
483
- }
484
- }
485
- this.websocketServer = undefined;
405
+ this.websocketTransport = undefined;
486
406
  for (const socketKey of this.websocketOperationContainers.keys()) {
487
407
  await this.disposeAllWebSocketOperationContainers(socketKey);
488
408
  }
@@ -490,32 +410,21 @@ class GraphqlLifecycleService {
490
410
  isWebSocketTransportEnabled() {
491
411
  return this.options.subscriptions?.websocket?.enabled === true;
492
412
  }
493
- resolveUpgradeServer() {
494
- if (typeof this.adapter.getServer !== 'function') {
495
- throw new Error('GraphQL websocket subscriptions require an HTTP adapter with getServer(). Use the Node HTTP adapter or provide a compatible adapter implementation.');
496
- }
497
- const server = this.adapter.getServer();
498
- if (!hasNodeUpgradeServer(server)) {
499
- throw new Error('GraphQL websocket subscriptions require adapter.getServer() to return a Node HTTP/S server that supports upgrade listeners.');
500
- }
501
- return server;
502
- }
503
- async handleWebSocketSubscribe(context, operationId, payload) {
413
+ async handleWebSocketSubscribe(request) {
504
414
  const yoga = this.yoga;
505
415
  if (!yoga) {
506
416
  throw new Error('GraphQL server not initialized.');
507
417
  }
508
- const websocketLimitError = this.createWebSocketOperationLimitError(context.extra.socket, operationId);
418
+ const websocketLimitError = this.createWebSocketOperationLimitError(request.socket, request.operationId);
509
419
  if (websocketLimitError) {
510
420
  return [websocketLimitError];
511
421
  }
512
- const frameworkRequest = buildFrameworkRequestFromIncomingMessage(context.extra.request);
513
- const fetchRequest = toFetchRequest(frameworkRequest);
514
- const operationContainer = this.getOrCreateWebSocketOperationContainer(context.extra.socket, operationId);
422
+ const fetchRequest = toFetchRequest(request.request);
423
+ const operationContainer = this.getOrCreateWebSocketOperationContainer(request.socket, request.operationId);
515
424
  const graphqlContext = this.buildGraphqlContext(fetchRequest, {
516
- connectionParams: isConnectionParamsRecord(context.connectionParams) ? context.connectionParams : undefined,
517
- request: frameworkRequest,
518
- socket: context.extra.socket
425
+ connectionParams: request.connectionParams,
426
+ request: request.request,
427
+ socket: request.socket
519
428
  }, operationContainer);
520
429
  try {
521
430
  const {
@@ -527,21 +436,21 @@ class GraphqlLifecycleService {
527
436
  request: fetchRequest,
528
437
  [GRAPHQL_CONTEXT_OVERRIDE]: graphqlContext
529
438
  });
530
- const document = parse(payload.query);
439
+ const document = parse(request.payload.query);
531
440
  const validationErrors = validate(schema, document);
532
441
  if (validationErrors.length > 0) {
533
- await this.disposeWebSocketOperationContainer(context.extra.socket, operationId);
442
+ await this.disposeWebSocketOperationContainer(request.socket, request.operationId);
534
443
  return validationErrors;
535
444
  }
536
445
  return {
537
446
  contextValue: await contextFactory(),
538
447
  document,
539
- operationName: payload.operationName ?? undefined,
448
+ operationName: request.payload.operationName ?? undefined,
540
449
  schema,
541
- variableValues: payload.variables
450
+ variableValues: request.payload.variables
542
451
  };
543
452
  } catch (error) {
544
- await this.disposeWebSocketOperationContainer(context.extra.socket, operationId);
453
+ await this.disposeWebSocketOperationContainer(request.socket, request.operationId);
545
454
  throw error;
546
455
  }
547
456
  }
@@ -560,15 +469,6 @@ class GraphqlLifecycleService {
560
469
  }
561
470
  return new GraphQLError(`GraphQL websocket active operation count exceeds the configured limit of ${String(limits.maxOperationsPerConnection)}.`);
562
471
  }
563
- rejectWebSocketUpgrade(socket, statusCode, message) {
564
- if (!socket.writable) {
565
- socket.destroy();
566
- return;
567
- }
568
- const body = `${message}\n`;
569
- 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(Buffer.byteLength(body))}`, '', body].join('\r\n'));
570
- socket.destroy();
571
- }
572
472
  getOrCreateWebSocketOperationContainer(socketKey, operationId) {
573
473
  const existingSocketContainers = this.websocketOperationContainers.get(socketKey);
574
474
  if (existingSocketContainers?.has(operationId)) {
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAA2B,MAAM,cAAc,CAAC;AAEjG;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAsED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUjE;AAgGD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BrH"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAA2B,MAAM,cAAc,CAAC;AAEjG;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AA6ED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUjE;AAgGD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BrH"}
@@ -34,13 +34,18 @@ function createFetchHeaders(request) {
34
34
  }
35
35
  return headers;
36
36
  }
37
+ function copyBytesToArrayBuffer(bytes) {
38
+ const body = new ArrayBuffer(bytes.byteLength);
39
+ new Uint8Array(body).set(bytes);
40
+ return body;
41
+ }
37
42
  function createFetchBody(request, headers) {
38
43
  const method = request.method.toUpperCase();
39
44
  if (method === 'GET' || method === 'HEAD') {
40
45
  return undefined;
41
46
  }
42
47
  if (request.rawBody) {
43
- return Buffer.from(request.rawBody);
48
+ return copyBytesToArrayBuffer(request.rawBody);
44
49
  }
45
50
  if (request.body === undefined) {
46
51
  return undefined;
@@ -49,10 +54,10 @@ function createFetchBody(request, headers) {
49
54
  return request.body;
50
55
  }
51
56
  if (request.body instanceof Uint8Array) {
52
- return Buffer.from(request.body);
57
+ return copyBytesToArrayBuffer(request.body);
53
58
  }
54
59
  if (request.body instanceof ArrayBuffer) {
55
- return Buffer.from(request.body);
60
+ return request.body;
56
61
  }
57
62
  if (!headers.has('content-type')) {
58
63
  headers.set('content-type', 'application/json; charset=utf-8');
package/dist/types.d.ts CHANGED
@@ -99,9 +99,20 @@ export interface ResolverMetadata {
99
99
  typeName: string;
100
100
  }
101
101
  /**
102
- * Supported GraphQL operation handler categories.
102
+ * Supported GraphQL root-operation and object-field handler categories.
103
103
  */
104
- export type ResolverHandlerType = 'query' | 'mutation' | 'subscription';
104
+ export type ResolverHandlerType = 'query' | 'mutation' | 'subscription' | 'field';
105
+ /**
106
+ * Explicit source kinds that can be bound to object field-resolver parameters.
107
+ */
108
+ export type FieldResolverParameterKind = 'parent' | 'context';
109
+ /**
110
+ * Describes one positional parameter binding for an object field resolver.
111
+ */
112
+ export interface FieldResolverParameterBindingMetadata {
113
+ index: number;
114
+ kind: FieldResolverParameterKind;
115
+ }
105
116
  /**
106
117
  * Scalar names supported by the code-first schema helpers.
107
118
  */
@@ -157,6 +168,7 @@ export interface ResolverHandlerMetadata {
157
168
  inputClass?: Function;
158
169
  argTypes?: Record<string, GraphqlArgType>;
159
170
  outputType?: GraphqlRootOutputType;
171
+ nullable?: boolean;
160
172
  }
161
173
  /**
162
174
  * Describes how one method parameter maps to a named GraphQL argument.
@@ -177,6 +189,8 @@ export interface ResolverHandlerDescriptor {
177
189
  argFields: ArgFieldMetadata[];
178
190
  argTypes?: Record<string, GraphqlArgType>;
179
191
  outputType?: GraphqlRootOutputType;
192
+ nullable?: boolean;
193
+ parameterBindings: FieldResolverParameterBindingMetadata[];
180
194
  }
181
195
  /**
182
196
  * Fully discovered resolver descriptor used by the GraphQL runtime.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -48,7 +48,15 @@ export const GRAPHQL_REQUEST_SCOPED_LOADER_CACHE = Symbol.for('fluo.graphql.requ
48
48
  */
49
49
 
50
50
  /**
51
- * Supported GraphQL operation handler categories.
51
+ * Supported GraphQL root-operation and object-field handler categories.
52
+ */
53
+
54
+ /**
55
+ * Explicit source kinds that can be bound to object field-resolver parameters.
56
+ */
57
+
58
+ /**
59
+ * Describes one positional parameter binding for an object field resolver.
52
60
  */
53
61
 
54
62
  /**
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "yoga",
10
10
  "api"
11
11
  ],
12
- "version": "1.0.3",
12
+ "version": "1.1.0",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -18,7 +18,7 @@
18
18
  "directory": "packages/graphql"
19
19
  },
20
20
  "engines": {
21
- "node": ">=20.0.0"
21
+ "node": ">=20.16.0"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"
@@ -41,11 +41,11 @@
41
41
  "graphql-ws": "^5.16.2",
42
42
  "graphql-yoga": "^5.18.1",
43
43
  "ws": "^8.18.3",
44
- "@fluojs/core": "^1.0.3",
45
- "@fluojs/di": "^1.0.3",
46
- "@fluojs/http": "^1.1.0",
47
- "@fluojs/runtime": "^1.1.1",
48
- "@fluojs/validation": "^1.0.4"
44
+ "@fluojs/core": "^1.1.0",
45
+ "@fluojs/di": "^2.0.0",
46
+ "@fluojs/http": "^2.0.1",
47
+ "@fluojs/runtime": "^2.0.1",
48
+ "@fluojs/validation": "^1.0.6"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/ws": "^8.18.1",