@gqloom/core 0.8.3 → 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,19 +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,
86
+ screamingSnakeCase: () => screamingSnakeCase,
85
87
  silk: () => silk,
86
88
  subscription: () => subscription,
87
89
  toObjMap: () => toObjMap,
88
90
  tryIn: () => tryIn,
89
- useContext: () => useContext,
90
- useMemoizationMap: () => useMemoizationMap,
91
- useResolverPayload: () => useResolverPayload,
92
91
  weave: () => weave,
93
92
  weaverContext: () => weaverContext
94
93
  });
@@ -107,20 +106,22 @@ function getSubscriptionOptions(subscribeOrOptions) {
107
106
  }
108
107
  return subscribeOrOptions;
109
108
  }
110
- function getFieldOptions({
111
- description,
112
- deprecationReason,
113
- extensions
114
- }) {
109
+ function getFieldOptions({ description, deprecationReason, extensions }, extraExtensions) {
115
110
  return {
116
111
  description,
117
112
  deprecationReason,
118
- extensions
113
+ extensions: extraExtensions ? { ...extensions, ...extraExtensions } : extensions
119
114
  };
120
115
  }
121
116
 
122
117
  // src/utils/middleware.ts
123
- function applyMiddlewares(middlewares, resolveFunction, options) {
118
+ var defaultOperations = [
119
+ "field",
120
+ "mutation",
121
+ "query",
122
+ "subscription.subscribe"
123
+ ];
124
+ function applyMiddlewares(options, resolveFunction, middlewares) {
124
125
  const next = (index) => {
125
126
  if (index >= middlewares.length) {
126
127
  return resolveFunction();
@@ -134,122 +135,20 @@ function applyMiddlewares(middlewares, resolveFunction, options) {
134
135
  };
135
136
  return next(0);
136
137
  }
137
- function compose(...lists) {
138
- const list = [];
139
- for (const item of lists) {
140
- if (item != null) {
141
- list.push(...item);
142
- }
143
- }
144
- return list;
145
- }
146
-
147
- // src/utils/context.ts
148
- var import_async_hooks = require("async_hooks");
149
-
150
- // src/utils/symbols.ts
151
- var symbols_exports = {};
152
- __export(symbols_exports, {
153
- CONTEXT_MEMORY_MAP_KEY: () => CONTEXT_MEMORY_MAP_KEY,
154
- FIELD_HIDDEN: () => FIELD_HIDDEN,
155
- GET_GRAPHQL_TYPE: () => GET_GRAPHQL_TYPE,
156
- IS_RESOLVER: () => IS_RESOLVER,
157
- RESOLVER_OPTIONS_KEY: () => RESOLVER_OPTIONS_KEY,
158
- WEAVER_CONFIG: () => WEAVER_CONFIG
159
- });
160
- var GET_GRAPHQL_TYPE = Symbol.for("gqloom.get_graphql_type");
161
- var WEAVER_CONFIG = Symbol.for("gqloom.weaver_config");
162
- var RESOLVER_OPTIONS_KEY = Symbol.for("gqloom.resolver-options");
163
- var IS_RESOLVER = Symbol.for("gqloom.is-resolver");
164
- var CONTEXT_MEMORY_MAP_KEY = Symbol.for("gqloom.context-memory");
165
- var FIELD_HIDDEN = Symbol.for("gqloom.field-hidden");
166
-
167
- // src/utils/context.ts
168
- function onlyMemoization() {
169
- return { memoization: /* @__PURE__ */ new WeakMap(), isMemoization: true };
170
- }
171
- function isOnlyMemoryPayload(payload) {
172
- return payload.isMemoization === true;
173
- }
174
- var resolverPayloadStorage = new import_async_hooks.AsyncLocalStorage();
175
- function useResolverPayload() {
176
- const payload = resolverPayloadStorage.getStore();
177
- if (payload === void 0 || isOnlyMemoryPayload(payload)) return;
178
- return payload;
179
- }
180
- function useContext() {
181
- return useResolverPayload()?.context;
182
- }
183
- function useMemoizationMap() {
184
- const payload = resolverPayloadStorage.getStore();
185
- if (payload == null) return;
186
- if (isOnlyMemoryPayload(payload)) return payload.memoization;
187
- 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
+ }, []);
188
149
  }
189
- var ContextMemoization = class {
190
- constructor(getter, options = {}) {
191
- this.getter = getter;
192
- this.getter = getter;
193
- this.getMemoizationMap = options.getMemoizationMap ?? useMemoizationMap;
194
- this.key = options.key ?? this.getter;
195
- }
196
- getMemoizationMap;
197
- key;
198
- /**
199
- * Get the value in memoization or call the getter function
200
- * @returns the value of the getter function
201
- */
202
- get() {
203
- const map = this.getMemoizationMap();
204
- if (!map) return this.getter();
205
- if (!map.has(this.key)) {
206
- map.set(this.key, this.getter());
207
- }
208
- return map.get(this.key);
209
- }
210
- /**
211
- * Clear the memoization
212
- * @returns true if the memoization is cleared, undefined if the context is not found
213
- */
214
- clear() {
215
- const map = this.getMemoizationMap();
216
- if (!map) return;
217
- return map.delete(this.key);
218
- }
219
- /**
220
- * Check if the memoization exists
221
- * @returns true if the memoization exists, undefined if the context is not found
222
- */
223
- exists() {
224
- const map = this.getMemoizationMap();
225
- if (!map) return;
226
- return map.has(this.key);
227
- }
228
- /**
229
- * Set a new value to the memoization
230
- * @param value the new value to set
231
- * @returns the memoization map or undefined if the context is not found
232
- */
233
- set(value) {
234
- const map = this.getMemoizationMap();
235
- if (!map) return;
236
- return map.set(this.key, value);
237
- }
238
- static assignMemoizationMap(target) {
239
- target[CONTEXT_MEMORY_MAP_KEY] ??= /* @__PURE__ */ new WeakMap();
240
- return target[CONTEXT_MEMORY_MAP_KEY];
241
- }
242
- };
243
- function createMemoization(...args) {
244
- const memoization = new ContextMemoization(...args);
245
- const callable = () => memoization.get();
246
- return Object.assign(callable, {
247
- get: () => memoization.get(),
248
- set: (value) => memoization.set(value),
249
- clear: () => memoization.clear(),
250
- exists: () => memoization.exists(),
251
- getter: memoization.getter
252
- });
150
+ function ensureArray(value) {
151
+ return Array.isArray(value) ? value : [value];
253
152
  }
254
153
 
255
154
  // src/utils/object.ts
@@ -305,6 +204,167 @@ function meta(data) {
305
204
  return { "~meta": data };
306
205
  }
307
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
+
308
368
  // src/utils/string.ts
309
369
  function pascalCase(str) {
310
370
  return str.split(/[\s-_]+/).map(
@@ -314,6 +374,9 @@ function pascalCase(str) {
314
374
  function capitalize(str) {
315
375
  return str.slice(0, 1).toUpperCase() + str.slice(1);
316
376
  }
377
+ function screamingSnakeCase(str) {
378
+ return str.replace(/([a-z])([A-Z])/g, "$1_$2").split(/[\s-_]+/).map((word) => word.toUpperCase()).join("_");
379
+ }
317
380
 
318
381
  // src/utils/error.ts
319
382
  function markErrorLocation(error, ...locations) {
@@ -409,11 +472,47 @@ var EasyDataLoader = class _EasyDataLoader {
409
472
  }
410
473
  };
411
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
+
412
511
  // src/resolver/silk.ts
413
- var import_graphql2 = require("graphql");
512
+ var import_graphql5 = require("graphql");
414
513
 
415
514
  // src/schema/weaver-context.ts
416
- var import_graphql = require("graphql");
515
+ var import_graphql4 = require("graphql");
417
516
  var ref;
418
517
  var names = /* @__PURE__ */ new WeakMap();
419
518
  function initWeaverContext() {
@@ -438,7 +537,7 @@ function initWeaverContext() {
438
537
  namedTypes: /* @__PURE__ */ new Map(),
439
538
  memoNamedType(gqlTypeValue) {
440
539
  const gqlType = gqlTypeValue;
441
- 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)) {
442
541
  this.namedTypes.set(gqlType.name, gqlType);
443
542
  }
444
543
  return gqlTypeValue;
@@ -558,10 +657,10 @@ function nonNullSilk(origin) {
558
657
  ...origin,
559
658
  [GET_GRAPHQL_TYPE]: () => {
560
659
  const originType = getGraphQLType(origin);
561
- if (originType instanceof import_graphql2.GraphQLNonNull) {
660
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
562
661
  return originType;
563
662
  } else {
564
- return new import_graphql2.GraphQLNonNull(originType);
663
+ return new import_graphql5.GraphQLNonNull(originType);
565
664
  }
566
665
  }
567
666
  };
@@ -571,13 +670,13 @@ function listSilk(origin) {
571
670
  ...origin,
572
671
  [GET_GRAPHQL_TYPE]: () => {
573
672
  let originType = getGraphQLType(origin);
574
- 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) {
575
674
  originType = originType.ofType.ofType;
576
675
  }
577
- if (originType instanceof import_graphql2.GraphQLList) {
676
+ if (originType instanceof import_graphql5.GraphQLList) {
578
677
  originType = originType.ofType;
579
678
  }
580
- return new import_graphql2.GraphQLNonNull(new import_graphql2.GraphQLList(originType));
679
+ return new import_graphql5.GraphQLNonNull(new import_graphql5.GraphQLList(originType));
581
680
  }
582
681
  };
583
682
  }
@@ -586,7 +685,7 @@ function nullableSilk(origin) {
586
685
  ...origin,
587
686
  [GET_GRAPHQL_TYPE]: () => {
588
687
  const originType = getGraphQLType(origin);
589
- if (originType instanceof import_graphql2.GraphQLNonNull) {
688
+ if (originType instanceof import_graphql5.GraphQLNonNull) {
590
689
  return originType.ofType;
591
690
  } else {
592
691
  return originType;
@@ -618,7 +717,7 @@ function isSilk(target) {
618
717
  }
619
718
 
620
719
  // src/resolver/input.ts
621
- var import_graphql3 = require("graphql");
720
+ var import_graphql6 = require("graphql");
622
721
  function createInputParser(schema, value) {
623
722
  let result;
624
723
  const parse = async () => {
@@ -665,19 +764,26 @@ function getStandardValue(result) {
665
764
  if (result == null) return result;
666
765
  const { issues } = result;
667
766
  if (issues?.length) {
668
- throw new import_graphql3.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
767
+ throw new import_graphql6.GraphQLError(issues?.[0]?.message ?? "Invalid input", {
669
768
  extensions: { issues }
670
769
  });
671
770
  }
672
771
  if ("value" in result) return result.value;
673
- else throw new import_graphql3.GraphQLError("Invalid input");
772
+ else throw new import_graphql6.GraphQLError("Invalid input");
674
773
  }
675
774
 
676
775
  // src/resolver/resolver-chain-factory.ts
677
776
  var BaseChainFactory = class _BaseChainFactory {
777
+ /**
778
+ * Creates a new instance of the chain factory
779
+ * @param options - Configuration options for the factory
780
+ */
678
781
  constructor(options) {
679
782
  this.options = options;
680
783
  }
784
+ /**
785
+ * Returns the available methods for the chain factory
786
+ */
681
787
  static methods() {
682
788
  return {
683
789
  description: _BaseChainFactory.prototype.description,
@@ -685,15 +791,31 @@ var BaseChainFactory = class _BaseChainFactory {
685
791
  extensions: _BaseChainFactory.prototype.extensions
686
792
  };
687
793
  }
794
+ /**
795
+ * Sets the description for the field
796
+ * @param description - The description text
797
+ */
688
798
  description(description) {
689
799
  return this.clone({ description });
690
800
  }
801
+ /**
802
+ * Sets the deprecation reason for the field
803
+ * @param deprecationReason - The reason for deprecation
804
+ */
691
805
  deprecationReason(deprecationReason) {
692
806
  return this.clone({ deprecationReason });
693
807
  }
808
+ /**
809
+ * Sets custom extensions for the field
810
+ * @param extensions - Custom extensions to add
811
+ */
694
812
  extensions(extensions) {
695
813
  return this.clone({ extensions });
696
814
  }
815
+ /**
816
+ * Adds middleware functions to the field
817
+ * @param middlewares - Middleware functions to add
818
+ */
697
819
  use(...middlewares) {
698
820
  return this.clone({
699
821
  middlewares: [...this.options?.middlewares ?? [], ...middlewares]
@@ -701,6 +823,9 @@ var BaseChainFactory = class _BaseChainFactory {
701
823
  }
702
824
  };
703
825
  var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
826
+ /**
827
+ * Returns the available methods for the field chain factory
828
+ */
704
829
  static methods() {
705
830
  return {
706
831
  ...BaseChainFactory.methods(),
@@ -710,15 +835,42 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
710
835
  clone: _FieldChainFactory.prototype.clone
711
836
  };
712
837
  }
838
+ /**
839
+ * Creates a clone of the current factory with new options
840
+ * @param options - New options to apply to the clone
841
+ */
713
842
  clone(options) {
714
843
  return new _FieldChainFactory({ ...this.options, ...options });
715
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
+ */
716
850
  output(output) {
717
851
  return new _FieldChainFactory({ ...this.options, output });
718
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
+ */
719
858
  input(input) {
720
859
  return new _FieldChainFactory({ ...this.options, input });
721
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
+ */
722
874
  resolve(resolve) {
723
875
  if (!this.options?.output) throw new Error("Output is required");
724
876
  return createField(this.options.output, {
@@ -726,40 +878,47 @@ var FieldChainFactory = class _FieldChainFactory extends BaseChainFactory {
726
878
  resolve
727
879
  });
728
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
+ */
729
893
  load(resolve) {
730
894
  if (!this.options?.output) throw new Error("Output is required");
731
- const useUnifiedParseInput = createMemoization(() => ({ current: void 0 }));
732
- const useUserLoader = createMemoization(
733
- () => new EasyDataLoader(
734
- async (parents) => resolve(
735
- parents,
736
- await useUnifiedParseInput().current?.getResult()
737
- )
738
- )
739
- );
740
- const operation = "field";
741
- return meta({
742
- ...getFieldOptions(this.options),
743
- operation,
744
- input: this.options.input,
745
- output: this.options.output,
746
- resolve: async (parent, inputValue, extraOptions) => {
747
- const unifiedParseInput = useUnifiedParseInput();
748
- unifiedParseInput.current ??= createInputParser(
749
- this.options?.input,
750
- inputValue
751
- );
752
- const parseInput = unifiedParseInput.current;
753
- return applyMiddlewares(
754
- compose(extraOptions?.middlewares, this.options?.middlewares),
755
- async () => useUserLoader().load(parent),
756
- { parseInput, parent, outputSilk: this.output, operation }
757
- );
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]);
758
913
  }
759
914
  });
760
915
  }
761
916
  };
762
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
+ */
763
922
  static methods() {
764
923
  return {
765
924
  ...BaseChainFactory.methods(),
@@ -769,15 +928,38 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
769
928
  clone: _QueryChainFactory.prototype.clone
770
929
  };
771
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
+ */
772
936
  clone(options) {
773
937
  return new _QueryChainFactory({ ...this.options, ...options });
774
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
+ */
775
945
  output(output) {
776
946
  return new _QueryChainFactory({ ...this.options, output });
777
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
+ */
778
954
  input(input) {
779
955
  return new _QueryChainFactory({ ...this.options, input });
780
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
+ */
781
963
  resolve(resolve) {
782
964
  if (!this.options?.output) throw new Error("Output is required");
783
965
  return createQuery(this.options.output, {
@@ -787,6 +969,10 @@ var QueryChainFactory = class _QueryChainFactory extends BaseChainFactory {
787
969
  }
788
970
  };
789
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
+ */
790
976
  static methods() {
791
977
  return {
792
978
  ...BaseChainFactory.methods(),
@@ -796,15 +982,38 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
796
982
  clone: _MutationChainFactory.prototype.clone
797
983
  };
798
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
+ */
799
990
  clone(options) {
800
991
  return new _MutationChainFactory({ ...this.options, ...options });
801
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
+ */
802
999
  output(output) {
803
1000
  return new _MutationChainFactory({ ...this.options, output });
804
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
+ */
805
1008
  input(input) {
806
1009
  return new _MutationChainFactory({ ...this.options, input });
807
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
+ */
808
1017
  resolve(resolve) {
809
1018
  if (!this.options?.output) throw new Error("Output is required");
810
1019
  return createMutation(this.options.output, {
@@ -814,6 +1023,10 @@ var MutationChainFactory = class _MutationChainFactory extends BaseChainFactory
814
1023
  }
815
1024
  };
816
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
+ */
817
1030
  static methods() {
818
1031
  return {
819
1032
  ...BaseChainFactory.methods(),
@@ -823,15 +1036,39 @@ var SubscriptionChainFactory = class _SubscriptionChainFactory extends BaseChain
823
1036
  clone: _SubscriptionChainFactory.prototype.clone
824
1037
  };
825
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
+ */
826
1044
  clone(options) {
827
1045
  return new _SubscriptionChainFactory({ ...this.options, ...options });
828
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
+ */
829
1053
  output(output) {
830
1054
  return new _SubscriptionChainFactory({ ...this.options, output });
831
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
+ */
832
1062
  input(input) {
833
1063
  return new _SubscriptionChainFactory({ ...this.options, input });
834
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
+ */
835
1072
  subscribe(subscribe) {
836
1073
  const options = this.options;
837
1074
  const output = this.options?.output;
@@ -921,20 +1158,13 @@ var createQuery = (output, resolveOrOptions) => {
921
1158
  return new QueryChainFactory({ output });
922
1159
  }
923
1160
  const options = getOperationOptions(resolveOrOptions);
924
- const operation = "query";
925
1161
  return meta({
926
1162
  ...getFieldOptions(options),
927
1163
  input: options.input,
928
1164
  output,
929
- resolve: (inputValue, extraOptions) => {
930
- const parseInput = createInputParser(options.input, inputValue);
931
- return applyMiddlewares(
932
- compose(extraOptions?.middlewares, options.middlewares),
933
- async () => options.resolve(getStandardValue(await parseInput())),
934
- { parseInput, parent: void 0, outputSilk: output, operation }
935
- );
936
- },
937
- operation
1165
+ resolve: options.resolve,
1166
+ middlewares: options.middlewares,
1167
+ operation: "query"
938
1168
  });
939
1169
  };
940
1170
  var query = Object.assign(
@@ -946,20 +1176,13 @@ var createMutation = (output, resolveOrOptions) => {
946
1176
  return new MutationChainFactory({ output });
947
1177
  }
948
1178
  const options = getOperationOptions(resolveOrOptions);
949
- const operation = "mutation";
950
1179
  return meta({
951
1180
  ...getFieldOptions(options),
952
1181
  input: options.input,
953
1182
  output,
954
- resolve: (inputValue, extraOptions) => {
955
- const parseInput = createInputParser(options.input, inputValue);
956
- return applyMiddlewares(
957
- compose(extraOptions?.middlewares, options.middlewares),
958
- async () => options.resolve(getStandardValue(await parseInput())),
959
- { parseInput, parent: void 0, outputSilk: output, operation }
960
- );
961
- },
962
- operation
1183
+ resolve: options.resolve,
1184
+ middlewares: options.middlewares,
1185
+ operation: "mutation"
963
1186
  });
964
1187
  };
965
1188
  var mutation = Object.assign(
@@ -971,20 +1194,16 @@ var createField = (output, resolveOrOptions) => {
971
1194
  return new FieldChainFactory({ output });
972
1195
  }
973
1196
  const options = getOperationOptions(resolveOrOptions);
974
- const operation = "field";
975
1197
  return meta({
976
- ...getFieldOptions(options),
1198
+ ...getFieldOptions(options, {
1199
+ [DERIVED_DEPENDENCIES]: options.dependencies
1200
+ }),
977
1201
  input: options.input,
1202
+ dependencies: options.dependencies,
978
1203
  output,
979
- resolve: (parent, inputValue, extraOptions) => {
980
- const parseInput = createInputParser(options.input, inputValue);
981
- return applyMiddlewares(
982
- compose(extraOptions?.middlewares, options.middlewares),
983
- async () => options.resolve(parent, getStandardValue(await parseInput())),
984
- { parseInput, parent, outputSilk: output, operation }
985
- );
986
- },
987
- operation
1204
+ resolve: options.resolve,
1205
+ middlewares: options.middlewares,
1206
+ operation: "field"
988
1207
  });
989
1208
  };
990
1209
  var field = Object.assign(
@@ -998,72 +1217,20 @@ function createSubscription(output, subscribeOrOptions) {
998
1217
  return new SubscriptionChainFactory({ output });
999
1218
  }
1000
1219
  const options = getSubscriptionOptions(subscribeOrOptions);
1001
- const operation = "subscription";
1002
1220
  return meta({
1003
1221
  ...getFieldOptions(options),
1004
1222
  input: options.input,
1005
1223
  output,
1006
- subscribe: (inputValue, extraOptions) => {
1007
- const parseInput = createInputParser(options.input, inputValue);
1008
- return applyMiddlewares(
1009
- compose(
1010
- extraOptions?.middlewares,
1011
- options.middlewares
1012
- ),
1013
- async () => options.subscribe(getStandardValue(await parseInput())),
1014
- { parseInput, parent: void 0, outputSilk: output, operation }
1015
- );
1016
- },
1224
+ subscribe: options.subscribe,
1017
1225
  resolve: options.resolve ?? defaultSubscriptionResolve,
1018
- operation
1226
+ middlewares: options.middlewares,
1227
+ operation: "subscription"
1019
1228
  });
1020
1229
  }
1021
1230
  var subscription = Object.assign(
1022
1231
  createSubscription,
1023
1232
  SubscriptionChainFactory.methods()
1024
1233
  );
1025
- function extraOperationOptions(field2, options) {
1026
- if (typeof field2 === "symbol") return field2;
1027
- const composeMiddlewares = (extraOptions) => compose(extraOptions?.middlewares, options?.middlewares);
1028
- switch (field2["~meta"].operation) {
1029
- case "field":
1030
- return {
1031
- ...field2,
1032
- "~meta": {
1033
- ...field2["~meta"],
1034
- resolve: (parent, input, extraOptions) => field2["~meta"].resolve(parent, input, {
1035
- ...extraOptions,
1036
- middlewares: composeMiddlewares(extraOptions)
1037
- })
1038
- }
1039
- };
1040
- case "subscription":
1041
- return {
1042
- ...field2,
1043
- "~meta": {
1044
- ...field2["~meta"],
1045
- subscribe: (input, extraOptions) => field2["~meta"].subscribe(
1046
- input,
1047
- {
1048
- ...extraOptions,
1049
- middlewares: composeMiddlewares(extraOptions)
1050
- }
1051
- )
1052
- }
1053
- };
1054
- default:
1055
- return {
1056
- ...field2,
1057
- "~meta": {
1058
- ...field2["~meta"],
1059
- resolve: (input, extraOptions) => field2["~meta"].resolve(input, {
1060
- ...extraOptions,
1061
- middlewares: composeMiddlewares(extraOptions)
1062
- })
1063
- }
1064
- };
1065
- }
1066
- }
1067
1234
  var resolver = Object.assign(
1068
1235
  (operations, options) => new ChainResolver(operations, options),
1069
1236
  {
@@ -1083,6 +1250,11 @@ var loom = {
1083
1250
  };
1084
1251
  var ChainResolver = class {
1085
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
+ */
1086
1258
  constructor(fields, options) {
1087
1259
  this.meta = {
1088
1260
  [IS_RESOLVER]: true,
@@ -1090,38 +1262,83 @@ var ChainResolver = class {
1090
1262
  options
1091
1263
  };
1092
1264
  }
1265
+ /**
1266
+ * Gets the metadata for the resolver
1267
+ */
1093
1268
  get "~meta"() {
1094
- const fields = {};
1095
- Object.entries(this.meta.fields).forEach(([name, field2]) => {
1096
- if (field2 === FIELD_HIDDEN) {
1097
- fields[name] = field2;
1098
- } else {
1099
- fields[name] = extraOperationOptions(field2, this.meta.options);
1100
- }
1101
- });
1102
- return {
1103
- ...this.meta,
1104
- fields
1105
- };
1269
+ return this.meta;
1106
1270
  }
1271
+ /**
1272
+ * Adds middleware functions to the resolver
1273
+ * @param middlewares - The middleware functions to add
1274
+ */
1107
1275
  use(...middlewares) {
1108
1276
  this.meta.options ??= {};
1109
1277
  this.meta.options.middlewares ??= [];
1110
1278
  this.meta.options.middlewares.push(...middlewares);
1111
1279
  return this;
1112
1280
  }
1113
- toExecutor() {
1114
- const fields = this["~meta"].fields;
1115
- const executor = {};
1116
- Object.entries(fields).forEach(([name, field2]) => {
1117
- if (field2 === FIELD_HIDDEN) return;
1118
- executor[name] = field2["~meta"].resolve;
1119
- });
1281
+ toExecutor(...middlewares) {
1282
+ const executor = mapValue(
1283
+ this["~meta"].fields,
1284
+ (field2) => this.toExecutorOperation(field2, middlewares) ?? mapValue.SKIP
1285
+ );
1120
1286
  return executor;
1121
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
+ }
1122
1333
  };
1123
1334
  var ObjectChainResolver = class extends ChainResolver {
1124
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
+ */
1125
1342
  constructor(parent, fields, options) {
1126
1343
  super(fields, options);
1127
1344
  this.meta = {
@@ -1131,9 +1348,16 @@ var ObjectChainResolver = class extends ChainResolver {
1131
1348
  options
1132
1349
  };
1133
1350
  }
1351
+ /**
1352
+ * Gets the metadata for the resolver
1353
+ */
1134
1354
  get "~meta"() {
1135
1355
  return super["~meta"];
1136
1356
  }
1357
+ /**
1358
+ * Sets custom extensions for the resolver
1359
+ * @param extensions - The extensions to add
1360
+ */
1137
1361
  extensions(extensions) {
1138
1362
  this.meta.options ??= {};
1139
1363
  this.meta.options.extensions ??= {};
@@ -1146,27 +1370,16 @@ var ObjectChainResolver = class extends ChainResolver {
1146
1370
  };
1147
1371
 
1148
1372
  // src/schema/object.ts
1149
- var import_graphql5 = require("graphql");
1150
-
1151
- // src/utils/async-iterator.ts
1152
- function bindAsyncIterator(storage, generator) {
1153
- const store = storage.getStore();
1154
- const next = generator.next;
1155
- Object.defineProperty(generator, "next", {
1156
- value: (...args) => storage.run(store, () => next.apply(generator, args)),
1157
- writable: false
1158
- });
1159
- return generator;
1160
- }
1373
+ var import_graphql8 = require("graphql");
1161
1374
 
1162
1375
  // src/schema/input.ts
1163
- var import_graphql4 = require("graphql");
1376
+ var import_graphql7 = require("graphql");
1164
1377
  function inputToArgs(input, options) {
1165
1378
  if (input === void 0) return void 0;
1166
1379
  if (isSilk(input)) {
1167
1380
  let inputType = getGraphQLType(input);
1168
- if ((0, import_graphql4.isNonNullType)(inputType)) inputType = inputType.ofType;
1169
- if ((0, import_graphql4.isObjectType)(inputType)) {
1381
+ if ((0, import_graphql7.isNonNullType)(inputType)) inputType = inputType.ofType;
1382
+ if ((0, import_graphql7.isObjectType)(inputType)) {
1170
1383
  return mapValue(inputType.toConfig().fields, (it, key) => {
1171
1384
  let fieldName;
1172
1385
  if (options?.fieldName) {
@@ -1199,20 +1412,20 @@ function ensureInputType(silkOrType, options) {
1199
1412
  }
1200
1413
  return silkOrType;
1201
1414
  })();
1202
- if ((0, import_graphql4.isUnionType)(gqlType))
1415
+ if ((0, import_graphql7.isUnionType)(gqlType))
1203
1416
  throw new Error(`Cannot convert union type ${gqlType.name} to input type`);
1204
- if ((0, import_graphql4.isNonNullType)(gqlType)) {
1205
- 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));
1206
1419
  }
1207
- if ((0, import_graphql4.isListType)(gqlType)) {
1208
- 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));
1209
1422
  }
1210
- if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isInterfaceType)(gqlType))
1423
+ if ((0, import_graphql7.isObjectType)(gqlType) || (0, import_graphql7.isInterfaceType)(gqlType))
1211
1424
  return ensureInputObjectType(gqlType, options);
1212
1425
  return gqlType;
1213
1426
  }
1214
1427
  function ensureInputObjectType(object, options) {
1215
- if ((0, import_graphql4.isInputObjectType)(object)) return object;
1428
+ if ((0, import_graphql7.isInputObjectType)(object)) return object;
1216
1429
  const existing = weaverContext.inputMap?.get(object);
1217
1430
  if (existing != null) return existing;
1218
1431
  const { astNode, extensionASTNodes, fields, ...config } = object.toConfig();
@@ -1222,7 +1435,7 @@ function ensureInputObjectType(object, options) {
1222
1435
  }
1223
1436
  const getInputObjectName = weaverContext.getConfig("gqloom.core.schema")?.getInputObjectName ?? ((n) => n);
1224
1437
  name = getInputObjectName(name);
1225
- const input = new import_graphql4.GraphQLInputObjectType({
1438
+ const input = new import_graphql7.GraphQLInputObjectType({
1226
1439
  ...config,
1227
1440
  name,
1228
1441
  fields: provideWeaverContext.inherit(
@@ -1248,16 +1461,20 @@ function inputFieldName(name) {
1248
1461
  }
1249
1462
 
1250
1463
  // src/schema/object.ts
1251
- var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObjectType {
1464
+ var LoomObjectType = class _LoomObjectType extends import_graphql8.GraphQLObjectType {
1252
1465
  extraFields = /* @__PURE__ */ new Map();
1253
1466
  hiddenFields = /* @__PURE__ */ new Set();
1254
1467
  static AUTO_ALIASING = "__gqloom_auto_aliasing";
1255
1468
  weaverContext;
1256
- resolverOptions;
1469
+ globalOptions;
1470
+ /**
1471
+ * field name -> resolver
1472
+ */
1473
+ resolvers;
1257
1474
  constructor(objectOrGetter, options = {}) {
1258
1475
  const origin = typeof objectOrGetter === "function" ? objectOrGetter() : objectOrGetter;
1259
1476
  const config = (() => {
1260
- if ((0, import_graphql5.isObjectType)(origin)) {
1477
+ if ((0, import_graphql8.isObjectType)(origin)) {
1261
1478
  return origin.toConfig();
1262
1479
  } else if (typeof origin === "string") {
1263
1480
  return { name: origin, fields: {} };
@@ -1266,8 +1483,9 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1266
1483
  }
1267
1484
  })();
1268
1485
  super(config);
1269
- this.resolverOptions = options.resolverOptions;
1486
+ this.globalOptions = options.globalOptions;
1270
1487
  this.weaverContext = options.weaverContext ?? initWeaverContext();
1488
+ this.resolvers = /* @__PURE__ */ new Map();
1271
1489
  if (this.name !== _LoomObjectType.AUTO_ALIASING) {
1272
1490
  this.hasExplicitName = true;
1273
1491
  }
@@ -1294,12 +1512,13 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1294
1512
  hideField(name) {
1295
1513
  this.hiddenFields.add(name);
1296
1514
  }
1297
- addField(name, resolver2) {
1515
+ addField(name, field2, resolver2) {
1298
1516
  const existing = this.extraFields.get(name);
1299
- if (existing && existing !== resolver2) {
1517
+ if (existing && existing !== field2) {
1300
1518
  throw new Error(`Field ${name} already exists in ${this.name}`);
1301
1519
  }
1302
- this.extraFields.set(name, resolver2);
1520
+ this.extraFields.set(name, field2);
1521
+ if (resolver2) this.resolvers.set(name, resolver2);
1303
1522
  }
1304
1523
  mergeExtensions(extensions) {
1305
1524
  this.extensions = deepMerge(this.extensions, extensions);
@@ -1334,58 +1553,140 @@ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObject
1334
1553
  return record;
1335
1554
  }
1336
1555
  toFieldConfig(field2, fieldName) {
1337
- try {
1338
- const outputType = this.getCacheType(
1339
- getGraphQLType(field2["~meta"].output),
1340
- fieldName
1341
- );
1342
- return {
1343
- ...extract(field2),
1344
- type: outputType,
1345
- args: inputToArgs(field2["~meta"].input, {
1346
- fieldName: fieldName ? parentName(this.name) + fieldName : void 0
1347
- }),
1348
- ...this.provideForResolve(field2),
1349
- ...this.provideForSubscribe(field2)
1350
- };
1351
- } catch (error) {
1352
- throw markErrorLocation(error);
1353
- }
1354
- }
1355
- provideForResolve(field2) {
1356
- if (field2?.["~meta"]?.resolve == null) return;
1357
- if (field2["~meta"].resolve === defaultSubscriptionResolve)
1358
- return { resolve: defaultSubscriptionResolve };
1359
- const resolve = field2["~meta"].operation === "field" ? (root, args, context, info) => resolverPayloadStorage.run(
1360
- { root, args, context, info, field: field2 },
1361
- () => field2["~meta"].resolve(root, args, this.resolverOptions)
1362
- ) : field2["~meta"].operation === "subscription" ? (root, args, context, info) => resolverPayloadStorage.run(
1363
- { root, args, context, info, field: field2 },
1364
- () => field2["~meta"].resolve(root, args)
1365
- ) : (root, args, context, info) => resolverPayloadStorage.run(
1366
- { root, args, context, info, field: field2 },
1367
- () => field2["~meta"].resolve(args, this.resolverOptions)
1556
+ const outputType = this.getCacheType(
1557
+ getGraphQLType(field2["~meta"].output),
1558
+ fieldName
1368
1559
  );
1369
- 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
+ };
1370
1571
  }
1371
- provideForSubscribe(field2) {
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
+ }
1655
+ }
1656
+ provideForSubscribe(field2, fieldName) {
1372
1657
  if (field2?.["~meta"]?.subscribe == null)
1373
1658
  return;
1374
- return {
1375
- subscribe: (root, args, context, info) => resolverPayloadStorage.run(
1376
- { root, args, context, info, field: field2 },
1377
- async () => {
1378
- const generator = await field2["~meta"].subscribe?.(args, this.resolverOptions);
1379
- return bindAsyncIterator(resolverPayloadStorage, generator);
1380
- }
1381
- )
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
+ );
1382
1683
  };
1383
1684
  }
1384
1685
  getCacheType(gqlType, fieldName) {
1385
1686
  return getCacheType(gqlType, { ...this.options, fieldName, parent: this });
1386
1687
  }
1387
1688
  get options() {
1388
- const { resolverOptions, weaverContext: weaverContext2 } = this;
1689
+ const { globalOptions: resolverOptions, weaverContext: weaverContext2 } = this;
1389
1690
  return { resolverOptions, weaverContext: weaverContext2 };
1390
1691
  }
1391
1692
  };
@@ -1398,11 +1699,11 @@ function extract(field2) {
1398
1699
  };
1399
1700
  }
1400
1701
  function defineFieldMap(fields) {
1401
- const fieldMap = (0, import_graphql5.resolveObjMapThunk)(fields);
1702
+ const fieldMap = (0, import_graphql8.resolveObjMapThunk)(fields);
1402
1703
  return mapValue(fieldMap, (fieldConfig, fieldName) => {
1403
1704
  const argsConfig = fieldConfig.args ?? {};
1404
1705
  return {
1405
- name: (0, import_graphql5.assertName)(fieldName),
1706
+ name: (0, import_graphql8.assertName)(fieldName),
1406
1707
  description: fieldConfig.description,
1407
1708
  type: fieldConfig.type,
1408
1709
  args: defineArguments(argsConfig),
@@ -1416,7 +1717,7 @@ function defineFieldMap(fields) {
1416
1717
  }
1417
1718
  function defineArguments(args) {
1418
1719
  return Object.entries(args).map(([argName, argConfig]) => ({
1419
- name: (0, import_graphql5.assertName)(argName),
1720
+ name: (0, import_graphql8.assertName)(argName),
1420
1721
  description: argConfig.description,
1421
1722
  type: argConfig.type,
1422
1723
  defaultValue: argConfig.defaultValue,
@@ -1433,7 +1734,7 @@ var OPERATION_OBJECT_NAMES = /* @__PURE__ */ new Set([
1433
1734
  function getCacheType(gqlType, options = {}) {
1434
1735
  const context = options.weaverContext ?? weaverContext;
1435
1736
  if (gqlType instanceof LoomObjectType) return gqlType;
1436
- if ((0, import_graphql5.isObjectType)(gqlType)) {
1737
+ if ((0, import_graphql8.isObjectType)(gqlType)) {
1437
1738
  const gqlObject = context.loomObjectMap?.get(gqlType);
1438
1739
  if (gqlObject != null) return gqlObject;
1439
1740
  const loomObject = new LoomObjectType(gqlType, options);
@@ -1444,15 +1745,15 @@ function getCacheType(gqlType, options = {}) {
1444
1745
  );
1445
1746
  }
1446
1747
  return loomObject;
1447
- } else if ((0, import_graphql5.isListType)(gqlType)) {
1448
- return new import_graphql5.GraphQLList(getCacheType(gqlType.ofType, options));
1449
- } else if ((0, import_graphql5.isNonNullType)(gqlType)) {
1450
- return new import_graphql5.GraphQLNonNull(getCacheType(gqlType.ofType, options));
1451
- } 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)) {
1452
1753
  const existing = context.loomUnionMap?.get(gqlType);
1453
1754
  if (existing != null) return existing;
1454
1755
  const config = gqlType.toConfig();
1455
- const unionType = new import_graphql5.GraphQLUnionType({
1756
+ const unionType = new import_graphql8.GraphQLUnionType({
1456
1757
  ...config,
1457
1758
  types: config.types.map(
1458
1759
  (type) => getCacheType(type, options)
@@ -1479,7 +1780,7 @@ function isSchemaVendorWeaver(some) {
1479
1780
  }
1480
1781
 
1481
1782
  // src/schema/schema-loom.ts
1482
- var import_graphql6 = require("graphql");
1783
+ var import_graphql9 = require("graphql");
1483
1784
  var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1484
1785
  query;
1485
1786
  mutation;
@@ -1522,14 +1823,14 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1522
1823
  addType(silk2) {
1523
1824
  const gqlType = provideWeaverContext(() => {
1524
1825
  let gqlType2 = getGraphQLType(silk2);
1525
- if ((0, import_graphql6.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1526
- if ((0, import_graphql6.isObjectType)(gqlType2)) {
1826
+ if ((0, import_graphql9.isNonNullType)(gqlType2)) gqlType2 = gqlType2.ofType;
1827
+ if ((0, import_graphql9.isObjectType)(gqlType2)) {
1527
1828
  const existing = this.context.loomObjectMap.get(gqlType2);
1528
1829
  if (existing != null) return existing;
1529
1830
  const extraObject = new LoomObjectType(gqlType2, this.fieldOptions);
1530
1831
  this.context.loomObjectMap.set(gqlType2, extraObject);
1531
1832
  return extraObject;
1532
- } 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)) {
1533
1834
  return gqlType2;
1534
1835
  }
1535
1836
  throw new Error(
@@ -1546,7 +1847,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1546
1847
  weaveGraphQLSchema() {
1547
1848
  const { query: query2, mutation: mutation2, subscription: subscription2, types } = this;
1548
1849
  const config = this.context.getConfig("gqloom.core.schema");
1549
- const schema = new import_graphql6.GraphQLSchema({
1850
+ const schema = new import_graphql9.GraphQLSchema({
1550
1851
  query: query2,
1551
1852
  mutation: mutation2,
1552
1853
  subscription: subscription2,
@@ -1561,8 +1862,8 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1561
1862
  const parentObject = (() => {
1562
1863
  if (parent == null) return void 0;
1563
1864
  let gqlType = getGraphQLType(parent);
1564
- if ((0, import_graphql6.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1565
- if (!(0, import_graphql6.isObjectType)(gqlType)) {
1865
+ if ((0, import_graphql9.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1866
+ if (!(0, import_graphql9.isObjectType)(gqlType)) {
1566
1867
  throw new Error(
1567
1868
  `${gqlType?.name ?? gqlType.toString()} is not an object type`
1568
1869
  );
@@ -1582,12 +1883,12 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1582
1883
  parentObject.hideField(name);
1583
1884
  } else if (field2["~meta"].operation === "field") {
1584
1885
  if (parentObject == null) return;
1585
- parentObject.addField(name, field2);
1886
+ parentObject.addField(name, field2, resolver2);
1586
1887
  } else {
1587
1888
  const operationObject = this.getOperationObject(
1588
1889
  field2["~meta"].operation
1589
1890
  );
1590
- operationObject.addField(name, field2);
1891
+ operationObject.addField(name, field2, resolver2);
1591
1892
  }
1592
1893
  });
1593
1894
  return this;
@@ -1619,7 +1920,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1619
1920
  }
1620
1921
  get fieldOptions() {
1621
1922
  const { resolverOptions, context } = this;
1622
- return { resolverOptions, weaverContext: context };
1923
+ return { globalOptions: resolverOptions, weaverContext: context };
1623
1924
  }
1624
1925
  static optionsFrom(...inputs) {
1625
1926
  const configs = /* @__PURE__ */ new Set();
@@ -1629,6 +1930,7 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1629
1930
  const weavers = /* @__PURE__ */ new Set();
1630
1931
  let context;
1631
1932
  for (const item of inputs) {
1933
+ if (item == null) continue;
1632
1934
  if (isSchemaVendorWeaver(item)) {
1633
1935
  weavers.add(item);
1634
1936
  } else if (typeof item === "function") {
@@ -1666,10 +1968,10 @@ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1666
1968
  var weave = GraphQLSchemaLoom.weave;
1667
1969
 
1668
1970
  // src/schema/interface.ts
1669
- var import_graphql7 = require("graphql");
1971
+ var import_graphql10 = require("graphql");
1670
1972
  function ensureInterfaceType(gqlType, interfaceConfig) {
1671
- if ((0, import_graphql7.isInterfaceType)(gqlType)) return gqlType;
1672
- if (!(0, import_graphql7.isObjectType)(gqlType))
1973
+ if ((0, import_graphql10.isInterfaceType)(gqlType)) return gqlType;
1974
+ if (!(0, import_graphql10.isObjectType)(gqlType))
1673
1975
  throw new Error(`${gqlType.toString()} is not an object`);
1674
1976
  const key = gqlType;
1675
1977
  const existing = weaverContext.interfaceMap?.get(key);
@@ -1680,7 +1982,7 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1680
1982
  fields,
1681
1983
  ...config
1682
1984
  } = gqlType.toConfig();
1683
- const interfaceType = new import_graphql7.GraphQLInterfaceType({
1985
+ const interfaceType = new import_graphql10.GraphQLInterfaceType({
1684
1986
  ...config,
1685
1987
  ...interfaceConfig,
1686
1988
  fields: mapValue(fields, (field2) => {
@@ -1694,7 +1996,6 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1694
1996
  0 && (module.exports = {
1695
1997
  BaseChainFactory,
1696
1998
  ChainResolver,
1697
- ContextMemoization,
1698
1999
  EasyDataLoader,
1699
2000
  FieldChainFactory,
1700
2001
  FieldFactoryWithResolve,
@@ -1709,13 +2010,12 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1709
2010
  SYMBOLS,
1710
2011
  SubscriptionChainFactory,
1711
2012
  applyMiddlewares,
2013
+ assignContextMap,
1712
2014
  capitalize,
1713
2015
  collectName,
1714
2016
  collectNames,
1715
- compose,
1716
2017
  createField,
1717
2018
  createInputParser,
1718
- createMemoization,
1719
2019
  createMutation,
1720
2020
  createQuery,
1721
2021
  createSubscription,
@@ -1725,10 +2025,13 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1725
2025
  ensureInputType,
1726
2026
  ensureInterfaceType,
1727
2027
  field,
2028
+ filterMiddlewares,
1728
2029
  getCacheType,
1729
2030
  getFieldOptions,
1730
2031
  getGraphQLType,
2032
+ getMemoizationMap,
1731
2033
  getOperationOptions,
2034
+ getResolvingFields,
1732
2035
  getStandardValue,
1733
2036
  getSubscriptionOptions,
1734
2037
  initWeaverContext,
@@ -1748,19 +2051,17 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1748
2051
  nullableSilk,
1749
2052
  onlyMemoization,
1750
2053
  parseInputValue,
2054
+ parseResolvingFields,
1751
2055
  parseSilk,
1752
2056
  pascalCase,
1753
2057
  provideWeaverContext,
1754
2058
  query,
1755
2059
  resolver,
1756
- resolverPayloadStorage,
2060
+ screamingSnakeCase,
1757
2061
  silk,
1758
2062
  subscription,
1759
2063
  toObjMap,
1760
2064
  tryIn,
1761
- useContext,
1762
- useMemoizationMap,
1763
- useResolverPayload,
1764
2065
  weave,
1765
2066
  weaverContext
1766
2067
  });