@gqloom/core 0.8.4 → 0.9.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/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,20 @@ 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];
242
- }
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
- });
150
+ function ensureArray(value) {
151
+ return Array.isArray(value) ? value : [value];
254
152
  }
255
153
 
256
154
  // src/utils/object.ts
@@ -306,6 +204,167 @@ function meta(data) {
306
204
  return { "~meta": data };
307
205
  }
308
206
 
207
+ // src/utils/parse-resolving-fields.ts
208
+ var import_graphql3 = require("graphql");
209
+
210
+ // src/utils/constants.ts
211
+ var DERIVED_DEPENDENCIES = "loom.derived-from-dependencies";
212
+
213
+ // src/utils/type.ts
214
+ var import_graphql = require("graphql");
215
+ var import_graphql2 = require("graphql");
216
+ function unwrapType(gqlType) {
217
+ if ((0, import_graphql2.isNonNullType)(gqlType)) {
218
+ return unwrapType(gqlType.ofType);
219
+ }
220
+ if ((0, import_graphql.isListType)(gqlType)) {
221
+ return unwrapType(gqlType.ofType);
222
+ }
223
+ return gqlType;
224
+ }
225
+
226
+ // src/utils/parse-resolving-fields.ts
227
+ function getResolvingFields(payload) {
228
+ const requestedFields = parseResolvingFields(payload.info);
229
+ const derivedFields = /* @__PURE__ */ new Set();
230
+ const derivedDependencies = /* @__PURE__ */ new Set();
231
+ const resolvingObject = unwrapType(payload.info.returnType);
232
+ if ((0, import_graphql3.isObjectType)(resolvingObject)) {
233
+ const objectFields = resolvingObject.getFields();
234
+ for (const requestedFieldName of requestedFields) {
235
+ const field2 = objectFields[requestedFieldName];
236
+ if (field2) {
237
+ const deps = field2.extensions?.[DERIVED_DEPENDENCIES];
238
+ if (deps && Array.isArray(deps) && deps.length > 0) {
239
+ derivedFields.add(requestedFieldName);
240
+ for (const d of deps) derivedDependencies.add(d);
241
+ }
242
+ }
243
+ }
244
+ }
245
+ const selectedFields = new Set(requestedFields);
246
+ for (const f of derivedFields) selectedFields.delete(f);
247
+ for (const d of derivedDependencies) selectedFields.add(d);
248
+ return { requestedFields, derivedFields, derivedDependencies, selectedFields };
249
+ }
250
+ function parseResolvingFields(info, maxDepth = 1) {
251
+ return new ResolvingFieldsParser(info, maxDepth).parse();
252
+ }
253
+ var ResolvingFieldsParser = class {
254
+ /** Store unique field paths */
255
+ fields = /* @__PURE__ */ new Set();
256
+ /** Track visited fragments to prevent circular references */
257
+ visitedFragments = /* @__PURE__ */ new Set();
258
+ /** The GraphQL resolve info object */
259
+ info;
260
+ /** Maximum depth of nested fields to parse */
261
+ maxDepth;
262
+ constructor(info, maxDepth) {
263
+ this.info = info;
264
+ this.maxDepth = maxDepth;
265
+ }
266
+ /**
267
+ * Parses the GraphQL resolve info to extract all requested fields.
268
+ * @returns A Set of field paths
269
+ */
270
+ parse() {
271
+ for (const fieldNode of this.info.fieldNodes) {
272
+ this.collectFields(fieldNode.selectionSet);
273
+ }
274
+ return this.fields;
275
+ }
276
+ /**
277
+ * Recursively collects fields from a selection set.
278
+ * Handles fields, inline fragments, and fragment spreads.
279
+ *
280
+ * @param selectionSet - The selection set to process
281
+ * @param parentPath - The path of the parent field (for nested fields)
282
+ * @param currentDepth - Current depth of recursion
283
+ */
284
+ collectFields(selectionSet, parentPath = "", currentDepth = 0) {
285
+ if (!selectionSet?.selections.length || currentDepth >= this.maxDepth)
286
+ return;
287
+ for (const selection of selectionSet.selections) {
288
+ if (!this.shouldIncludeNode(selection)) continue;
289
+ switch (selection.kind) {
290
+ case import_graphql3.Kind.FIELD: {
291
+ const fieldName = selection.name.value;
292
+ const fieldPath = parentPath ? `${parentPath}.${fieldName}` : fieldName;
293
+ this.fields.add(fieldPath);
294
+ const hasSelectionSet = selection.selectionSet != null;
295
+ if (hasSelectionSet) {
296
+ this.collectFields(
297
+ selection.selectionSet,
298
+ fieldPath,
299
+ currentDepth + 1
300
+ );
301
+ }
302
+ break;
303
+ }
304
+ case import_graphql3.Kind.INLINE_FRAGMENT: {
305
+ if (selection.selectionSet) {
306
+ this.collectFields(selection.selectionSet, parentPath, currentDepth);
307
+ }
308
+ break;
309
+ }
310
+ case import_graphql3.Kind.FRAGMENT_SPREAD: {
311
+ const fragmentName = selection.name.value;
312
+ if (this.visitedFragments.has(fragmentName)) continue;
313
+ this.visitedFragments.add(fragmentName);
314
+ const fragment = this.info.fragments[fragmentName];
315
+ if (fragment) {
316
+ this.collectFields(fragment.selectionSet, parentPath, currentDepth);
317
+ }
318
+ break;
319
+ }
320
+ }
321
+ }
322
+ }
323
+ /**
324
+ * Extracts the boolean value from a directive's 'if' argument.
325
+ * Handles both literal boolean values and variables.
326
+ *
327
+ * @param directive - The directive node to extract value from
328
+ * @returns The boolean value of the directive's condition
329
+ */
330
+ getDirectiveValue(directive) {
331
+ const ifArg = directive.arguments?.find(
332
+ (arg) => arg.name.value === "if"
333
+ );
334
+ if (!ifArg) return true;
335
+ const value = ifArg.value;
336
+ if (value.kind === import_graphql3.Kind.BOOLEAN) {
337
+ return value.value;
338
+ }
339
+ if (value.kind === import_graphql3.Kind.VARIABLE) {
340
+ const variableName = value.name.value;
341
+ const variableValue = this.info.variableValues?.[variableName];
342
+ return variableValue === true;
343
+ }
344
+ return true;
345
+ }
346
+ /**
347
+ * Determines if a selection node should be included based on its directives.
348
+ * Handles both @include and @skip directives.
349
+ *
350
+ * @param node - The selection node to check
351
+ * @returns Whether the node should be included
352
+ */
353
+ shouldIncludeNode(node) {
354
+ if (!node.directives?.length) return true;
355
+ return node.directives.every((directive) => {
356
+ const isIncludeDirective = directive.name.value === "include";
357
+ if (isIncludeDirective) {
358
+ return this.getDirectiveValue(directive);
359
+ }
360
+ if (directive.name.value === "skip") {
361
+ return !this.getDirectiveValue(directive);
362
+ }
363
+ return true;
364
+ });
365
+ }
366
+ };
367
+
309
368
  // src/utils/string.ts
310
369
  function pascalCase(str) {
311
370
  return str.split(/[\s-_]+/).map(
@@ -413,11 +472,47 @@ var EasyDataLoader = class _EasyDataLoader {
413
472
  }
414
473
  };
415
474
 
475
+ // src/utils/symbols.ts
476
+ var symbols_exports = {};
477
+ __export(symbols_exports, {
478
+ CONTEXT_MAP_KEY: () => CONTEXT_MAP_KEY,
479
+ FIELD_HIDDEN: () => FIELD_HIDDEN,
480
+ GET_GRAPHQL_TYPE: () => GET_GRAPHQL_TYPE,
481
+ IS_RESOLVER: () => IS_RESOLVER,
482
+ RESOLVER_OPTIONS_KEY: () => RESOLVER_OPTIONS_KEY,
483
+ WEAVER_CONFIG: () => WEAVER_CONFIG
484
+ });
485
+ var GET_GRAPHQL_TYPE = Symbol.for("gqloom.get_graphql_type");
486
+ var WEAVER_CONFIG = Symbol.for("gqloom.weaver_config");
487
+ var RESOLVER_OPTIONS_KEY = Symbol.for("gqloom.resolver-options");
488
+ var IS_RESOLVER = Symbol.for("gqloom.is-resolver");
489
+ var CONTEXT_MAP_KEY = Symbol.for("gqloom.context-map");
490
+ var FIELD_HIDDEN = Symbol.for("gqloom.field-hidden");
491
+
492
+ // src/utils/context.ts
493
+ function onlyMemoization() {
494
+ return { memoization: /* @__PURE__ */ new WeakMap(), isMemoization: true };
495
+ }
496
+ function isOnlyMemoryPayload(payload) {
497
+ return payload.isMemoization === true;
498
+ }
499
+ function getMemoizationMap(payload) {
500
+ if (isOnlyMemoryPayload(payload)) return payload.memoization;
501
+ if (typeof payload.context === "undefined") {
502
+ Object.defineProperty(payload, "context", { value: {} });
503
+ }
504
+ return assignContextMap(payload.context);
505
+ }
506
+ function assignContextMap(target) {
507
+ target[CONTEXT_MAP_KEY] ??= /* @__PURE__ */ new WeakMap();
508
+ return target[CONTEXT_MAP_KEY];
509
+ }
510
+
416
511
  // src/resolver/silk.ts
417
- var import_graphql2 = require("graphql");
512
+ var import_graphql5 = require("graphql");
418
513
 
419
514
  // src/schema/weaver-context.ts
420
- var import_graphql = require("graphql");
515
+ var import_graphql4 = require("graphql");
421
516
  var ref;
422
517
  var names = /* @__PURE__ */ new WeakMap();
423
518
  function initWeaverContext() {
@@ -442,7 +537,7 @@ function initWeaverContext() {
442
537
  namedTypes: /* @__PURE__ */ new Map(),
443
538
  memoNamedType(gqlTypeValue) {
444
539
  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)) {
540
+ if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isUnionType)(gqlType) || (0, import_graphql4.isEnumType)(gqlType) || (0, import_graphql4.isScalarType)(gqlType)) {
446
541
  this.namedTypes.set(gqlType.name, gqlType);
447
542
  }
448
543
  return gqlTypeValue;
@@ -562,10 +657,10 @@ function nonNullSilk(origin) {
562
657
  ...origin,
563
658
  [GET_GRAPHQL_TYPE]: () => {
564
659
  const originType = getGraphQLType(origin);
565
- if (originType instanceof import_graphql2.GraphQLNonNull) {
660
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
566
661
  return originType;
567
662
  } else {
568
- return new import_graphql2.GraphQLNonNull(originType);
663
+ return new import_graphql5.GraphQLNonNull(originType);
569
664
  }
570
665
  }
571
666
  };
@@ -575,13 +670,13 @@ function listSilk(origin) {
575
670
  ...origin,
576
671
  [GET_GRAPHQL_TYPE]: () => {
577
672
  let originType = getGraphQLType(origin);
578
- if (originType instanceof import_graphql2.GraphQLNonNull && originType.ofType instanceof import_graphql2.GraphQLList) {
673
+ if (originType instanceof import_graphql5.GraphQLNonNull && originType.ofType instanceof import_graphql5.GraphQLList) {
579
674
  originType = originType.ofType.ofType;
580
675
  }
581
- if (originType instanceof import_graphql2.GraphQLList) {
676
+ if (originType instanceof import_graphql5.GraphQLList) {
582
677
  originType = originType.ofType;
583
678
  }
584
- return new import_graphql2.GraphQLNonNull(new import_graphql2.GraphQLList(originType));
679
+ return new import_graphql5.GraphQLNonNull(new import_graphql5.GraphQLList(originType));
585
680
  }
586
681
  };
587
682
  }
@@ -590,7 +685,7 @@ function nullableSilk(origin) {
590
685
  ...origin,
591
686
  [GET_GRAPHQL_TYPE]: () => {
592
687
  const originType = getGraphQLType(origin);
593
- if (originType instanceof import_graphql2.GraphQLNonNull) {
688
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
594
689
  return originType.ofType;
595
690
  } else {
596
691
  return originType;
@@ -622,7 +717,7 @@ function isSilk(target) {
622
717
  }
623
718
 
624
719
  // src/resolver/input.ts
625
- var import_graphql3 = require("graphql");
720
+ var import_graphql6 = require("graphql");
626
721
  function createInputParser(schema, value) {
627
722
  let result;
628
723
  const parse = async () => {
@@ -669,19 +764,26 @@ function getStandardValue(result) {
669
764
  if (result == null) return result;
670
765
  const { issues } = result;
671
766
  if (issues?.length) {
672
- throw new import_graphql3.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
767
+ throw new import_graphql6.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
673
768
  extensions: { issues }
674
769
  });
675
770
  }
676
771
  if ("value" in result) return result.value;
677
- else throw new import_graphql3.GraphQLError("Invalid input");
772
+ else throw new import_graphql6.GraphQLError("Invalid input");
678
773
  }
679
774
 
680
775
  // src/resolver/resolver-chain-factory.ts
681
776
  var BaseChainFactory = class _BaseChainFactory {
777
+ /**
778
+ * Creates a new instance of the chain factory
779
+ * @param options - Configuration options for the factory
780
+ */
682
781
  constructor(options) {
683
782
  this.options = options;
684
783
  }
784
+ /**
785
+ * Returns the available methods for the chain factory
786
+ */
685
787
  static methods() {
686
788
  return {
687
789
  description: _BaseChainFactory.prototype.description,
@@ -689,15 +791,31 @@ var BaseChainFactory = class _BaseChainFactory {
689
791
  extensions: _BaseChainFactory.prototype.extensions
690
792
  };
691
793
  }
794
+ /**
795
+ * Sets the description for the field
796
+ * @param description - The description text
797
+ */
692
798
  description(description) {
693
799
  return this.clone({ description });
694
800
  }
801
+ /**
802
+ * Sets the deprecation reason for the field
803
+ * @param deprecationReason - The reason for deprecation
804
+ */
695
805
  deprecationReason(deprecationReason) {
696
806
  return this.clone({ deprecationReason });
697
807
  }
808
+ /**
809
+ * Sets custom extensions for the field
810
+ * @param extensions - Custom extensions to add
811
+ */
698
812
  extensions(extensions) {
699
813
  return this.clone({ extensions });
700
814
  }
815
+ /**
816
+ * Adds middleware functions to the field
817
+ * @param middlewares - Middleware functions to add
818
+ */
701
819
  use(...middlewares) {
702
820
  return this.clone({
703
821
  middlewares: [...this.options?.middlewares ?? [], ...middlewares]
@@ -705,6 +823,9 @@ var BaseChainFactory = class _BaseChainFactory {
705
823
  }
706
824
  };
707
825
  var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
826
+ /**
827
+ * Returns the available methods for the field chain factory
828
+ */
708
829
  static methods() {
709
830
  return {
710
831
  ...BaseChainFactory.methods(),
@@ -714,15 +835,42 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
714
835
  clone: _FieldChainFactory.prototype.clone
715
836
  };
716
837
  }
838
+ /**
839
+ * Creates a clone of the current factory with new options
840
+ * @param options - New options to apply to the clone
841
+ */
717
842
  clone(options) {
718
843
  return new _FieldChainFactory({ ...this.options, ...options });
719
844
  }
845
+ /**
846
+ * Sets the output type for the field
847
+ * @template TOutputNew - The new output type
848
+ * @param output - The output type definition
849
+ */
720
850
  output(output) {
721
851
  return new _FieldChainFactory({ ...this.options, output });
722
852
  }
853
+ /**
854
+ * Sets the input type for the field
855
+ * @template TInputNew - The new input type
856
+ * @param input - The input type definition
857
+ */
723
858
  input(input) {
724
859
  return new _FieldChainFactory({ ...this.options, input });
725
860
  }
861
+ /**
862
+ * Specifies the dependencies for the field
863
+ * @template TDependencies - The dependencies type
864
+ * @param dependencies - The dependencies to add
865
+ */
866
+ derivedFrom(...dependencies) {
867
+ return this.clone({ dependencies });
868
+ }
869
+ /**
870
+ * Sets the resolve function for the field
871
+ * @template TParent - The parent type
872
+ * @param resolve - The resolve function
873
+ */
726
874
  resolve(resolve) {
727
875
  if (!this.options?.output) throw new Error("Output is required");
728
876
  return createField(this.options.output, {
@@ -730,40 +878,47 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
730
878
  resolve
731
879
  });
732
880
  }
881
+ /**
882
+ * Creates a field resolver that uses DataLoader for batch loading data.
883
+ * This method is particularly useful for optimizing performance when dealing with multiple data requests
884
+ * by batching them together and handling caching automatically.
885
+ *
886
+ * @template TParent - The parent type that extends GraphQLSilk
887
+ * @param resolve - A function that handles batch loading of data. The function receives:
888
+ * - When no input type is defined: An array of parent objects
889
+ * - When input type is defined: An array of tuples containing [parent, input]
890
+ * - An array of resolver payloads
891
+ * @returns A GraphQL field resolver that implements batch loading
892
+ */
733
893
  load(resolve) {
734
894
  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
- );
895
+ const hasInput = typeof this.options.input !== "undefined";
896
+ const initLoader = () => new EasyDataLoader((args) => {
897
+ const parents = args.map(
898
+ ([parent, input]) => hasInput ? [parent, input] : parent
899
+ );
900
+ const payloads = args.map(([, , payload]) => payload);
901
+ return resolve(parents, payloads);
902
+ });
903
+ return createField(this.options.output, {
904
+ ...this.options,
905
+ resolve: (parent, input, payload) => {
906
+ const loader = (() => {
907
+ if (!payload) return initLoader();
908
+ const memoMap = getMemoizationMap(payload);
909
+ if (!memoMap.has(resolve)) memoMap.set(resolve, initLoader());
910
+ return memoMap.get(resolve);
911
+ })();
912
+ return loader.load([parent, input, payload]);
762
913
  }
763
914
  });
764
915
  }
765
916
  };
766
917
  var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
918
+ /**
919
+ * Returns the available methods for the query chain factory
920
+ * @returns An object containing all available methods
921
+ */
767
922
  static methods() {
768
923
  return {
769
924
  ...BaseChainFactory.methods(),
@@ -773,15 +928,38 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
773
928
  clone: _QueryChainFactory.prototype.clone
774
929
  };
775
930
  }
931
+ /**
932
+ * Creates a clone of the current factory with new options
933
+ * @param options - New options to apply to the clone
934
+ * @returns A new instance of QueryChainFactory with the updated options
935
+ */
776
936
  clone(options) {
777
937
  return new _QueryChainFactory({ ...this.options, ...options });
778
938
  }
939
+ /**
940
+ * Sets the output type for the query
941
+ * @template TOutputNew - The new output type
942
+ * @param output - The output type definition
943
+ * @returns A new QueryChainFactory instance with the updated output type
944
+ */
779
945
  output(output) {
780
946
  return new _QueryChainFactory({ ...this.options, output });
781
947
  }
948
+ /**
949
+ * Sets the input type for the query
950
+ * @template TInputNew - The new input type
951
+ * @param input - The input type definition
952
+ * @returns A new QueryChainFactory instance with the updated input type
953
+ */
782
954
  input(input) {
783
955
  return new _QueryChainFactory({ ...this.options, input });
784
956
  }
957
+ /**
958
+ * Sets the resolve function for the query
959
+ * @param resolve - The resolve function that processes the input and returns the output
960
+ * @returns A GraphQL query resolver
961
+ * @throws {Error} If output type is not set
962
+ */
785
963
  resolve(resolve) {
786
964
  if (!this.options?.output) throw new Error("Output is required");
787
965
  return createQuery(this.options.output, {
@@ -791,6 +969,10 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
791
969
  }
792
970
  };
793
971
  var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory {
972
+ /**
973
+ * Returns the available methods for the mutation chain factory
974
+ * @returns An object containing all available methods
975
+ */
794
976
  static methods() {
795
977
  return {
796
978
  ...BaseChainFactory.methods(),
@@ -800,15 +982,38 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
800
982
  clone: _MutationChainFactory.prototype.clone
801
983
  };
802
984
  }
985
+ /**
986
+ * Creates a clone of the current factory with new options
987
+ * @param options - New options to apply to the clone
988
+ * @returns A new instance of MutationChainFactory with the updated options
989
+ */
803
990
  clone(options) {
804
991
  return new _MutationChainFactory({ ...this.options, ...options });
805
992
  }
993
+ /**
994
+ * Sets the output type for the mutation
995
+ * @template TOutputNew - The new output type
996
+ * @param output - The output type definition
997
+ * @returns A new MutationChainFactory instance with the updated output type
998
+ */
806
999
  output(output) {
807
1000
  return new _MutationChainFactory({ ...this.options, output });
808
1001
  }
1002
+ /**
1003
+ * Sets the input type for the mutation
1004
+ * @template TInputNew - The new input type
1005
+ * @param input - The input type definition
1006
+ * @returns A new MutationChainFactory instance with the updated input type
1007
+ */
809
1008
  input(input) {
810
1009
  return new _MutationChainFactory({ ...this.options, input });
811
1010
  }
1011
+ /**
1012
+ * Sets the resolve function for the mutation
1013
+ * @param resolve - The resolve function that processes the input and returns the output
1014
+ * @returns A GraphQL mutation resolver
1015
+ * @throws {Error} If output type is not set
1016
+ */
812
1017
  resolve(resolve) {
813
1018
  if (!this.options?.output) throw new Error("Output is required");
814
1019
  return createMutation(this.options.output, {
@@ -818,6 +1023,10 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
818
1023
  }
819
1024
  };
820
1025
  var SubscriptionChainFactory = class _SubscriptionChainFactory extends BaseChainFactory {
1026
+ /**
1027
+ * Returns the available methods for the subscription chain factory
1028
+ * @returns An object containing all available methods
1029
+ */
821
1030
  static methods() {
822
1031
  return {
823
1032
  ...BaseChainFactory.methods(),
@@ -827,15 +1036,39 @@ var SubscriptionChainFactory = class _SubscriptionChainFactory extends BaseChain
827
1036
  clone: _SubscriptionChainFactory.prototype.clone
828
1037
  };
829
1038
  }
1039
+ /**
1040
+ * Creates a clone of the current factory with new options
1041
+ * @param options - New options to apply to the clone
1042
+ * @returns A new instance of SubscriptionChainFactory with the updated options
1043
+ */
830
1044
  clone(options) {
831
1045
  return new _SubscriptionChainFactory({ ...this.options, ...options });
832
1046
  }
1047
+ /**
1048
+ * Sets the output type for the subscription
1049
+ * @template TOutputNew - The new output type
1050
+ * @param output - The output type definition
1051
+ * @returns A new SubscriptionChainFactory instance with the updated output type
1052
+ */
833
1053
  output(output) {
834
1054
  return new _SubscriptionChainFactory({ ...this.options, output });
835
1055
  }
1056
+ /**
1057
+ * Sets the input type for the subscription
1058
+ * @template TInputNew - The new input type
1059
+ * @param input - The input type definition
1060
+ * @returns A new SubscriptionChainFactory instance with the updated input type
1061
+ */
836
1062
  input(input) {
837
1063
  return new _SubscriptionChainFactory({ ...this.options, input });
838
1064
  }
1065
+ /**
1066
+ * Sets the subscribe function for the subscription
1067
+ * @template TValue - The value type of the subscription
1068
+ * @param subscribe - The subscribe function that returns an AsyncIterator
1069
+ * @returns A subscription resolver that can be further configured with a resolve function
1070
+ * @throws {Error} If output type is not set
1071
+ */
839
1072
  subscribe(subscribe) {
840
1073
  const options = this.options;
841
1074
  const output = this.options?.output;
@@ -925,20 +1158,13 @@ var createQuery = (output, resolveOrOptions) => {
925
1158
  return new QueryChainFactory({ output });
926
1159
  }
927
1160
  const options = getOperationOptions(resolveOrOptions);
928
- const operation = "query";
929
1161
  return meta({
930
1162
  ...getFieldOptions(options),
931
1163
  input: options.input,
932
1164
  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
1165
+ resolve: options.resolve,
1166
+ middlewares: options.middlewares,
1167
+ operation: "query"
942
1168
  });
943
1169
  };
944
1170
  var query = Object.assign(
@@ -950,20 +1176,13 @@ var createMutation = (output, resolveOrOptions) => {
950
1176
  return new MutationChainFactory({ output });
951
1177
  }
952
1178
  const options = getOperationOptions(resolveOrOptions);
953
- const operation = "mutation";
954
1179
  return meta({
955
1180
  ...getFieldOptions(options),
956
1181
  input: options.input,
957
1182
  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
1183
+ resolve: options.resolve,
1184
+ middlewares: options.middlewares,
1185
+ operation: "mutation"
967
1186
  });
968
1187
  };
969
1188
  var mutation = Object.assign(
@@ -975,20 +1194,16 @@ var createField = (output, resolveOrOptions) => {
975
1194
  return new FieldChainFactory({ output });
976
1195
  }
977
1196
  const options = getOperationOptions(resolveOrOptions);
978
- const operation = "field";
979
1197
  return meta({
980
- ...getFieldOptions(options),
1198
+ ...getFieldOptions(options, {
1199
+ [DERIVED_DEPENDENCIES]: options.dependencies
1200
+ }),
981
1201
  input: options.input,
1202
+ dependencies: options.dependencies,
982
1203
  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
1204
+ resolve: options.resolve,
1205
+ middlewares: options.middlewares,
1206
+ operation: "field"
992
1207
  });
993
1208
  };
994
1209
  var field = Object.assign(
@@ -1002,72 +1217,20 @@ function createSubscription(output, subscribeOrOptions) {
1002
1217
  return new SubscriptionChainFactory({ output });
1003
1218
  }
1004
1219
  const options = getSubscriptionOptions(subscribeOrOptions);
1005
- const operation = "subscription";
1006
1220
  return meta({
1007
1221
  ...getFieldOptions(options),
1008
1222
  input: options.input,
1009
1223
  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
- },
1224
+ subscribe: options.subscribe,
1021
1225
  resolve: options.resolve ?? defaultSubscriptionResolve,
1022
- operation
1226
+ middlewares: options.middlewares,
1227
+ operation: "subscription"
1023
1228
  });
1024
1229
  }
1025
1230
  var subscription = Object.assign(
1026
1231
  createSubscription,
1027
1232
  SubscriptionChainFactory.methods()
1028
1233
  );
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
1234
  var resolver = Object.assign(
1072
1235
  (operations, options) => new ChainResolver(operations, options),
1073
1236
  {
@@ -1087,6 +1250,11 @@ var loom = {
1087
1250
  };
1088
1251
  var ChainResolver = class {
1089
1252
  meta;
1253
+ /**
1254
+ * Creates a new chain resolver
1255
+ * @param fields - The fields or operations to resolve
1256
+ * @param options - Optional resolver options
1257
+ */
1090
1258
  constructor(fields, options) {
1091
1259
  this.meta = {
1092
1260
  [IS_RESOLVER]: true,
@@ -1094,38 +1262,83 @@ var ChainResolver = class {
1094
1262
  options
1095
1263
  };
1096
1264
  }
1265
+ /**
1266
+ * Gets the metadata for the resolver
1267
+ */
1097
1268
  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
- };
1269
+ return this.meta;
1110
1270
  }
1271
+ /**
1272
+ * Adds middleware functions to the resolver
1273
+ * @param middlewares - The middleware functions to add
1274
+ */
1111
1275
  use(...middlewares) {
1112
1276
  this.meta.options ??= {};
1113
1277
  this.meta.options.middlewares ??= [];
1114
1278
  this.meta.options.middlewares.push(...middlewares);
1115
1279
  return this;
1116
1280
  }
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
- });
1281
+ toExecutor(...middlewares) {
1282
+ const executor = mapValue(
1283
+ this["~meta"].fields,
1284
+ (field2) => this.toExecutorOperation(field2, middlewares) ?? mapValue.SKIP
1285
+ );
1124
1286
  return executor;
1125
1287
  }
1288
+ toExecutorOperation(field2, executorMiddlewares) {
1289
+ if (field2 === FIELD_HIDDEN || field2["~meta"].operation === "subscription") {
1290
+ return void 0;
1291
+ }
1292
+ const operation = field2["~meta"].operation;
1293
+ const middlewares = filterMiddlewares(
1294
+ operation,
1295
+ executorMiddlewares,
1296
+ this.meta.options?.middlewares,
1297
+ field2["~meta"].middlewares
1298
+ );
1299
+ if (field2["~meta"].operation === "field") {
1300
+ const resolve = field2["~meta"].resolve;
1301
+ return (parent, args, payload) => {
1302
+ const parseInput = createInputParser(field2["~meta"].input, args);
1303
+ return applyMiddlewares(
1304
+ {
1305
+ outputSilk: field2["~meta"].output,
1306
+ parent,
1307
+ payload,
1308
+ parseInput,
1309
+ operation
1310
+ },
1311
+ async () => resolve(parent, await parseInput.getResult(), payload),
1312
+ middlewares
1313
+ );
1314
+ };
1315
+ } else {
1316
+ const resolve = field2["~meta"].resolve;
1317
+ return (args, payload) => {
1318
+ const parseInput = createInputParser(field2["~meta"].input, args);
1319
+ return applyMiddlewares(
1320
+ {
1321
+ outputSilk: field2["~meta"].output,
1322
+ parent: void 0,
1323
+ payload,
1324
+ parseInput,
1325
+ operation
1326
+ },
1327
+ async () => resolve(await parseInput.getResult(), payload),
1328
+ middlewares
1329
+ );
1330
+ };
1331
+ }
1332
+ }
1126
1333
  };
1127
1334
  var ObjectChainResolver = class extends ChainResolver {
1128
1335
  meta;
1336
+ /**
1337
+ * Creates a new object chain resolver
1338
+ * @param parent - The parent type definition
1339
+ * @param fields - The fields to resolve
1340
+ * @param options - Optional resolver options
1341
+ */
1129
1342
  constructor(parent, fields, options) {
1130
1343
  super(fields, options);
1131
1344
  this.meta = {
@@ -1135,9 +1348,16 @@ var ObjectChainResolver = class extends ChainResolver {
1135
1348
  options
1136
1349
  };
1137
1350
  }
1351
+ /**
1352
+ * Gets the metadata for the resolver
1353
+ */
1138
1354
  get "~meta"() {
1139
1355
  return super["~meta"];
1140
1356
  }
1357
+ /**
1358
+ * Sets custom extensions for the resolver
1359
+ * @param extensions - The extensions to add
1360
+ */
1141
1361
  extensions(extensions) {
1142
1362
  this.meta.options ??= {};
1143
1363
  this.meta.options.extensions ??= {};
@@ -1150,27 +1370,16 @@ var ObjectChainResolver = class extends ChainResolver {
1150
1370
  };
1151
1371
 
1152
1372
  // 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
- }
1373
+ var import_graphql8 = require("graphql");
1165
1374
 
1166
1375
  // src/schema/input.ts
1167
- var import_graphql4 = require("graphql");
1376
+ var import_graphql7 = require("graphql");
1168
1377
  function inputToArgs(input, options) {
1169
1378
  if (input === void 0) return void 0;
1170
1379
  if (isSilk(input)) {
1171
1380
  let inputType = getGraphQLType(input);
1172
- if ((0, import_graphql4.isNonNullType)(inputType)) inputType = inputType.ofType;
1173
- if ((0, import_graphql4.isObjectType)(inputType)) {
1381
+ if ((0, import_graphql7.isNonNullType)(inputType)) inputType = inputType.ofType;
1382
+ if ((0, import_graphql7.isObjectType)(inputType)) {
1174
1383
  return mapValue(inputType.toConfig().fields, (it, key) => {
1175
1384
  let fieldName;
1176
1385
  if (options?.fieldName) {
@@ -1203,20 +1412,20 @@ function ensureInputType(silkOrType, options) {
1203
1412
  }
1204
1413
  return silkOrType;
1205
1414
  })();
1206
- if ((0, import_graphql4.isUnionType)(gqlType))
1415
+ if ((0, import_graphql7.isUnionType)(gqlType))
1207
1416
  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));
1417
+ if ((0, import_graphql7.isNonNullType)(gqlType)) {
1418
+ return new import_graphql7.GraphQLNonNull(ensureInputType(gqlType.ofType, options));
1210
1419
  }
1211
- if ((0, import_graphql4.isListType)(gqlType)) {
1212
- return new import_graphql4.GraphQLList(ensureInputType(gqlType.ofType, options));
1420
+ if ((0, import_graphql7.isListType)(gqlType)) {
1421
+ return new import_graphql7.GraphQLList(ensureInputType(gqlType.ofType, options));
1213
1422
  }
1214
- if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isInterfaceType)(gqlType))
1423
+ if ((0, import_graphql7.isObjectType)(gqlType) || (0, import_graphql7.isInterfaceType)(gqlType))
1215
1424
  return ensureInputObjectType(gqlType, options);
1216
1425
  return gqlType;
1217
1426
  }
1218
1427
  function ensureInputObjectType(object, options) {
1219
- if ((0, import_graphql4.isInputObjectType)(object)) return object;
1428
+ if ((0, import_graphql7.isInputObjectType)(object)) return object;
1220
1429
  const existing = weaverContext.inputMap?.get(object);
1221
1430
  if (existing != null) return existing;
1222
1431
  const { astNode, extensionASTNodes, fields, ...config } = object.toConfig();
@@ -1226,7 +1435,7 @@ function ensureInputObjectType(object, options) {
1226
1435
  }
1227
1436
  const getInputObjectName = weaverContext.getConfig("gqloom.core.schema")?.getInputObjectName ?? ((n) => n);
1228
1437
  name = getInputObjectName(name);
1229
- const input = new import_graphql4.GraphQLInputObjectType({
1438
+ const input = new import_graphql7.GraphQLInputObjectType({
1230
1439
  ...config,
1231
1440
  name,
1232
1441
  fields: provideWeaverContext.inherit(
@@ -1252,16 +1461,20 @@ function inputFieldName(name) {
1252
1461
  }
1253
1462
 
1254
1463
  // src/schema/object.ts
1255
- var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObjectType {
1464
+ var LoomObjectType = class _LoomObjectType extends import_graphql8.GraphQLObjectType {
1256
1465
  extraFields = /* @__PURE__ */ new Map();
1257
1466
  hiddenFields = /* @__PURE__ */ new Set();
1258
1467
  static AUTO_ALIASING = "__gqloom_auto_aliasing";
1259
1468
  weaverContext;
1260
- resolverOptions;
1469
+ globalOptions;
1470
+ /**
1471
+ * field name -> resolver
1472
+ */
1473
+ resolvers;
1261
1474
  constructor(objectOrGetter, options = {}) {
1262
1475
  const origin = typeof objectOrGetter === "function" ? objectOrGetter() : objectOrGetter;
1263
1476
  const config = (() => {
1264
- if ((0, import_graphql5.isObjectType)(origin)) {
1477
+ if ((0, import_graphql8.isObjectType)(origin)) {
1265
1478
  return origin.toConfig();
1266
1479
  } else if (typeof origin === "string") {
1267
1480
  return { name: origin, fields: {} };
@@ -1270,8 +1483,9 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1270
1483
  }
1271
1484
  })();
1272
1485
  super(config);
1273
- this.resolverOptions = options.resolverOptions;
1486
+ this.globalOptions = options.globalOptions;
1274
1487
  this.weaverContext = options.weaverContext ?? initWeaverContext();
1488
+ this.resolvers = /* @__PURE__ */ new Map();
1275
1489
  if (this.name !== _LoomObjectType.AUTO_ALIASING) {
1276
1490
  this.hasExplicitName = true;
1277
1491
  }
@@ -1298,12 +1512,13 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1298
1512
  hideField(name) {
1299
1513
  this.hiddenFields.add(name);
1300
1514
  }
1301
- addField(name, resolver2) {
1515
+ addField(name, field2, resolver2) {
1302
1516
  const existing = this.extraFields.get(name);
1303
- if (existing && existing !== resolver2) {
1517
+ if (existing && existing !== field2) {
1304
1518
  throw new Error(`Field ${name} already exists in ${this.name}`);
1305
1519
  }
1306
- this.extraFields.set(name, resolver2);
1520
+ this.extraFields.set(name, field2);
1521
+ if (resolver2) this.resolvers.set(name, resolver2);
1307
1522
  }
1308
1523
  mergeExtensions(extensions) {
1309
1524
  this.extensions = deepMerge(this.extensions, extensions);
@@ -1338,58 +1553,140 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1338
1553
  return record;
1339
1554
  }
1340
1555
  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)
1556
+ const outputType = this.getCacheType(
1557
+ getGraphQLType(field2["~meta"].output),
1558
+ fieldName
1372
1559
  );
1373
- return { resolve };
1560
+ const resolve = this.provideForResolve(field2, fieldName);
1561
+ const subscribe = this.provideForSubscribe(field2, fieldName);
1562
+ return {
1563
+ ...extract(field2),
1564
+ type: outputType,
1565
+ args: inputToArgs(field2["~meta"].input, {
1566
+ fieldName: fieldName ? parentName(this.name) + fieldName : void 0
1567
+ }),
1568
+ resolve,
1569
+ ...subscribe ? { subscribe } : {}
1570
+ };
1571
+ }
1572
+ provideForResolve(field2, fieldName) {
1573
+ const resolverMiddlewares = this.resolvers.get(fieldName)?.["~meta"].options?.middlewares;
1574
+ switch (field2["~meta"].operation) {
1575
+ case "query":
1576
+ case "mutation": {
1577
+ const operation = field2["~meta"].operation;
1578
+ const middlewares = filterMiddlewares(
1579
+ operation,
1580
+ this.globalOptions?.middlewares,
1581
+ resolverMiddlewares,
1582
+ field2["~meta"].middlewares
1583
+ );
1584
+ return (root, args, context, info) => {
1585
+ const payload = { root, args, context, info, field: field2 };
1586
+ const parseInput = createInputParser(field2["~meta"].input, args);
1587
+ return applyMiddlewares(
1588
+ {
1589
+ operation,
1590
+ outputSilk: field2["~meta"].output,
1591
+ parent: void 0,
1592
+ parseInput,
1593
+ payload
1594
+ },
1595
+ async () => field2["~meta"].resolve(await parseInput.getResult(), payload),
1596
+ middlewares
1597
+ );
1598
+ };
1599
+ }
1600
+ case "field": {
1601
+ const middlewares = filterMiddlewares(
1602
+ "field",
1603
+ this.globalOptions?.middlewares,
1604
+ resolverMiddlewares,
1605
+ field2["~meta"].middlewares
1606
+ );
1607
+ return (root, args, context, info) => {
1608
+ const payload = { root, args, context, info, field: field2 };
1609
+ const parseInput = createInputParser(field2["~meta"].input, args);
1610
+ return applyMiddlewares(
1611
+ {
1612
+ operation: "field",
1613
+ outputSilk: field2["~meta"].output,
1614
+ parent: root,
1615
+ parseInput,
1616
+ payload
1617
+ },
1618
+ async () => field2["~meta"].resolve(
1619
+ root,
1620
+ await parseInput.getResult(),
1621
+ payload
1622
+ ),
1623
+ middlewares
1624
+ );
1625
+ };
1626
+ }
1627
+ case "subscription": {
1628
+ const middlewares = filterMiddlewares(
1629
+ "subscription.resolve",
1630
+ this.globalOptions?.middlewares,
1631
+ resolverMiddlewares,
1632
+ field2["~meta"].middlewares
1633
+ );
1634
+ return (root, args, context, info) => {
1635
+ const payload = { root, args, context, info, field: field2 };
1636
+ const parseInput = createInputParser(field2["~meta"].input, args);
1637
+ return applyMiddlewares(
1638
+ {
1639
+ operation: "subscription.resolve",
1640
+ outputSilk: field2["~meta"].output,
1641
+ parent: root,
1642
+ parseInput,
1643
+ payload
1644
+ },
1645
+ async () => field2["~meta"].resolve(
1646
+ root,
1647
+ await parseInput.getResult(),
1648
+ payload
1649
+ ),
1650
+ middlewares
1651
+ );
1652
+ };
1653
+ }
1654
+ }
1374
1655
  }
1375
- provideForSubscribe(field2) {
1656
+ provideForSubscribe(field2, fieldName) {
1376
1657
  if (field2?.["~meta"]?.subscribe == null)
1377
1658
  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
- )
1659
+ const resolverMiddlewares = this.resolvers.get(fieldName)?.["~meta"].options?.middlewares;
1660
+ const middlewares = filterMiddlewares(
1661
+ "subscription.subscribe",
1662
+ this.globalOptions?.middlewares,
1663
+ resolverMiddlewares,
1664
+ field2["~meta"].middlewares
1665
+ );
1666
+ return (source, args, context, info) => {
1667
+ const payload = { root: source, args, context, info, field: field2 };
1668
+ const parseInput = createInputParser(field2["~meta"].input, args);
1669
+ return applyMiddlewares(
1670
+ {
1671
+ operation: "subscription.subscribe",
1672
+ outputSilk: field2["~meta"].output,
1673
+ parent: void 0,
1674
+ parseInput,
1675
+ payload
1676
+ },
1677
+ async () => field2["~meta"].subscribe(
1678
+ await parseInput.getResult(),
1679
+ payload
1680
+ ),
1681
+ middlewares
1682
+ );
1386
1683
  };
1387
1684
  }
1388
1685
  getCacheType(gqlType, fieldName) {
1389
1686
  return getCacheType(gqlType, { ...this.options, fieldName, parent: this });
1390
1687
  }
1391
1688
  get options() {
1392
- const { resolverOptions, weaverContext: weaverContext2 } = this;
1689
+ const { globalOptions: resolverOptions, weaverContext: weaverContext2 } = this;
1393
1690
  return { resolverOptions, weaverContext: weaverContext2 };
1394
1691
  }
1395
1692
  };
@@ -1402,11 +1699,11 @@ function extract(field2) {
1402
1699
  };
1403
1700
  }
1404
1701
  function defineFieldMap(fields) {
1405
- const fieldMap = (0, import_graphql5.resolveObjMapThunk)(fields);
1702
+ const fieldMap = (0, import_graphql8.resolveObjMapThunk)(fields);
1406
1703
  return mapValue(fieldMap, (fieldConfig, fieldName) => {
1407
1704
  const argsConfig = fieldConfig.args ?? {};
1408
1705
  return {
1409
- name: (0, import_graphql5.assertName)(fieldName),
1706
+ name: (0, import_graphql8.assertName)(fieldName),
1410
1707
  description: fieldConfig.description,
1411
1708
  type: fieldConfig.type,
1412
1709
  args: defineArguments(argsConfig),
@@ -1420,7 +1717,7 @@ function defineFieldMap(fields) {
1420
1717
  }
1421
1718
  function defineArguments(args) {
1422
1719
  return Object.entries(args).map(([argName, argConfig]) => ({
1423
- name: (0, import_graphql5.assertName)(argName),
1720
+ name: (0, import_graphql8.assertName)(argName),
1424
1721
  description: argConfig.description,
1425
1722
  type: argConfig.type,
1426
1723
  defaultValue: argConfig.defaultValue,
@@ -1437,7 +1734,7 @@ var OPERATION_OBJECT_NAMES = /* @__PURE__ */ new Set([
1437
1734
  function getCacheType(gqlType, options = {}) {
1438
1735
  const context = options.weaverContext ?? weaverContext;
1439
1736
  if (gqlType instanceof LoomObjectType) return gqlType;
1440
- if ((0, import_graphql5.isObjectType)(gqlType)) {
1737
+ if ((0, import_graphql8.isObjectType)(gqlType)) {
1441
1738
  const gqlObject = context.loomObjectMap?.get(gqlType);
1442
1739
  if (gqlObject != null) return gqlObject;
1443
1740
  const loomObject = new LoomObjectType(gqlType, options);
@@ -1448,15 +1745,15 @@ function getCacheType(gqlType, options = {}) {
1448
1745
  );
1449
1746
  }
1450
1747
  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)) {
1748
+ } else if ((0, import_graphql8.isListType)(gqlType)) {
1749
+ return new import_graphql8.GraphQLList(getCacheType(gqlType.ofType, options));
1750
+ } else if ((0, import_graphql8.isNonNullType)(gqlType)) {
1751
+ return new import_graphql8.GraphQLNonNull(getCacheType(gqlType.ofType, options));
1752
+ } else if ((0, import_graphql8.isUnionType)(gqlType)) {
1456
1753
  const existing = context.loomUnionMap?.get(gqlType);
1457
1754
  if (existing != null) return existing;
1458
1755
  const config = gqlType.toConfig();
1459
- const unionType = new import_graphql5.GraphQLUnionType({
1756
+ const unionType = new import_graphql8.GraphQLUnionType({
1460
1757
  ...config,
1461
1758
  types: config.types.map(
1462
1759
  (type) => getCacheType(type, options)
@@ -1483,7 +1780,7 @@ function isSchemaVendorWeaver(some) {
1483
1780
  }
1484
1781
 
1485
1782
  // src/schema/schema-loom.ts
1486
- var import_graphql6 = require("graphql");
1783
+ var import_graphql9 = require("graphql");
1487
1784
  var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1488
1785
  query;
1489
1786
  mutation;
@@ -1526,14 +1823,14 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1526
1823
  addType(silk2) {
1527
1824
  const gqlType = provideWeaverContext(() => {
1528
1825
  let gqlType2 = getGraphQLType(silk2);
1529
- if ((0, import_graphql6.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1530
- if ((0, import_graphql6.isObjectType)(gqlType2)) {
1826
+ if ((0, import_graphql9.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1827
+ if ((0, import_graphql9.isObjectType)(gqlType2)) {
1531
1828
  const existing = this.context.loomObjectMap.get(gqlType2);
1532
1829
  if (existing != null) return existing;
1533
1830
  const extraObject = new LoomObjectType(gqlType2, this.fieldOptions);
1534
1831
  this.context.loomObjectMap.set(gqlType2, extraObject);
1535
1832
  return extraObject;
1536
- } else if ((0, import_graphql6.isUnionType)(gqlType2) || (0, import_graphql6.isEnumType)(gqlType2)) {
1833
+ } else if ((0, import_graphql9.isUnionType)(gqlType2) || (0, import_graphql9.isEnumType)(gqlType2)) {
1537
1834
  return gqlType2;
1538
1835
  }
1539
1836
  throw new Error(
@@ -1550,7 +1847,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1550
1847
  weaveGraphQLSchema() {
1551
1848
  const { query: query2, mutation: mutation2, subscription: subscription2, types } = this;
1552
1849
  const config = this.context.getConfig("gqloom.core.schema");
1553
- const schema = new import_graphql6.GraphQLSchema({
1850
+ const schema = new import_graphql9.GraphQLSchema({
1554
1851
  query: query2,
1555
1852
  mutation: mutation2,
1556
1853
  subscription: subscription2,
@@ -1565,8 +1862,8 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1565
1862
  const parentObject = (() => {
1566
1863
  if (parent == null) return void 0;
1567
1864
  let gqlType = getGraphQLType(parent);
1568
- if ((0, import_graphql6.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1569
- if (!(0, import_graphql6.isObjectType)(gqlType)) {
1865
+ if ((0, import_graphql9.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1866
+ if (!(0, import_graphql9.isObjectType)(gqlType)) {
1570
1867
  throw new Error(
1571
1868
  `${gqlType?.name ?? gqlType.toString()} is not an object type`
1572
1869
  );
@@ -1586,12 +1883,12 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1586
1883
  parentObject.hideField(name);
1587
1884
  } else if (field2["~meta"].operation === "field") {
1588
1885
  if (parentObject == null) return;
1589
- parentObject.addField(name, field2);
1886
+ parentObject.addField(name, field2, resolver2);
1590
1887
  } else {
1591
1888
  const operationObject = this.getOperationObject(
1592
1889
  field2["~meta"].operation
1593
1890
  );
1594
- operationObject.addField(name, field2);
1891
+ operationObject.addField(name, field2, resolver2);
1595
1892
  }
1596
1893
  });
1597
1894
  return this;
@@ -1623,7 +1920,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1623
1920
  }
1624
1921
  get fieldOptions() {
1625
1922
  const { resolverOptions, context } = this;
1626
- return { resolverOptions, weaverContext: context };
1923
+ return { globalOptions: resolverOptions, weaverContext: context };
1627
1924
  }
1628
1925
  static optionsFrom(...inputs) {
1629
1926
  const configs = /* @__PURE__ */ new Set();
@@ -1633,6 +1930,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1633
1930
  const weavers = /* @__PURE__ */ new Set();
1634
1931
  let context;
1635
1932
  for (const item of inputs) {
1933
+ if (item == null) continue;
1636
1934
  if (isSchemaVendorWeaver(item)) {
1637
1935
  weavers.add(item);
1638
1936
  } else if (typeof item === "function") {
@@ -1670,10 +1968,10 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1670
1968
  var weave = GraphQLSchemaLoom.weave;
1671
1969
 
1672
1970
  // src/schema/interface.ts
1673
- var import_graphql7 = require("graphql");
1971
+ var import_graphql10 = require("graphql");
1674
1972
  function ensureInterfaceType(gqlType, interfaceConfig) {
1675
- if ((0, import_graphql7.isInterfaceType)(gqlType)) return gqlType;
1676
- if (!(0, import_graphql7.isObjectType)(gqlType))
1973
+ if ((0, import_graphql10.isInterfaceType)(gqlType)) return gqlType;
1974
+ if (!(0, import_graphql10.isObjectType)(gqlType))
1677
1975
  throw new Error(`${gqlType.toString()} is not an object`);
1678
1976
  const key = gqlType;
1679
1977
  const existing = weaverContext.interfaceMap?.get(key);
@@ -1684,7 +1982,7 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1684
1982
  fields,
1685
1983
  ...config
1686
1984
  } = gqlType.toConfig();
1687
- const interfaceType = new import_graphql7.GraphQLInterfaceType({
1985
+ const interfaceType = new import_graphql10.GraphQLInterfaceType({
1688
1986
  ...config,
1689
1987
  ...interfaceConfig,
1690
1988
  fields: mapValue(fields, (field2) => {
@@ -1698,7 +1996,6 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1698
1996
  0 && (module.exports = {
1699
1997
  BaseChainFactory,
1700
1998
  ChainResolver,
1701
- ContextMemoization,
1702
1999
  EasyDataLoader,
1703
2000
  FieldChainFactory,
1704
2001
  FieldFactoryWithResolve,
@@ -1713,13 +2010,12 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1713
2010
  SYMBOLS,
1714
2011
  SubscriptionChainFactory,
1715
2012
  applyMiddlewares,
2013
+ assignContextMap,
1716
2014
  capitalize,
1717
2015
  collectName,
1718
2016
  collectNames,
1719
- compose,
1720
2017
  createField,
1721
2018
  createInputParser,
1722
- createMemoization,
1723
2019
  createMutation,
1724
2020
  createQuery,
1725
2021
  createSubscription,
@@ -1729,10 +2025,13 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1729
2025
  ensureInputType,
1730
2026
  ensureInterfaceType,
1731
2027
  field,
2028
+ filterMiddlewares,
1732
2029
  getCacheType,
1733
2030
  getFieldOptions,
1734
2031
  getGraphQLType,
2032
+ getMemoizationMap,
1735
2033
  getOperationOptions,
2034
+ getResolvingFields,
1736
2035
  getStandardValue,
1737
2036
  getSubscriptionOptions,
1738
2037
  initWeaverContext,
@@ -1752,20 +2051,17 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1752
2051
  nullableSilk,
1753
2052
  onlyMemoization,
1754
2053
  parseInputValue,
2054
+ parseResolvingFields,
1755
2055
  parseSilk,
1756
2056
  pascalCase,
1757
2057
  provideWeaverContext,
1758
2058
  query,
1759
2059
  resolver,
1760
- resolverPayloadStorage,
1761
2060
  screamingSnakeCase,
1762
2061
  silk,
1763
2062
  subscription,
1764
2063
  toObjMap,
1765
2064
  tryIn,
1766
- useContext,
1767
- useMemoizationMap,
1768
- useResolverPayload,
1769
2065
  weave,
1770
2066
  weaverContext
1771
2067
  });