@gqloom/core 0.8.4 → 0.9.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/dist/index.cjs CHANGED
@@ -22,7 +22,6 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  BaseChainFactory: () => BaseChainFactory,
24
24
  ChainResolver: () => ChainResolver,
25
- ContextMemoization: () => ContextMemoization,
26
25
  EasyDataLoader: () => EasyDataLoader,
27
26
  FieldChainFactory: () => FieldChainFactory,
28
27
  FieldFactoryWithResolve: () => FieldFactoryWithResolve,
@@ -37,13 +36,12 @@ __export(src_exports, {
37
36
  SYMBOLS: () => symbols_exports,
38
37
  SubscriptionChainFactory: () => SubscriptionChainFactory,
39
38
  applyMiddlewares: () => applyMiddlewares,
39
+ assignContextMap: () => assignContextMap,
40
40
  capitalize: () => capitalize,
41
41
  collectName: () => collectName,
42
42
  collectNames: () => collectNames,
43
- compose: () => compose,
44
43
  createField: () => createField,
45
44
  createInputParser: () => createInputParser,
46
- createMemoization: () => createMemoization,
47
45
  createMutation: () => createMutation,
48
46
  createQuery: () => createQuery,
49
47
  createSubscription: () => createSubscription,
@@ -53,10 +51,13 @@ __export(src_exports, {
53
51
  ensureInputType: () => ensureInputType,
54
52
  ensureInterfaceType: () => ensureInterfaceType,
55
53
  field: () => field,
54
+ filterMiddlewares: () => filterMiddlewares,
56
55
  getCacheType: () => getCacheType,
57
56
  getFieldOptions: () => getFieldOptions,
58
57
  getGraphQLType: () => getGraphQLType,
58
+ getMemoizationMap: () => getMemoizationMap,
59
59
  getOperationOptions: () => getOperationOptions,
60
+ getResolvingFields: () => getResolvingFields,
60
61
  getStandardValue: () => getStandardValue,
61
62
  getSubscriptionOptions: () => getSubscriptionOptions,
62
63
  initWeaverContext: () => initWeaverContext,
@@ -76,20 +77,17 @@ __export(src_exports, {
76
77
  nullableSilk: () => nullableSilk,
77
78
  onlyMemoization: () => onlyMemoization,
78
79
  parseInputValue: () => parseInputValue,
80
+ parseResolvingFields: () => parseResolvingFields,
79
81
  parseSilk: () => parseSilk,
80
82
  pascalCase: () => pascalCase,
81
83
  provideWeaverContext: () => provideWeaverContext,
82
84
  query: () => query,
83
85
  resolver: () => resolver,
84
- resolverPayloadStorage: () => resolverPayloadStorage,
85
86
  screamingSnakeCase: () => screamingSnakeCase,
86
87
  silk: () => silk,
87
88
  subscription: () => subscription,
88
89
  toObjMap: () => toObjMap,
89
90
  tryIn: () => tryIn,
90
- useContext: () => useContext,
91
- useMemoizationMap: () => useMemoizationMap,
92
- useResolverPayload: () => useResolverPayload,
93
91
  weave: () => weave,
94
92
  weaverContext: () => weaverContext
95
93
  });
@@ -108,20 +106,22 @@ function getSubscriptionOptions(subscribeOrOptions) {
108
106
  }
109
107
  return subscribeOrOptions;
110
108
  }
111
- function getFieldOptions({
112
- description,
113
- deprecationReason,
114
- extensions
115
- }) {
109
+ function getFieldOptions({ description, deprecationReason, extensions }, extraExtensions) {
116
110
  return {
117
111
  description,
118
112
  deprecationReason,
119
- extensions
113
+ extensions: extraExtensions ? { ...extensions, ...extraExtensions } : extensions
120
114
  };
121
115
  }
122
116
 
123
117
  // src/utils/middleware.ts
124
- function applyMiddlewares(middlewares, resolveFunction, options) {
118
+ var defaultOperations = [
119
+ "field",
120
+ "mutation",
121
+ "query",
122
+ "subscription.subscribe"
123
+ ];
124
+ function applyMiddlewares(options, resolveFunction, middlewares) {
125
125
  const next = (index) => {
126
126
  if (index >= middlewares.length) {
127
127
  return resolveFunction();
@@ -135,122 +135,23 @@ function applyMiddlewares(middlewares, resolveFunction, options) {
135
135
  };
136
136
  return next(0);
137
137
  }
138
- function compose(...lists) {
139
- const list = [];
140
- for (const item of lists) {
141
- if (item != null) {
142
- list.push(...item);
143
- }
144
- }
145
- return list;
146
- }
147
-
148
- // src/utils/context.ts
149
- var import_async_hooks = require("async_hooks");
150
-
151
- // src/utils/symbols.ts
152
- var symbols_exports = {};
153
- __export(symbols_exports, {
154
- CONTEXT_MEMORY_MAP_KEY: () => CONTEXT_MEMORY_MAP_KEY,
155
- FIELD_HIDDEN: () => FIELD_HIDDEN,
156
- GET_GRAPHQL_TYPE: () => GET_GRAPHQL_TYPE,
157
- IS_RESOLVER: () => IS_RESOLVER,
158
- RESOLVER_OPTIONS_KEY: () => RESOLVER_OPTIONS_KEY,
159
- WEAVER_CONFIG: () => WEAVER_CONFIG
160
- });
161
- var GET_GRAPHQL_TYPE = Symbol.for("gqloom.get_graphql_type");
162
- var WEAVER_CONFIG = Symbol.for("gqloom.weaver_config");
163
- var RESOLVER_OPTIONS_KEY = Symbol.for("gqloom.resolver-options");
164
- var IS_RESOLVER = Symbol.for("gqloom.is-resolver");
165
- var CONTEXT_MEMORY_MAP_KEY = Symbol.for("gqloom.context-memory");
166
- var FIELD_HIDDEN = Symbol.for("gqloom.field-hidden");
167
-
168
- // src/utils/context.ts
169
- function onlyMemoization() {
170
- return { memoization: /* @__PURE__ */ new WeakMap(), isMemoization: true };
171
- }
172
- function isOnlyMemoryPayload(payload) {
173
- return payload.isMemoization === true;
174
- }
175
- var resolverPayloadStorage = new import_async_hooks.AsyncLocalStorage();
176
- function useResolverPayload() {
177
- const payload = resolverPayloadStorage.getStore();
178
- if (payload === void 0 || isOnlyMemoryPayload(payload)) return;
179
- return payload;
180
- }
181
- function useContext() {
182
- return useResolverPayload()?.context;
183
- }
184
- function useMemoizationMap() {
185
- const payload = resolverPayloadStorage.getStore();
186
- if (payload == null) return;
187
- if (isOnlyMemoryPayload(payload)) return payload.memoization;
188
- return ContextMemoization.assignMemoizationMap(payload.context);
138
+ function filterMiddlewares(operation, ...middlewareList) {
139
+ return middlewareList.reduce((acc, m) => {
140
+ if (!m) return acc;
141
+ acc.push(
142
+ ...ensureArray(m).filter((m2) => {
143
+ const ops = m2.operations ?? defaultOperations;
144
+ return ops.includes(operation);
145
+ })
146
+ );
147
+ return acc;
148
+ }, []);
189
149
  }
190
- var ContextMemoization = class {
191
- constructor(getter, options = {}) {
192
- this.getter = getter;
193
- this.getter = getter;
194
- this.getMemoizationMap = options.getMemoizationMap ?? useMemoizationMap;
195
- this.key = options.key ?? this.getter;
196
- }
197
- getMemoizationMap;
198
- key;
199
- /**
200
- * Get the value in memoization or call the getter function
201
- * @returns the value of the getter function
202
- */
203
- get() {
204
- const map = this.getMemoizationMap();
205
- if (!map) return this.getter();
206
- if (!map.has(this.key)) {
207
- map.set(this.key, this.getter());
208
- }
209
- return map.get(this.key);
210
- }
211
- /**
212
- * Clear the memoization
213
- * @returns true if the memoization is cleared, undefined if the context is not found
214
- */
215
- clear() {
216
- const map = this.getMemoizationMap();
217
- if (!map) return;
218
- return map.delete(this.key);
219
- }
220
- /**
221
- * Check if the memoization exists
222
- * @returns true if the memoization exists, undefined if the context is not found
223
- */
224
- exists() {
225
- const map = this.getMemoizationMap();
226
- if (!map) return;
227
- return map.has(this.key);
228
- }
229
- /**
230
- * Set a new value to the memoization
231
- * @param value the new value to set
232
- * @returns the memoization map or undefined if the context is not found
233
- */
234
- set(value) {
235
- const map = this.getMemoizationMap();
236
- if (!map) return;
237
- return map.set(this.key, value);
238
- }
239
- static assignMemoizationMap(target) {
240
- target[CONTEXT_MEMORY_MAP_KEY] ??= /* @__PURE__ */ new WeakMap();
241
- return target[CONTEXT_MEMORY_MAP_KEY];
150
+ function ensureArray(value) {
151
+ if (value != null && typeof value === "object" && Symbol.iterator in value) {
152
+ return Array.from(value);
242
153
  }
243
- };
244
- function createMemoization(...args) {
245
- const memoization = new ContextMemoization(...args);
246
- const callable = () => memoization.get();
247
- return Object.assign(callable, {
248
- get: () => memoization.get(),
249
- set: (value) => memoization.set(value),
250
- clear: () => memoization.clear(),
251
- exists: () => memoization.exists(),
252
- getter: memoization.getter
253
- });
154
+ return [value];
254
155
  }
255
156
 
256
157
  // src/utils/object.ts
@@ -306,6 +207,167 @@ function meta(data) {
306
207
  return { "~meta": data };
307
208
  }
308
209
 
210
+ // src/utils/parse-resolving-fields.ts
211
+ var import_graphql3 = require("graphql");
212
+
213
+ // src/utils/constants.ts
214
+ var DERIVED_DEPENDENCIES = "loom.derived-from-dependencies";
215
+
216
+ // src/utils/type.ts
217
+ var import_graphql = require("graphql");
218
+ var import_graphql2 = require("graphql");
219
+ function unwrapType(gqlType) {
220
+ if ((0, import_graphql2.isNonNullType)(gqlType)) {
221
+ return unwrapType(gqlType.ofType);
222
+ }
223
+ if ((0, import_graphql.isListType)(gqlType)) {
224
+ return unwrapType(gqlType.ofType);
225
+ }
226
+ return gqlType;
227
+ }
228
+
229
+ // src/utils/parse-resolving-fields.ts
230
+ function getResolvingFields(payload) {
231
+ const requestedFields = parseResolvingFields(payload.info);
232
+ const derivedFields = /* @__PURE__ */ new Set();
233
+ const derivedDependencies = /* @__PURE__ */ new Set();
234
+ const resolvingObject = unwrapType(payload.info.returnType);
235
+ if ((0, import_graphql3.isObjectType)(resolvingObject)) {
236
+ const objectFields = resolvingObject.getFields();
237
+ for (const requestedFieldName of requestedFields) {
238
+ const field2 = objectFields[requestedFieldName];
239
+ if (field2) {
240
+ const deps = field2.extensions?.[DERIVED_DEPENDENCIES];
241
+ if (deps && Array.isArray(deps) && deps.length > 0) {
242
+ derivedFields.add(requestedFieldName);
243
+ for (const d of deps) derivedDependencies.add(d);
244
+ }
245
+ }
246
+ }
247
+ }
248
+ const selectedFields = new Set(requestedFields);
249
+ for (const f of derivedFields) selectedFields.delete(f);
250
+ for (const d of derivedDependencies) selectedFields.add(d);
251
+ return { requestedFields, derivedFields, derivedDependencies, selectedFields };
252
+ }
253
+ function parseResolvingFields(info, maxDepth = 1) {
254
+ return new ResolvingFieldsParser(info, maxDepth).parse();
255
+ }
256
+ var ResolvingFieldsParser = class {
257
+ /** Store unique field paths */
258
+ fields = /* @__PURE__ */ new Set();
259
+ /** Track visited fragments to prevent circular references */
260
+ visitedFragments = /* @__PURE__ */ new Set();
261
+ /** The GraphQL resolve info object */
262
+ info;
263
+ /** Maximum depth of nested fields to parse */
264
+ maxDepth;
265
+ constructor(info, maxDepth) {
266
+ this.info = info;
267
+ this.maxDepth = maxDepth;
268
+ }
269
+ /**
270
+ * Parses the GraphQL resolve info to extract all requested fields.
271
+ * @returns A Set of field paths
272
+ */
273
+ parse() {
274
+ for (const fieldNode of this.info.fieldNodes) {
275
+ this.collectFields(fieldNode.selectionSet);
276
+ }
277
+ return this.fields;
278
+ }
279
+ /**
280
+ * Recursively collects fields from a selection set.
281
+ * Handles fields, inline fragments, and fragment spreads.
282
+ *
283
+ * @param selectionSet - The selection set to process
284
+ * @param parentPath - The path of the parent field (for nested fields)
285
+ * @param currentDepth - Current depth of recursion
286
+ */
287
+ collectFields(selectionSet, parentPath = "", currentDepth = 0) {
288
+ if (!selectionSet?.selections.length || currentDepth >= this.maxDepth)
289
+ return;
290
+ for (const selection of selectionSet.selections) {
291
+ if (!this.shouldIncludeNode(selection)) continue;
292
+ switch (selection.kind) {
293
+ case import_graphql3.Kind.FIELD: {
294
+ const fieldName = selection.name.value;
295
+ const fieldPath = parentPath ? `${parentPath}.${fieldName}` : fieldName;
296
+ this.fields.add(fieldPath);
297
+ const hasSelectionSet = selection.selectionSet != null;
298
+ if (hasSelectionSet) {
299
+ this.collectFields(
300
+ selection.selectionSet,
301
+ fieldPath,
302
+ currentDepth + 1
303
+ );
304
+ }
305
+ break;
306
+ }
307
+ case import_graphql3.Kind.INLINE_FRAGMENT: {
308
+ if (selection.selectionSet) {
309
+ this.collectFields(selection.selectionSet, parentPath, currentDepth);
310
+ }
311
+ break;
312
+ }
313
+ case import_graphql3.Kind.FRAGMENT_SPREAD: {
314
+ const fragmentName = selection.name.value;
315
+ if (this.visitedFragments.has(fragmentName)) continue;
316
+ this.visitedFragments.add(fragmentName);
317
+ const fragment = this.info.fragments[fragmentName];
318
+ if (fragment) {
319
+ this.collectFields(fragment.selectionSet, parentPath, currentDepth);
320
+ }
321
+ break;
322
+ }
323
+ }
324
+ }
325
+ }
326
+ /**
327
+ * Extracts the boolean value from a directive's 'if' argument.
328
+ * Handles both literal boolean values and variables.
329
+ *
330
+ * @param directive - The directive node to extract value from
331
+ * @returns The boolean value of the directive's condition
332
+ */
333
+ getDirectiveValue(directive) {
334
+ const ifArg = directive.arguments?.find(
335
+ (arg) => arg.name.value === "if"
336
+ );
337
+ if (!ifArg) return true;
338
+ const value = ifArg.value;
339
+ if (value.kind === import_graphql3.Kind.BOOLEAN) {
340
+ return value.value;
341
+ }
342
+ if (value.kind === import_graphql3.Kind.VARIABLE) {
343
+ const variableName = value.name.value;
344
+ const variableValue = this.info.variableValues?.[variableName];
345
+ return variableValue === true;
346
+ }
347
+ return true;
348
+ }
349
+ /**
350
+ * Determines if a selection node should be included based on its directives.
351
+ * Handles both @include and @skip directives.
352
+ *
353
+ * @param node - The selection node to check
354
+ * @returns Whether the node should be included
355
+ */
356
+ shouldIncludeNode(node) {
357
+ if (!node.directives?.length) return true;
358
+ return node.directives.every((directive) => {
359
+ const isIncludeDirective = directive.name.value === "include";
360
+ if (isIncludeDirective) {
361
+ return this.getDirectiveValue(directive);
362
+ }
363
+ if (directive.name.value === "skip") {
364
+ return !this.getDirectiveValue(directive);
365
+ }
366
+ return true;
367
+ });
368
+ }
369
+ };
370
+
309
371
  // src/utils/string.ts
310
372
  function pascalCase(str) {
311
373
  return str.split(/[\s-_]+/).map(
@@ -413,11 +475,47 @@ var EasyDataLoader = class _EasyDataLoader {
413
475
  }
414
476
  };
415
477
 
478
+ // src/utils/symbols.ts
479
+ var symbols_exports = {};
480
+ __export(symbols_exports, {
481
+ CONTEXT_MAP_KEY: () => CONTEXT_MAP_KEY,
482
+ FIELD_HIDDEN: () => FIELD_HIDDEN,
483
+ GET_GRAPHQL_TYPE: () => GET_GRAPHQL_TYPE,
484
+ IS_RESOLVER: () => IS_RESOLVER,
485
+ RESOLVER_OPTIONS_KEY: () => RESOLVER_OPTIONS_KEY,
486
+ WEAVER_CONFIG: () => WEAVER_CONFIG
487
+ });
488
+ var GET_GRAPHQL_TYPE = Symbol.for("gqloom.get_graphql_type");
489
+ var WEAVER_CONFIG = Symbol.for("gqloom.weaver_config");
490
+ var RESOLVER_OPTIONS_KEY = Symbol.for("gqloom.resolver-options");
491
+ var IS_RESOLVER = Symbol.for("gqloom.is-resolver");
492
+ var CONTEXT_MAP_KEY = Symbol.for("gqloom.context-map");
493
+ var FIELD_HIDDEN = Symbol.for("gqloom.field-hidden");
494
+
495
+ // src/utils/context.ts
496
+ function onlyMemoization() {
497
+ return { memoization: /* @__PURE__ */ new WeakMap(), isMemoization: true };
498
+ }
499
+ function isOnlyMemoryPayload(payload) {
500
+ return payload.isMemoization === true;
501
+ }
502
+ function getMemoizationMap(payload) {
503
+ if (isOnlyMemoryPayload(payload)) return payload.memoization;
504
+ if (typeof payload.context === "undefined") {
505
+ Object.defineProperty(payload, "context", { value: {} });
506
+ }
507
+ return assignContextMap(payload.context);
508
+ }
509
+ function assignContextMap(target) {
510
+ target[CONTEXT_MAP_KEY] ??= /* @__PURE__ */ new WeakMap();
511
+ return target[CONTEXT_MAP_KEY];
512
+ }
513
+
416
514
  // src/resolver/silk.ts
417
- var import_graphql2 = require("graphql");
515
+ var import_graphql5 = require("graphql");
418
516
 
419
517
  // src/schema/weaver-context.ts
420
- var import_graphql = require("graphql");
518
+ var import_graphql4 = require("graphql");
421
519
  var ref;
422
520
  var names = /* @__PURE__ */ new WeakMap();
423
521
  function initWeaverContext() {
@@ -442,7 +540,7 @@ function initWeaverContext() {
442
540
  namedTypes: /* @__PURE__ */ new Map(),
443
541
  memoNamedType(gqlTypeValue) {
444
542
  const gqlType = gqlTypeValue;
445
- if ((0, import_graphql.isObjectType)(gqlType) || (0, import_graphql.isUnionType)(gqlType) || (0, import_graphql.isEnumType)(gqlType) || (0, import_graphql.isScalarType)(gqlType)) {
543
+ if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isUnionType)(gqlType) || (0, import_graphql4.isEnumType)(gqlType) || (0, import_graphql4.isScalarType)(gqlType)) {
446
544
  this.namedTypes.set(gqlType.name, gqlType);
447
545
  }
448
546
  return gqlTypeValue;
@@ -562,10 +660,10 @@ function nonNullSilk(origin) {
562
660
  ...origin,
563
661
  [GET_GRAPHQL_TYPE]: () => {
564
662
  const originType = getGraphQLType(origin);
565
- if (originType instanceof import_graphql2.GraphQLNonNull) {
663
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
566
664
  return originType;
567
665
  } else {
568
- return new import_graphql2.GraphQLNonNull(originType);
666
+ return new import_graphql5.GraphQLNonNull(originType);
569
667
  }
570
668
  }
571
669
  };
@@ -575,13 +673,13 @@ function listSilk(origin) {
575
673
  ...origin,
576
674
  [GET_GRAPHQL_TYPE]: () => {
577
675
  let originType = getGraphQLType(origin);
578
- if (originType instanceof import_graphql2.GraphQLNonNull && originType.ofType instanceof import_graphql2.GraphQLList) {
676
+ if (originType instanceof import_graphql5.GraphQLNonNull && originType.ofType instanceof import_graphql5.GraphQLList) {
579
677
  originType = originType.ofType.ofType;
580
678
  }
581
- if (originType instanceof import_graphql2.GraphQLList) {
679
+ if (originType instanceof import_graphql5.GraphQLList) {
582
680
  originType = originType.ofType;
583
681
  }
584
- return new import_graphql2.GraphQLNonNull(new import_graphql2.GraphQLList(originType));
682
+ return new import_graphql5.GraphQLNonNull(new import_graphql5.GraphQLList(originType));
585
683
  }
586
684
  };
587
685
  }
@@ -590,7 +688,7 @@ function nullableSilk(origin) {
590
688
  ...origin,
591
689
  [GET_GRAPHQL_TYPE]: () => {
592
690
  const originType = getGraphQLType(origin);
593
- if (originType instanceof import_graphql2.GraphQLNonNull) {
691
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
594
692
  return originType.ofType;
595
693
  } else {
596
694
  return originType;
@@ -622,7 +720,7 @@ function isSilk(target) {
622
720
  }
623
721
 
624
722
  // src/resolver/input.ts
625
- var import_graphql3 = require("graphql");
723
+ var import_graphql6 = require("graphql");
626
724
  function createInputParser(schema, value) {
627
725
  let result;
628
726
  const parse = async () => {
@@ -669,19 +767,26 @@ function getStandardValue(result) {
669
767
  if (result == null) return result;
670
768
  const { issues } = result;
671
769
  if (issues?.length) {
672
- throw new import_graphql3.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
770
+ throw new import_graphql6.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
673
771
  extensions: { issues }
674
772
  });
675
773
  }
676
774
  if ("value" in result) return result.value;
677
- else throw new import_graphql3.GraphQLError("Invalid input");
775
+ else throw new import_graphql6.GraphQLError("Invalid input");
678
776
  }
679
777
 
680
778
  // src/resolver/resolver-chain-factory.ts
681
779
  var BaseChainFactory = class _BaseChainFactory {
780
+ /**
781
+ * Creates a new instance of the chain factory
782
+ * @param options - Configuration options for the factory
783
+ */
682
784
  constructor(options) {
683
785
  this.options = options;
684
786
  }
787
+ /**
788
+ * Returns the available methods for the chain factory
789
+ */
685
790
  static methods() {
686
791
  return {
687
792
  description: _BaseChainFactory.prototype.description,
@@ -689,15 +794,31 @@ var BaseChainFactory = class _BaseChainFactory {
689
794
  extensions: _BaseChainFactory.prototype.extensions
690
795
  };
691
796
  }
797
+ /**
798
+ * Sets the description for the field
799
+ * @param description - The description text
800
+ */
692
801
  description(description) {
693
802
  return this.clone({ description });
694
803
  }
804
+ /**
805
+ * Sets the deprecation reason for the field
806
+ * @param deprecationReason - The reason for deprecation
807
+ */
695
808
  deprecationReason(deprecationReason) {
696
809
  return this.clone({ deprecationReason });
697
810
  }
811
+ /**
812
+ * Sets custom extensions for the field
813
+ * @param extensions - Custom extensions to add
814
+ */
698
815
  extensions(extensions) {
699
816
  return this.clone({ extensions });
700
817
  }
818
+ /**
819
+ * Adds middleware functions to the field
820
+ * @param middlewares - Middleware functions to add
821
+ */
701
822
  use(...middlewares) {
702
823
  return this.clone({
703
824
  middlewares: [...this.options?.middlewares ?? [], ...middlewares]
@@ -705,6 +826,9 @@ var BaseChainFactory = class _BaseChainFactory {
705
826
  }
706
827
  };
707
828
  var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
829
+ /**
830
+ * Returns the available methods for the field chain factory
831
+ */
708
832
  static methods() {
709
833
  return {
710
834
  ...BaseChainFactory.methods(),
@@ -714,15 +838,42 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
714
838
  clone: _FieldChainFactory.prototype.clone
715
839
  };
716
840
  }
841
+ /**
842
+ * Creates a clone of the current factory with new options
843
+ * @param options - New options to apply to the clone
844
+ */
717
845
  clone(options) {
718
846
  return new _FieldChainFactory({ ...this.options, ...options });
719
847
  }
848
+ /**
849
+ * Sets the output type for the field
850
+ * @template TOutputNew - The new output type
851
+ * @param output - The output type definition
852
+ */
720
853
  output(output) {
721
854
  return new _FieldChainFactory({ ...this.options, output });
722
855
  }
856
+ /**
857
+ * Sets the input type for the field
858
+ * @template TInputNew - The new input type
859
+ * @param input - The input type definition
860
+ */
723
861
  input(input) {
724
862
  return new _FieldChainFactory({ ...this.options, input });
725
863
  }
864
+ /**
865
+ * Specifies the dependencies for the field
866
+ * @template TDependencies - The dependencies type
867
+ * @param dependencies - The dependencies to add
868
+ */
869
+ derivedFrom(...dependencies) {
870
+ return this.clone({ dependencies });
871
+ }
872
+ /**
873
+ * Sets the resolve function for the field
874
+ * @template TParent - The parent type
875
+ * @param resolve - The resolve function
876
+ */
726
877
  resolve(resolve) {
727
878
  if (!this.options?.output) throw new Error("Output is required");
728
879
  return createField(this.options.output, {
@@ -730,40 +881,47 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
730
881
  resolve
731
882
  });
732
883
  }
884
+ /**
885
+ * Creates a field resolver that uses DataLoader for batch loading data.
886
+ * This method is particularly useful for optimizing performance when dealing with multiple data requests
887
+ * by batching them together and handling caching automatically.
888
+ *
889
+ * @template TParent - The parent type that extends GraphQLSilk
890
+ * @param resolve - A function that handles batch loading of data. The function receives:
891
+ * - When no input type is defined: An array of parent objects
892
+ * - When input type is defined: An array of tuples containing [parent, input]
893
+ * - An array of resolver payloads
894
+ * @returns A GraphQL field resolver that implements batch loading
895
+ */
733
896
  load(resolve) {
734
897
  if (!this.options?.output) throw new Error("Output is required");
735
- const useUnifiedParseInput = createMemoization(() => ({ current: void 0 }));
736
- const useUserLoader = createMemoization(
737
- () => new EasyDataLoader(
738
- async (parents) => resolve(
739
- parents,
740
- await useUnifiedParseInput().current?.getResult()
741
- )
742
- )
743
- );
744
- const operation = "field";
745
- return meta({
746
- ...getFieldOptions(this.options),
747
- operation,
748
- input: this.options.input,
749
- output: this.options.output,
750
- resolve: async (parent, inputValue, extraOptions) => {
751
- const unifiedParseInput = useUnifiedParseInput();
752
- unifiedParseInput.current ??= createInputParser(
753
- this.options?.input,
754
- inputValue
755
- );
756
- const parseInput = unifiedParseInput.current;
757
- return applyMiddlewares(
758
- compose(extraOptions?.middlewares, this.options?.middlewares),
759
- async () => useUserLoader().load(parent),
760
- { parseInput, parent, outputSilk: this.output, operation }
761
- );
898
+ const hasInput = typeof this.options.input !== "undefined";
899
+ const initLoader = () => new EasyDataLoader((args) => {
900
+ const parents = args.map(
901
+ ([parent, input]) => hasInput ? [parent, input] : parent
902
+ );
903
+ const payloads = args.map(([, , payload]) => payload);
904
+ return resolve(parents, payloads);
905
+ });
906
+ return createField(this.options.output, {
907
+ ...this.options,
908
+ resolve: (parent, input, payload) => {
909
+ const loader = (() => {
910
+ if (!payload) return initLoader();
911
+ const memoMap = getMemoizationMap(payload);
912
+ if (!memoMap.has(resolve)) memoMap.set(resolve, initLoader());
913
+ return memoMap.get(resolve);
914
+ })();
915
+ return loader.load([parent, input, payload]);
762
916
  }
763
917
  });
764
918
  }
765
919
  };
766
920
  var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
921
+ /**
922
+ * Returns the available methods for the query chain factory
923
+ * @returns An object containing all available methods
924
+ */
767
925
  static methods() {
768
926
  return {
769
927
  ...BaseChainFactory.methods(),
@@ -773,15 +931,38 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
773
931
  clone: _QueryChainFactory.prototype.clone
774
932
  };
775
933
  }
934
+ /**
935
+ * Creates a clone of the current factory with new options
936
+ * @param options - New options to apply to the clone
937
+ * @returns A new instance of QueryChainFactory with the updated options
938
+ */
776
939
  clone(options) {
777
940
  return new _QueryChainFactory({ ...this.options, ...options });
778
941
  }
942
+ /**
943
+ * Sets the output type for the query
944
+ * @template TOutputNew - The new output type
945
+ * @param output - The output type definition
946
+ * @returns A new QueryChainFactory instance with the updated output type
947
+ */
779
948
  output(output) {
780
949
  return new _QueryChainFactory({ ...this.options, output });
781
950
  }
951
+ /**
952
+ * Sets the input type for the query
953
+ * @template TInputNew - The new input type
954
+ * @param input - The input type definition
955
+ * @returns A new QueryChainFactory instance with the updated input type
956
+ */
782
957
  input(input) {
783
958
  return new _QueryChainFactory({ ...this.options, input });
784
959
  }
960
+ /**
961
+ * Sets the resolve function for the query
962
+ * @param resolve - The resolve function that processes the input and returns the output
963
+ * @returns A GraphQL query resolver
964
+ * @throws {Error} If output type is not set
965
+ */
785
966
  resolve(resolve) {
786
967
  if (!this.options?.output) throw new Error("Output is required");
787
968
  return createQuery(this.options.output, {
@@ -791,6 +972,10 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
791
972
  }
792
973
  };
793
974
  var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory {
975
+ /**
976
+ * Returns the available methods for the mutation chain factory
977
+ * @returns An object containing all available methods
978
+ */
794
979
  static methods() {
795
980
  return {
796
981
  ...BaseChainFactory.methods(),
@@ -800,15 +985,38 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
800
985
  clone: _MutationChainFactory.prototype.clone
801
986
  };
802
987
  }
988
+ /**
989
+ * Creates a clone of the current factory with new options
990
+ * @param options - New options to apply to the clone
991
+ * @returns A new instance of MutationChainFactory with the updated options
992
+ */
803
993
  clone(options) {
804
994
  return new _MutationChainFactory({ ...this.options, ...options });
805
995
  }
996
+ /**
997
+ * Sets the output type for the mutation
998
+ * @template TOutputNew - The new output type
999
+ * @param output - The output type definition
1000
+ * @returns A new MutationChainFactory instance with the updated output type
1001
+ */
806
1002
  output(output) {
807
1003
  return new _MutationChainFactory({ ...this.options, output });
808
1004
  }
1005
+ /**
1006
+ * Sets the input type for the mutation
1007
+ * @template TInputNew - The new input type
1008
+ * @param input - The input type definition
1009
+ * @returns A new MutationChainFactory instance with the updated input type
1010
+ */
809
1011
  input(input) {
810
1012
  return new _MutationChainFactory({ ...this.options, input });
811
1013
  }
1014
+ /**
1015
+ * Sets the resolve function for the mutation
1016
+ * @param resolve - The resolve function that processes the input and returns the output
1017
+ * @returns A GraphQL mutation resolver
1018
+ * @throws {Error} If output type is not set
1019
+ */
812
1020
  resolve(resolve) {
813
1021
  if (!this.options?.output) throw new Error("Output is required");
814
1022
  return createMutation(this.options.output, {
@@ -818,6 +1026,10 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
818
1026
  }
819
1027
  };
820
1028
  var SubscriptionChainFactory = class _SubscriptionChainFactory extends BaseChainFactory {
1029
+ /**
1030
+ * Returns the available methods for the subscription chain factory
1031
+ * @returns An object containing all available methods
1032
+ */
821
1033
  static methods() {
822
1034
  return {
823
1035
  ...BaseChainFactory.methods(),
@@ -827,15 +1039,39 @@ var SubscriptionChainFactory = class _SubscriptionChainFactory extends BaseChain
827
1039
  clone: _SubscriptionChainFactory.prototype.clone
828
1040
  };
829
1041
  }
1042
+ /**
1043
+ * Creates a clone of the current factory with new options
1044
+ * @param options - New options to apply to the clone
1045
+ * @returns A new instance of SubscriptionChainFactory with the updated options
1046
+ */
830
1047
  clone(options) {
831
1048
  return new _SubscriptionChainFactory({ ...this.options, ...options });
832
1049
  }
1050
+ /**
1051
+ * Sets the output type for the subscription
1052
+ * @template TOutputNew - The new output type
1053
+ * @param output - The output type definition
1054
+ * @returns A new SubscriptionChainFactory instance with the updated output type
1055
+ */
833
1056
  output(output) {
834
1057
  return new _SubscriptionChainFactory({ ...this.options, output });
835
1058
  }
1059
+ /**
1060
+ * Sets the input type for the subscription
1061
+ * @template TInputNew - The new input type
1062
+ * @param input - The input type definition
1063
+ * @returns A new SubscriptionChainFactory instance with the updated input type
1064
+ */
836
1065
  input(input) {
837
1066
  return new _SubscriptionChainFactory({ ...this.options, input });
838
1067
  }
1068
+ /**
1069
+ * Sets the subscribe function for the subscription
1070
+ * @template TValue - The value type of the subscription
1071
+ * @param subscribe - The subscribe function that returns an AsyncIterator
1072
+ * @returns A subscription resolver that can be further configured with a resolve function
1073
+ * @throws {Error} If output type is not set
1074
+ */
839
1075
  subscribe(subscribe) {
840
1076
  const options = this.options;
841
1077
  const output = this.options?.output;
@@ -925,20 +1161,13 @@ var createQuery = (output, resolveOrOptions) => {
925
1161
  return new QueryChainFactory({ output });
926
1162
  }
927
1163
  const options = getOperationOptions(resolveOrOptions);
928
- const operation = "query";
929
1164
  return meta({
930
1165
  ...getFieldOptions(options),
931
1166
  input: options.input,
932
1167
  output,
933
- resolve: (inputValue, extraOptions) => {
934
- const parseInput = createInputParser(options.input, inputValue);
935
- return applyMiddlewares(
936
- compose(extraOptions?.middlewares, options.middlewares),
937
- async () => options.resolve(getStandardValue(await parseInput())),
938
- { parseInput, parent: void 0, outputSilk: output, operation }
939
- );
940
- },
941
- operation
1168
+ resolve: options.resolve,
1169
+ middlewares: options.middlewares,
1170
+ operation: "query"
942
1171
  });
943
1172
  };
944
1173
  var query = Object.assign(
@@ -950,20 +1179,13 @@ var createMutation = (output, resolveOrOptions) => {
950
1179
  return new MutationChainFactory({ output });
951
1180
  }
952
1181
  const options = getOperationOptions(resolveOrOptions);
953
- const operation = "mutation";
954
1182
  return meta({
955
1183
  ...getFieldOptions(options),
956
1184
  input: options.input,
957
1185
  output,
958
- resolve: (inputValue, extraOptions) => {
959
- const parseInput = createInputParser(options.input, inputValue);
960
- return applyMiddlewares(
961
- compose(extraOptions?.middlewares, options.middlewares),
962
- async () => options.resolve(getStandardValue(await parseInput())),
963
- { parseInput, parent: void 0, outputSilk: output, operation }
964
- );
965
- },
966
- operation
1186
+ resolve: options.resolve,
1187
+ middlewares: options.middlewares,
1188
+ operation: "mutation"
967
1189
  });
968
1190
  };
969
1191
  var mutation = Object.assign(
@@ -975,20 +1197,16 @@ var createField = (output, resolveOrOptions) => {
975
1197
  return new FieldChainFactory({ output });
976
1198
  }
977
1199
  const options = getOperationOptions(resolveOrOptions);
978
- const operation = "field";
979
1200
  return meta({
980
- ...getFieldOptions(options),
1201
+ ...getFieldOptions(options, {
1202
+ [DERIVED_DEPENDENCIES]: options.dependencies
1203
+ }),
981
1204
  input: options.input,
1205
+ dependencies: options.dependencies,
982
1206
  output,
983
- resolve: (parent, inputValue, extraOptions) => {
984
- const parseInput = createInputParser(options.input, inputValue);
985
- return applyMiddlewares(
986
- compose(extraOptions?.middlewares, options.middlewares),
987
- async () => options.resolve(parent, getStandardValue(await parseInput())),
988
- { parseInput, parent, outputSilk: output, operation }
989
- );
990
- },
991
- operation
1207
+ resolve: options.resolve,
1208
+ middlewares: options.middlewares,
1209
+ operation: "field"
992
1210
  });
993
1211
  };
994
1212
  var field = Object.assign(
@@ -1002,72 +1220,20 @@ function createSubscription(output, subscribeOrOptions) {
1002
1220
  return new SubscriptionChainFactory({ output });
1003
1221
  }
1004
1222
  const options = getSubscriptionOptions(subscribeOrOptions);
1005
- const operation = "subscription";
1006
1223
  return meta({
1007
1224
  ...getFieldOptions(options),
1008
1225
  input: options.input,
1009
1226
  output,
1010
- subscribe: (inputValue, extraOptions) => {
1011
- const parseInput = createInputParser(options.input, inputValue);
1012
- return applyMiddlewares(
1013
- compose(
1014
- extraOptions?.middlewares,
1015
- options.middlewares
1016
- ),
1017
- async () => options.subscribe(getStandardValue(await parseInput())),
1018
- { parseInput, parent: void 0, outputSilk: output, operation }
1019
- );
1020
- },
1227
+ subscribe: options.subscribe,
1021
1228
  resolve: options.resolve ?? defaultSubscriptionResolve,
1022
- operation
1229
+ middlewares: options.middlewares,
1230
+ operation: "subscription"
1023
1231
  });
1024
1232
  }
1025
1233
  var subscription = Object.assign(
1026
1234
  createSubscription,
1027
1235
  SubscriptionChainFactory.methods()
1028
1236
  );
1029
- function extraOperationOptions(field2, options) {
1030
- if (typeof field2 === "symbol") return field2;
1031
- const composeMiddlewares = (extraOptions) => compose(extraOptions?.middlewares, options?.middlewares);
1032
- switch (field2["~meta"].operation) {
1033
- case "field":
1034
- return {
1035
- ...field2,
1036
- "~meta": {
1037
- ...field2["~meta"],
1038
- resolve: (parent, input, extraOptions) => field2["~meta"].resolve(parent, input, {
1039
- ...extraOptions,
1040
- middlewares: composeMiddlewares(extraOptions)
1041
- })
1042
- }
1043
- };
1044
- case "subscription":
1045
- return {
1046
- ...field2,
1047
- "~meta": {
1048
- ...field2["~meta"],
1049
- subscribe: (input, extraOptions) => field2["~meta"].subscribe(
1050
- input,
1051
- {
1052
- ...extraOptions,
1053
- middlewares: composeMiddlewares(extraOptions)
1054
- }
1055
- )
1056
- }
1057
- };
1058
- default:
1059
- return {
1060
- ...field2,
1061
- "~meta": {
1062
- ...field2["~meta"],
1063
- resolve: (input, extraOptions) => field2["~meta"].resolve(input, {
1064
- ...extraOptions,
1065
- middlewares: composeMiddlewares(extraOptions)
1066
- })
1067
- }
1068
- };
1069
- }
1070
- }
1071
1237
  var resolver = Object.assign(
1072
1238
  (operations, options) => new ChainResolver(operations, options),
1073
1239
  {
@@ -1087,6 +1253,11 @@ var loom = {
1087
1253
  };
1088
1254
  var ChainResolver = class {
1089
1255
  meta;
1256
+ /**
1257
+ * Creates a new chain resolver
1258
+ * @param fields - The fields or operations to resolve
1259
+ * @param options - Optional resolver options
1260
+ */
1090
1261
  constructor(fields, options) {
1091
1262
  this.meta = {
1092
1263
  [IS_RESOLVER]: true,
@@ -1094,38 +1265,83 @@ var ChainResolver = class {
1094
1265
  options
1095
1266
  };
1096
1267
  }
1268
+ /**
1269
+ * Gets the metadata for the resolver
1270
+ */
1097
1271
  get "~meta"() {
1098
- const fields = {};
1099
- Object.entries(this.meta.fields).forEach(([name, field2]) => {
1100
- if (field2 === FIELD_HIDDEN) {
1101
- fields[name] = field2;
1102
- } else {
1103
- fields[name] = extraOperationOptions(field2, this.meta.options);
1104
- }
1105
- });
1106
- return {
1107
- ...this.meta,
1108
- fields
1109
- };
1272
+ return this.meta;
1110
1273
  }
1274
+ /**
1275
+ * Adds middleware functions to the resolver
1276
+ * @param middlewares - The middleware functions to add
1277
+ */
1111
1278
  use(...middlewares) {
1112
1279
  this.meta.options ??= {};
1113
1280
  this.meta.options.middlewares ??= [];
1114
1281
  this.meta.options.middlewares.push(...middlewares);
1115
1282
  return this;
1116
1283
  }
1117
- toExecutor() {
1118
- const fields = this["~meta"].fields;
1119
- const executor = {};
1120
- Object.entries(fields).forEach(([name, field2]) => {
1121
- if (field2 === FIELD_HIDDEN) return;
1122
- executor[name] = field2["~meta"].resolve;
1123
- });
1284
+ toExecutor(...middlewares) {
1285
+ const executor = mapValue(
1286
+ this["~meta"].fields,
1287
+ (field2) => this.toExecutorOperation(field2, middlewares) ?? mapValue.SKIP
1288
+ );
1124
1289
  return executor;
1125
1290
  }
1291
+ toExecutorOperation(field2, executorMiddlewares) {
1292
+ if (field2 === FIELD_HIDDEN || field2["~meta"].operation === "subscription") {
1293
+ return void 0;
1294
+ }
1295
+ const operation = field2["~meta"].operation;
1296
+ const middlewares = filterMiddlewares(
1297
+ operation,
1298
+ executorMiddlewares,
1299
+ this.meta.options?.middlewares,
1300
+ field2["~meta"].middlewares
1301
+ );
1302
+ if (field2["~meta"].operation === "field") {
1303
+ const resolve = field2["~meta"].resolve;
1304
+ return (parent, args, payload) => {
1305
+ const parseInput = createInputParser(field2["~meta"].input, args);
1306
+ return applyMiddlewares(
1307
+ {
1308
+ outputSilk: field2["~meta"].output,
1309
+ parent,
1310
+ payload,
1311
+ parseInput,
1312
+ operation
1313
+ },
1314
+ async () => resolve(parent, await parseInput.getResult(), payload),
1315
+ middlewares
1316
+ );
1317
+ };
1318
+ } else {
1319
+ const resolve = field2["~meta"].resolve;
1320
+ return (args, payload) => {
1321
+ const parseInput = createInputParser(field2["~meta"].input, args);
1322
+ return applyMiddlewares(
1323
+ {
1324
+ outputSilk: field2["~meta"].output,
1325
+ parent: void 0,
1326
+ payload,
1327
+ parseInput,
1328
+ operation
1329
+ },
1330
+ async () => resolve(await parseInput.getResult(), payload),
1331
+ middlewares
1332
+ );
1333
+ };
1334
+ }
1335
+ }
1126
1336
  };
1127
1337
  var ObjectChainResolver = class extends ChainResolver {
1128
1338
  meta;
1339
+ /**
1340
+ * Creates a new object chain resolver
1341
+ * @param parent - The parent type definition
1342
+ * @param fields - The fields to resolve
1343
+ * @param options - Optional resolver options
1344
+ */
1129
1345
  constructor(parent, fields, options) {
1130
1346
  super(fields, options);
1131
1347
  this.meta = {
@@ -1135,9 +1351,16 @@ var ObjectChainResolver = class extends ChainResolver {
1135
1351
  options
1136
1352
  };
1137
1353
  }
1354
+ /**
1355
+ * Gets the metadata for the resolver
1356
+ */
1138
1357
  get "~meta"() {
1139
1358
  return super["~meta"];
1140
1359
  }
1360
+ /**
1361
+ * Sets custom extensions for the resolver
1362
+ * @param extensions - The extensions to add
1363
+ */
1141
1364
  extensions(extensions) {
1142
1365
  this.meta.options ??= {};
1143
1366
  this.meta.options.extensions ??= {};
@@ -1150,27 +1373,16 @@ var ObjectChainResolver = class extends ChainResolver {
1150
1373
  };
1151
1374
 
1152
1375
  // src/schema/object.ts
1153
- var import_graphql5 = require("graphql");
1154
-
1155
- // src/utils/async-iterator.ts
1156
- function bindAsyncIterator(storage, generator) {
1157
- const store = storage.getStore();
1158
- const next = generator.next;
1159
- Object.defineProperty(generator, "next", {
1160
- value: (...args) => storage.run(store, () => next.apply(generator, args)),
1161
- writable: false
1162
- });
1163
- return generator;
1164
- }
1376
+ var import_graphql8 = require("graphql");
1165
1377
 
1166
1378
  // src/schema/input.ts
1167
- var import_graphql4 = require("graphql");
1379
+ var import_graphql7 = require("graphql");
1168
1380
  function inputToArgs(input, options) {
1169
1381
  if (input === void 0) return void 0;
1170
1382
  if (isSilk(input)) {
1171
1383
  let inputType = getGraphQLType(input);
1172
- if ((0, import_graphql4.isNonNullType)(inputType)) inputType = inputType.ofType;
1173
- if ((0, import_graphql4.isObjectType)(inputType)) {
1384
+ if ((0, import_graphql7.isNonNullType)(inputType)) inputType = inputType.ofType;
1385
+ if ((0, import_graphql7.isObjectType)(inputType)) {
1174
1386
  return mapValue(inputType.toConfig().fields, (it, key) => {
1175
1387
  let fieldName;
1176
1388
  if (options?.fieldName) {
@@ -1203,20 +1415,20 @@ function ensureInputType(silkOrType, options) {
1203
1415
  }
1204
1416
  return silkOrType;
1205
1417
  })();
1206
- if ((0, import_graphql4.isUnionType)(gqlType))
1418
+ if ((0, import_graphql7.isUnionType)(gqlType))
1207
1419
  throw new Error(`Cannot convert union type ${gqlType.name} to input type`);
1208
- if ((0, import_graphql4.isNonNullType)(gqlType)) {
1209
- return new import_graphql4.GraphQLNonNull(ensureInputType(gqlType.ofType, options));
1420
+ if ((0, import_graphql7.isNonNullType)(gqlType)) {
1421
+ return new import_graphql7.GraphQLNonNull(ensureInputType(gqlType.ofType, options));
1210
1422
  }
1211
- if ((0, import_graphql4.isListType)(gqlType)) {
1212
- return new import_graphql4.GraphQLList(ensureInputType(gqlType.ofType, options));
1423
+ if ((0, import_graphql7.isListType)(gqlType)) {
1424
+ return new import_graphql7.GraphQLList(ensureInputType(gqlType.ofType, options));
1213
1425
  }
1214
- if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isInterfaceType)(gqlType))
1426
+ if ((0, import_graphql7.isObjectType)(gqlType) || (0, import_graphql7.isInterfaceType)(gqlType))
1215
1427
  return ensureInputObjectType(gqlType, options);
1216
1428
  return gqlType;
1217
1429
  }
1218
1430
  function ensureInputObjectType(object, options) {
1219
- if ((0, import_graphql4.isInputObjectType)(object)) return object;
1431
+ if ((0, import_graphql7.isInputObjectType)(object)) return object;
1220
1432
  const existing = weaverContext.inputMap?.get(object);
1221
1433
  if (existing != null) return existing;
1222
1434
  const { astNode, extensionASTNodes, fields, ...config } = object.toConfig();
@@ -1226,7 +1438,7 @@ function ensureInputObjectType(object, options) {
1226
1438
  }
1227
1439
  const getInputObjectName = weaverContext.getConfig("gqloom.core.schema")?.getInputObjectName ?? ((n) => n);
1228
1440
  name = getInputObjectName(name);
1229
- const input = new import_graphql4.GraphQLInputObjectType({
1441
+ const input = new import_graphql7.GraphQLInputObjectType({
1230
1442
  ...config,
1231
1443
  name,
1232
1444
  fields: provideWeaverContext.inherit(
@@ -1252,16 +1464,20 @@ function inputFieldName(name) {
1252
1464
  }
1253
1465
 
1254
1466
  // src/schema/object.ts
1255
- var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObjectType {
1467
+ var LoomObjectType = class _LoomObjectType extends import_graphql8.GraphQLObjectType {
1256
1468
  extraFields = /* @__PURE__ */ new Map();
1257
1469
  hiddenFields = /* @__PURE__ */ new Set();
1258
1470
  static AUTO_ALIASING = "__gqloom_auto_aliasing";
1259
1471
  weaverContext;
1260
- resolverOptions;
1472
+ globalOptions;
1473
+ /**
1474
+ * field name -> resolver
1475
+ */
1476
+ resolvers;
1261
1477
  constructor(objectOrGetter, options = {}) {
1262
1478
  const origin = typeof objectOrGetter === "function" ? objectOrGetter() : objectOrGetter;
1263
1479
  const config = (() => {
1264
- if ((0, import_graphql5.isObjectType)(origin)) {
1480
+ if ((0, import_graphql8.isObjectType)(origin)) {
1265
1481
  return origin.toConfig();
1266
1482
  } else if (typeof origin === "string") {
1267
1483
  return { name: origin, fields: {} };
@@ -1270,8 +1486,9 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1270
1486
  }
1271
1487
  })();
1272
1488
  super(config);
1273
- this.resolverOptions = options.resolverOptions;
1489
+ this.globalOptions = options.globalOptions;
1274
1490
  this.weaverContext = options.weaverContext ?? initWeaverContext();
1491
+ this.resolvers = /* @__PURE__ */ new Map();
1275
1492
  if (this.name !== _LoomObjectType.AUTO_ALIASING) {
1276
1493
  this.hasExplicitName = true;
1277
1494
  }
@@ -1298,12 +1515,13 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1298
1515
  hideField(name) {
1299
1516
  this.hiddenFields.add(name);
1300
1517
  }
1301
- addField(name, resolver2) {
1518
+ addField(name, field2, resolver2) {
1302
1519
  const existing = this.extraFields.get(name);
1303
- if (existing && existing !== resolver2) {
1520
+ if (existing && existing !== field2) {
1304
1521
  throw new Error(`Field ${name} already exists in ${this.name}`);
1305
1522
  }
1306
- this.extraFields.set(name, resolver2);
1523
+ this.extraFields.set(name, field2);
1524
+ if (resolver2) this.resolvers.set(name, resolver2);
1307
1525
  }
1308
1526
  mergeExtensions(extensions) {
1309
1527
  this.extensions = deepMerge(this.extensions, extensions);
@@ -1338,58 +1556,140 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1338
1556
  return record;
1339
1557
  }
1340
1558
  toFieldConfig(field2, fieldName) {
1341
- try {
1342
- const outputType = this.getCacheType(
1343
- getGraphQLType(field2["~meta"].output),
1344
- fieldName
1345
- );
1346
- return {
1347
- ...extract(field2),
1348
- type: outputType,
1349
- args: inputToArgs(field2["~meta"].input, {
1350
- fieldName: fieldName ? parentName(this.name) + fieldName : void 0
1351
- }),
1352
- ...this.provideForResolve(field2),
1353
- ...this.provideForSubscribe(field2)
1354
- };
1355
- } catch (error) {
1356
- throw markErrorLocation(error);
1357
- }
1358
- }
1359
- provideForResolve(field2) {
1360
- if (field2?.["~meta"]?.resolve == null) return;
1361
- if (field2["~meta"].resolve === defaultSubscriptionResolve)
1362
- return { resolve: defaultSubscriptionResolve };
1363
- const resolve = field2["~meta"].operation === "field" ? (root, args, context, info) => resolverPayloadStorage.run(
1364
- { root, args, context, info, field: field2 },
1365
- () => field2["~meta"].resolve(root, args, this.resolverOptions)
1366
- ) : field2["~meta"].operation === "subscription" ? (root, args, context, info) => resolverPayloadStorage.run(
1367
- { root, args, context, info, field: field2 },
1368
- () => field2["~meta"].resolve(root, args)
1369
- ) : (root, args, context, info) => resolverPayloadStorage.run(
1370
- { root, args, context, info, field: field2 },
1371
- () => field2["~meta"].resolve(args, this.resolverOptions)
1559
+ const outputType = this.getCacheType(
1560
+ getGraphQLType(field2["~meta"].output),
1561
+ fieldName
1372
1562
  );
1373
- return { resolve };
1563
+ const resolve = this.provideForResolve(field2, fieldName);
1564
+ const subscribe = this.provideForSubscribe(field2, fieldName);
1565
+ return {
1566
+ ...extract(field2),
1567
+ type: outputType,
1568
+ args: inputToArgs(field2["~meta"].input, {
1569
+ fieldName: fieldName ? parentName(this.name) + fieldName : void 0
1570
+ }),
1571
+ resolve,
1572
+ ...subscribe ? { subscribe } : {}
1573
+ };
1574
+ }
1575
+ provideForResolve(field2, fieldName) {
1576
+ const resolverMiddlewares = this.resolvers.get(fieldName)?.["~meta"].options?.middlewares;
1577
+ switch (field2["~meta"].operation) {
1578
+ case "query":
1579
+ case "mutation": {
1580
+ const operation = field2["~meta"].operation;
1581
+ const middlewares = filterMiddlewares(
1582
+ operation,
1583
+ this.globalOptions?.middlewares,
1584
+ resolverMiddlewares,
1585
+ field2["~meta"].middlewares
1586
+ );
1587
+ return (root, args, context, info) => {
1588
+ const payload = { root, args, context, info, field: field2 };
1589
+ const parseInput = createInputParser(field2["~meta"].input, args);
1590
+ return applyMiddlewares(
1591
+ {
1592
+ operation,
1593
+ outputSilk: field2["~meta"].output,
1594
+ parent: void 0,
1595
+ parseInput,
1596
+ payload
1597
+ },
1598
+ async () => field2["~meta"].resolve(await parseInput.getResult(), payload),
1599
+ middlewares
1600
+ );
1601
+ };
1602
+ }
1603
+ case "field": {
1604
+ const middlewares = filterMiddlewares(
1605
+ "field",
1606
+ this.globalOptions?.middlewares,
1607
+ resolverMiddlewares,
1608
+ field2["~meta"].middlewares
1609
+ );
1610
+ return (root, args, context, info) => {
1611
+ const payload = { root, args, context, info, field: field2 };
1612
+ const parseInput = createInputParser(field2["~meta"].input, args);
1613
+ return applyMiddlewares(
1614
+ {
1615
+ operation: "field",
1616
+ outputSilk: field2["~meta"].output,
1617
+ parent: root,
1618
+ parseInput,
1619
+ payload
1620
+ },
1621
+ async () => field2["~meta"].resolve(
1622
+ root,
1623
+ await parseInput.getResult(),
1624
+ payload
1625
+ ),
1626
+ middlewares
1627
+ );
1628
+ };
1629
+ }
1630
+ case "subscription": {
1631
+ const middlewares = filterMiddlewares(
1632
+ "subscription.resolve",
1633
+ this.globalOptions?.middlewares,
1634
+ resolverMiddlewares,
1635
+ field2["~meta"].middlewares
1636
+ );
1637
+ return (root, args, context, info) => {
1638
+ const payload = { root, args, context, info, field: field2 };
1639
+ const parseInput = createInputParser(field2["~meta"].input, args);
1640
+ return applyMiddlewares(
1641
+ {
1642
+ operation: "subscription.resolve",
1643
+ outputSilk: field2["~meta"].output,
1644
+ parent: root,
1645
+ parseInput,
1646
+ payload
1647
+ },
1648
+ async () => field2["~meta"].resolve(
1649
+ root,
1650
+ await parseInput.getResult(),
1651
+ payload
1652
+ ),
1653
+ middlewares
1654
+ );
1655
+ };
1656
+ }
1657
+ }
1374
1658
  }
1375
- provideForSubscribe(field2) {
1659
+ provideForSubscribe(field2, fieldName) {
1376
1660
  if (field2?.["~meta"]?.subscribe == null)
1377
1661
  return;
1378
- return {
1379
- subscribe: (root, args, context, info) => resolverPayloadStorage.run(
1380
- { root, args, context, info, field: field2 },
1381
- async () => {
1382
- const generator = await field2["~meta"].subscribe?.(args, this.resolverOptions);
1383
- return bindAsyncIterator(resolverPayloadStorage, generator);
1384
- }
1385
- )
1662
+ const resolverMiddlewares = this.resolvers.get(fieldName)?.["~meta"].options?.middlewares;
1663
+ const middlewares = filterMiddlewares(
1664
+ "subscription.subscribe",
1665
+ this.globalOptions?.middlewares,
1666
+ resolverMiddlewares,
1667
+ field2["~meta"].middlewares
1668
+ );
1669
+ return (source, args, context, info) => {
1670
+ const payload = { root: source, args, context, info, field: field2 };
1671
+ const parseInput = createInputParser(field2["~meta"].input, args);
1672
+ return applyMiddlewares(
1673
+ {
1674
+ operation: "subscription.subscribe",
1675
+ outputSilk: field2["~meta"].output,
1676
+ parent: void 0,
1677
+ parseInput,
1678
+ payload
1679
+ },
1680
+ async () => field2["~meta"].subscribe(
1681
+ await parseInput.getResult(),
1682
+ payload
1683
+ ),
1684
+ middlewares
1685
+ );
1386
1686
  };
1387
1687
  }
1388
1688
  getCacheType(gqlType, fieldName) {
1389
1689
  return getCacheType(gqlType, { ...this.options, fieldName, parent: this });
1390
1690
  }
1391
1691
  get options() {
1392
- const { resolverOptions, weaverContext: weaverContext2 } = this;
1692
+ const { globalOptions: resolverOptions, weaverContext: weaverContext2 } = this;
1393
1693
  return { resolverOptions, weaverContext: weaverContext2 };
1394
1694
  }
1395
1695
  };
@@ -1402,11 +1702,11 @@ function extract(field2) {
1402
1702
  };
1403
1703
  }
1404
1704
  function defineFieldMap(fields) {
1405
- const fieldMap = (0, import_graphql5.resolveObjMapThunk)(fields);
1705
+ const fieldMap = (0, import_graphql8.resolveObjMapThunk)(fields);
1406
1706
  return mapValue(fieldMap, (fieldConfig, fieldName) => {
1407
1707
  const argsConfig = fieldConfig.args ?? {};
1408
1708
  return {
1409
- name: (0, import_graphql5.assertName)(fieldName),
1709
+ name: (0, import_graphql8.assertName)(fieldName),
1410
1710
  description: fieldConfig.description,
1411
1711
  type: fieldConfig.type,
1412
1712
  args: defineArguments(argsConfig),
@@ -1420,7 +1720,7 @@ function defineFieldMap(fields) {
1420
1720
  }
1421
1721
  function defineArguments(args) {
1422
1722
  return Object.entries(args).map(([argName, argConfig]) => ({
1423
- name: (0, import_graphql5.assertName)(argName),
1723
+ name: (0, import_graphql8.assertName)(argName),
1424
1724
  description: argConfig.description,
1425
1725
  type: argConfig.type,
1426
1726
  defaultValue: argConfig.defaultValue,
@@ -1437,7 +1737,7 @@ var OPERATION_OBJECT_NAMES = /* @__PURE__ */ new Set([
1437
1737
  function getCacheType(gqlType, options = {}) {
1438
1738
  const context = options.weaverContext ?? weaverContext;
1439
1739
  if (gqlType instanceof LoomObjectType) return gqlType;
1440
- if ((0, import_graphql5.isObjectType)(gqlType)) {
1740
+ if ((0, import_graphql8.isObjectType)(gqlType)) {
1441
1741
  const gqlObject = context.loomObjectMap?.get(gqlType);
1442
1742
  if (gqlObject != null) return gqlObject;
1443
1743
  const loomObject = new LoomObjectType(gqlType, options);
@@ -1448,15 +1748,15 @@ function getCacheType(gqlType, options = {}) {
1448
1748
  );
1449
1749
  }
1450
1750
  return loomObject;
1451
- } else if ((0, import_graphql5.isListType)(gqlType)) {
1452
- return new import_graphql5.GraphQLList(getCacheType(gqlType.ofType, options));
1453
- } else if ((0, import_graphql5.isNonNullType)(gqlType)) {
1454
- return new import_graphql5.GraphQLNonNull(getCacheType(gqlType.ofType, options));
1455
- } else if ((0, import_graphql5.isUnionType)(gqlType)) {
1751
+ } else if ((0, import_graphql8.isListType)(gqlType)) {
1752
+ return new import_graphql8.GraphQLList(getCacheType(gqlType.ofType, options));
1753
+ } else if ((0, import_graphql8.isNonNullType)(gqlType)) {
1754
+ return new import_graphql8.GraphQLNonNull(getCacheType(gqlType.ofType, options));
1755
+ } else if ((0, import_graphql8.isUnionType)(gqlType)) {
1456
1756
  const existing = context.loomUnionMap?.get(gqlType);
1457
1757
  if (existing != null) return existing;
1458
1758
  const config = gqlType.toConfig();
1459
- const unionType = new import_graphql5.GraphQLUnionType({
1759
+ const unionType = new import_graphql8.GraphQLUnionType({
1460
1760
  ...config,
1461
1761
  types: config.types.map(
1462
1762
  (type) => getCacheType(type, options)
@@ -1483,7 +1783,7 @@ function isSchemaVendorWeaver(some) {
1483
1783
  }
1484
1784
 
1485
1785
  // src/schema/schema-loom.ts
1486
- var import_graphql6 = require("graphql");
1786
+ var import_graphql9 = require("graphql");
1487
1787
  var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1488
1788
  query;
1489
1789
  mutation;
@@ -1515,8 +1815,11 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1515
1815
  this.resolverOptions.middlewares.push(...middlewares);
1516
1816
  return this;
1517
1817
  }
1518
- add(resolver2) {
1519
- provideWeaverContext(() => this.addResolver(resolver2), this.context);
1818
+ add(resolver2, modifyParent) {
1819
+ provideWeaverContext(
1820
+ () => this.addResolver(resolver2, modifyParent),
1821
+ this.context
1822
+ );
1520
1823
  return this;
1521
1824
  }
1522
1825
  addVendor(weaver) {
@@ -1526,14 +1829,14 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1526
1829
  addType(silk2) {
1527
1830
  const gqlType = provideWeaverContext(() => {
1528
1831
  let gqlType2 = getGraphQLType(silk2);
1529
- if ((0, import_graphql6.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1530
- if ((0, import_graphql6.isObjectType)(gqlType2)) {
1832
+ if ((0, import_graphql9.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1833
+ if ((0, import_graphql9.isObjectType)(gqlType2)) {
1531
1834
  const existing = this.context.loomObjectMap.get(gqlType2);
1532
1835
  if (existing != null) return existing;
1533
1836
  const extraObject = new LoomObjectType(gqlType2, this.fieldOptions);
1534
1837
  this.context.loomObjectMap.set(gqlType2, extraObject);
1535
1838
  return extraObject;
1536
- } else if ((0, import_graphql6.isUnionType)(gqlType2) || (0, import_graphql6.isEnumType)(gqlType2)) {
1839
+ } else if ((0, import_graphql9.isUnionType)(gqlType2) || (0, import_graphql9.isEnumType)(gqlType2)) {
1537
1840
  return gqlType2;
1538
1841
  }
1539
1842
  throw new Error(
@@ -1550,7 +1853,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1550
1853
  weaveGraphQLSchema() {
1551
1854
  const { query: query2, mutation: mutation2, subscription: subscription2, types } = this;
1552
1855
  const config = this.context.getConfig("gqloom.core.schema");
1553
- const schema = new import_graphql6.GraphQLSchema({
1856
+ const schema = new import_graphql9.GraphQLSchema({
1554
1857
  query: query2,
1555
1858
  mutation: mutation2,
1556
1859
  subscription: subscription2,
@@ -1559,14 +1862,14 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1559
1862
  });
1560
1863
  return schema;
1561
1864
  }
1562
- addResolver(resolver2) {
1865
+ addResolver(resolver2, modifyParent) {
1563
1866
  const resolverOptions = resolver2["~meta"].options;
1564
1867
  const parent = resolver2["~meta"].parent;
1565
- const parentObject = (() => {
1868
+ let parentObject = (() => {
1566
1869
  if (parent == null) return void 0;
1567
1870
  let gqlType = getGraphQLType(parent);
1568
- if ((0, import_graphql6.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1569
- if (!(0, import_graphql6.isObjectType)(gqlType)) {
1871
+ if ((0, import_graphql9.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1872
+ if (!(0, import_graphql9.isObjectType)(gqlType)) {
1570
1873
  throw new Error(
1571
1874
  `${gqlType?.name ?? gqlType.toString()} is not an object type`
1572
1875
  );
@@ -1580,18 +1883,20 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1580
1883
  })();
1581
1884
  if (resolverOptions?.extensions && parentObject)
1582
1885
  parentObject.mergeExtensions(resolverOptions.extensions);
1886
+ if (modifyParent != null && parentObject)
1887
+ parentObject = modifyParent(parentObject);
1583
1888
  Object.entries(resolver2["~meta"].fields).forEach(([name, field2]) => {
1584
1889
  if (field2 === FIELD_HIDDEN) {
1585
1890
  if (parentObject == null) return;
1586
1891
  parentObject.hideField(name);
1587
1892
  } else if (field2["~meta"].operation === "field") {
1588
1893
  if (parentObject == null) return;
1589
- parentObject.addField(name, field2);
1894
+ parentObject.addField(name, field2, resolver2);
1590
1895
  } else {
1591
1896
  const operationObject = this.getOperationObject(
1592
1897
  field2["~meta"].operation
1593
1898
  );
1594
- operationObject.addField(name, field2);
1899
+ operationObject.addField(name, field2, resolver2);
1595
1900
  }
1596
1901
  });
1597
1902
  return this;
@@ -1623,7 +1928,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1623
1928
  }
1624
1929
  get fieldOptions() {
1625
1930
  const { resolverOptions, context } = this;
1626
- return { resolverOptions, weaverContext: context };
1931
+ return { globalOptions: resolverOptions, weaverContext: context };
1627
1932
  }
1628
1933
  static optionsFrom(...inputs) {
1629
1934
  const configs = /* @__PURE__ */ new Set();
@@ -1633,6 +1938,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1633
1938
  const weavers = /* @__PURE__ */ new Set();
1634
1939
  let context;
1635
1940
  for (const item of inputs) {
1941
+ if (item == null) continue;
1636
1942
  if (isSchemaVendorWeaver(item)) {
1637
1943
  weavers.add(item);
1638
1944
  } else if (typeof item === "function") {
@@ -1670,10 +1976,10 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1670
1976
  var weave = GraphQLSchemaLoom.weave;
1671
1977
 
1672
1978
  // src/schema/interface.ts
1673
- var import_graphql7 = require("graphql");
1979
+ var import_graphql10 = require("graphql");
1674
1980
  function ensureInterfaceType(gqlType, interfaceConfig) {
1675
- if ((0, import_graphql7.isInterfaceType)(gqlType)) return gqlType;
1676
- if (!(0, import_graphql7.isObjectType)(gqlType))
1981
+ if ((0, import_graphql10.isInterfaceType)(gqlType)) return gqlType;
1982
+ if (!(0, import_graphql10.isObjectType)(gqlType))
1677
1983
  throw new Error(`${gqlType.toString()} is not an object`);
1678
1984
  const key = gqlType;
1679
1985
  const existing = weaverContext.interfaceMap?.get(key);
@@ -1684,7 +1990,7 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1684
1990
  fields,
1685
1991
  ...config
1686
1992
  } = gqlType.toConfig();
1687
- const interfaceType = new import_graphql7.GraphQLInterfaceType({
1993
+ const interfaceType = new import_graphql10.GraphQLInterfaceType({
1688
1994
  ...config,
1689
1995
  ...interfaceConfig,
1690
1996
  fields: mapValue(fields, (field2) => {
@@ -1698,7 +2004,6 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1698
2004
  0 && (module.exports = {
1699
2005
  BaseChainFactory,
1700
2006
  ChainResolver,
1701
- ContextMemoization,
1702
2007
  EasyDataLoader,
1703
2008
  FieldChainFactory,
1704
2009
  FieldFactoryWithResolve,
@@ -1713,13 +2018,12 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1713
2018
  SYMBOLS,
1714
2019
  SubscriptionChainFactory,
1715
2020
  applyMiddlewares,
2021
+ assignContextMap,
1716
2022
  capitalize,
1717
2023
  collectName,
1718
2024
  collectNames,
1719
- compose,
1720
2025
  createField,
1721
2026
  createInputParser,
1722
- createMemoization,
1723
2027
  createMutation,
1724
2028
  createQuery,
1725
2029
  createSubscription,
@@ -1729,10 +2033,13 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1729
2033
  ensureInputType,
1730
2034
  ensureInterfaceType,
1731
2035
  field,
2036
+ filterMiddlewares,
1732
2037
  getCacheType,
1733
2038
  getFieldOptions,
1734
2039
  getGraphQLType,
2040
+ getMemoizationMap,
1735
2041
  getOperationOptions,
2042
+ getResolvingFields,
1736
2043
  getStandardValue,
1737
2044
  getSubscriptionOptions,
1738
2045
  initWeaverContext,
@@ -1752,20 +2059,17 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1752
2059
  nullableSilk,
1753
2060
  onlyMemoization,
1754
2061
  parseInputValue,
2062
+ parseResolvingFields,
1755
2063
  parseSilk,
1756
2064
  pascalCase,
1757
2065
  provideWeaverContext,
1758
2066
  query,
1759
2067
  resolver,
1760
- resolverPayloadStorage,
1761
2068
  screamingSnakeCase,
1762
2069
  silk,
1763
2070
  subscription,
1764
2071
  toObjMap,
1765
2072
  tryIn,
1766
- useContext,
1767
- useMemoizationMap,
1768
- useResolverPayload,
1769
2073
  weave,
1770
2074
  weaverContext
1771
2075
  });