@vantreeseba/drizzle-graphql 9.1.1 → 10.0.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.d.cts CHANGED
@@ -6,7 +6,6 @@ import "drizzle-orm/pg-core/query-builders/query";
6
6
  import { SQLiteAsyncDatabase } from "drizzle-orm/sqlite-core";
7
7
  import "drizzle-orm/sqlite-core/query-builders/query";
8
8
  import { ASTNode, GraphQLEnumType, GraphQLError, GraphQLFieldResolver, GraphQLInputObjectType, GraphQLInputType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo, GraphQLScalarType, GraphQLSchema } from "graphql";
9
- import { ResolveTree } from "graphql-parse-resolve-info";
10
9
  import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
11
10
  //#region src/util/extensions.d.ts
12
11
  /**
@@ -160,6 +159,8 @@ type DrizzleErrorCode =
160
159
  'DRIZZLE_INVALID_ON_CONFLICT' |
161
160
  /** A written value could not be converted to what its column stores. */
162
161
  'DRIZZLE_INVALID_INPUT_VALUE' |
162
+ /** An update's `set` gave a column that cannot hold null an explicit null. */
163
+ 'DRIZZLE_NOT_NULL' |
163
164
  /** A write's input named a key that is not a column of the table. */
164
165
  'DRIZZLE_UNKNOWN_COLUMN' |
165
166
  /** A stored value could not be represented by the scalar that transports it. */
@@ -612,6 +613,53 @@ type TablePolicies = {
612
613
  defaultOrderBy?: DefaultOrderByFor;
613
614
  };
614
615
  //#endregion
616
+ //#region src/util/parse-resolve-info.d.ts
617
+ /**
618
+ * The selections made against one concrete type, keyed by the *response key* — the field's
619
+ * alias when it has one, otherwise its name. A selection spanning an abstract type has one
620
+ * entry per type condition it was written against (the interface or union itself included,
621
+ * when fields were selected directly on it).
622
+ */
623
+ interface FieldsByTypeName {
624
+ [typeName: string]: {
625
+ [responseKey: string]: ResolveTree;
626
+ };
627
+ }
628
+ /** One selected field: what was asked for, under what alias, with which arguments. */
629
+ interface ResolveTree {
630
+ /** The field name as declared in the schema. */
631
+ name: string;
632
+ /** The response key — the alias when the selection carried one, otherwise `name`. */
633
+ alias: string;
634
+ /** The field's arguments, coerced by graphql's own `getArgumentValues`. */
635
+ args: {
636
+ [argName: string]: unknown;
637
+ };
638
+ /** The field's own sub-selections, keyed by the type they were written against. */
639
+ fieldsByTypeName: FieldsByTypeName;
640
+ }
641
+ /** Options accepted by {@link parseResolveInfo}. */
642
+ interface ParseResolveInfoOptions {
643
+ /**
644
+ * Whether to descend into sub-selections and fragments. Defaults to `true`; `false` reads
645
+ * only the root field's own name, alias and arguments.
646
+ */
647
+ deep?: boolean;
648
+ }
649
+ /**
650
+ * Reads the selection under a resolver's own field out of its `info`, as a tree of
651
+ * {@link ResolveTree} nodes.
652
+ *
653
+ * ```ts
654
+ * const parsed = parseResolveInfo(info, { deep: true })!;
655
+ * const selected = parsed.fieldsByTypeName['Users']; // keyed by response key
656
+ * ```
657
+ *
658
+ * Returns `undefined` when the resolver's field produced no node at all, which in practice
659
+ * means `info` carried no field nodes.
660
+ */
661
+ declare const parseResolveInfo: (info: GraphQLResolveInfo, options?: ParseResolveInfoOptions) => ResolveTree | undefined;
662
+ //#endregion
615
663
  //#region src/util/builders/common/order-by.d.ts
616
664
  /**
617
665
  * Compiles an `orderBy` argument into ORDER BY expressions, highest priority first.
@@ -2128,5 +2176,5 @@ declare const resolveSelection: (info: GraphQLResolveInfo | ResolveTree, options
2128
2176
  //#region src/index.d.ts
2129
2177
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
2130
2178
  //#endregion
2131
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, resolveSelection, selectionToWith, singularizeMapper };
2179
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type FieldsByTypeName, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type ParseResolveInfoOptions, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type ResolveTree, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, parseResolveInfo, resolveSelection, selectionToWith, singularizeMapper };
2132
2180
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -4,7 +4,6 @@ import { PgAsyncDatabase } from "drizzle-orm/pg-core";
4
4
  import { SQLiteAsyncDatabase } from "drizzle-orm/sqlite-core";
5
5
  import { ASTNode, GraphQLEnumType, GraphQLError, GraphQLFieldResolver, GraphQLInputObjectType, GraphQLInputType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo, GraphQLScalarType, GraphQLSchema } from "graphql";
6
6
  import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
7
- import { ResolveTree } from "graphql-parse-resolve-info";
8
7
  import "drizzle-orm/mysql-core/query-builders/query";
9
8
  import "drizzle-orm/pg-core/query-builders/query";
10
9
  import "drizzle-orm/sqlite-core/query-builders/query";
@@ -160,6 +159,8 @@ type DrizzleErrorCode =
160
159
  'DRIZZLE_INVALID_ON_CONFLICT' |
161
160
  /** A written value could not be converted to what its column stores. */
162
161
  'DRIZZLE_INVALID_INPUT_VALUE' |
162
+ /** An update's `set` gave a column that cannot hold null an explicit null. */
163
+ 'DRIZZLE_NOT_NULL' |
163
164
  /** A write's input named a key that is not a column of the table. */
164
165
  'DRIZZLE_UNKNOWN_COLUMN' |
165
166
  /** A stored value could not be represented by the scalar that transports it. */
@@ -612,6 +613,53 @@ type TablePolicies = {
612
613
  defaultOrderBy?: DefaultOrderByFor;
613
614
  };
614
615
  //#endregion
616
+ //#region src/util/parse-resolve-info.d.ts
617
+ /**
618
+ * The selections made against one concrete type, keyed by the *response key* — the field's
619
+ * alias when it has one, otherwise its name. A selection spanning an abstract type has one
620
+ * entry per type condition it was written against (the interface or union itself included,
621
+ * when fields were selected directly on it).
622
+ */
623
+ interface FieldsByTypeName {
624
+ [typeName: string]: {
625
+ [responseKey: string]: ResolveTree;
626
+ };
627
+ }
628
+ /** One selected field: what was asked for, under what alias, with which arguments. */
629
+ interface ResolveTree {
630
+ /** The field name as declared in the schema. */
631
+ name: string;
632
+ /** The response key — the alias when the selection carried one, otherwise `name`. */
633
+ alias: string;
634
+ /** The field's arguments, coerced by graphql's own `getArgumentValues`. */
635
+ args: {
636
+ [argName: string]: unknown;
637
+ };
638
+ /** The field's own sub-selections, keyed by the type they were written against. */
639
+ fieldsByTypeName: FieldsByTypeName;
640
+ }
641
+ /** Options accepted by {@link parseResolveInfo}. */
642
+ interface ParseResolveInfoOptions {
643
+ /**
644
+ * Whether to descend into sub-selections and fragments. Defaults to `true`; `false` reads
645
+ * only the root field's own name, alias and arguments.
646
+ */
647
+ deep?: boolean;
648
+ }
649
+ /**
650
+ * Reads the selection under a resolver's own field out of its `info`, as a tree of
651
+ * {@link ResolveTree} nodes.
652
+ *
653
+ * ```ts
654
+ * const parsed = parseResolveInfo(info, { deep: true })!;
655
+ * const selected = parsed.fieldsByTypeName['Users']; // keyed by response key
656
+ * ```
657
+ *
658
+ * Returns `undefined` when the resolver's field produced no node at all, which in practice
659
+ * means `info` carried no field nodes.
660
+ */
661
+ declare const parseResolveInfo: (info: GraphQLResolveInfo, options?: ParseResolveInfoOptions) => ResolveTree | undefined;
662
+ //#endregion
615
663
  //#region src/util/builders/common/order-by.d.ts
616
664
  /**
617
665
  * Compiles an `orderBy` argument into ORDER BY expressions, highest priority first.
@@ -2128,5 +2176,5 @@ declare const resolveSelection: (info: GraphQLResolveInfo | ResolveTree, options
2128
2176
  //#region src/index.d.ts
2129
2177
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
2130
2178
  //#endregion
2131
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, resolveSelection, selectionToWith, singularizeMapper };
2179
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type FieldsByTypeName, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type ParseResolveInfoOptions, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type ResolveTree, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, parseResolveInfo, resolveSelection, selectionToWith, singularizeMapper };
2132
2180
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -2,10 +2,9 @@ import { Column, One, SQL, Table, aliasedTable, and, arrayContains, arrayOverlap
2
2
  import { MySqlAsyncDatabase, MySqlInt, MySqlSerial, MySqlTable, getTableConfig } from "drizzle-orm/mysql-core";
3
3
  import { PgAsyncDatabase, PgDate, PgDateString, PgInteger, PgSerial, PgTable, PgTimestamp, PgTimestampString, PgUUID, getTableConfig as getTableConfig$1 } from "drizzle-orm/pg-core";
4
4
  import { SQLiteAsyncDatabase, SQLiteInteger, SQLiteTable, getTableConfig as getTableConfig$2 } from "drizzle-orm/sqlite-core";
5
- import { GraphQLBoolean, GraphQLEnumType, GraphQLError, GraphQLFloat, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString, Kind } from "graphql";
5
+ import { GraphQLBoolean, GraphQLEnumType, GraphQLError, GraphQLFloat, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString, Kind, getArgumentValues } from "graphql";
6
6
  import pluralize from "pluralize";
7
7
  import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
8
- import { parseResolveInfo } from "graphql-parse-resolve-info";
9
8
  //#region src/util/builders/common/errors.ts
10
9
  /**
11
10
  * A `GraphQLError` carrying its context as data. The message says what went wrong, in prose
@@ -564,12 +563,13 @@ const remapFromGraphQLCore = (value, column, columnName) => {
564
563
  return value;
565
564
  }
566
565
  };
567
- const remapFromGraphQLSingleInput = (queryInput, table) => {
566
+ const remapFromGraphQLSingleInput = (queryInput, table, operation = "insert") => {
568
567
  for (const [key, value] of Object.entries(queryInput)) if (value === void 0) delete queryInput[key];
569
568
  else {
570
569
  const column = getTableColumns(table)[key];
571
570
  if (!column) throw drizzleError(`Unknown column: ${key}`, { code: "DRIZZLE_UNKNOWN_COLUMN" });
572
571
  if (value === null && column.notNull) {
572
+ if (operation === "update") throw drizzleError(`Column '${key}' cannot be set to null.`, { code: "DRIZZLE_NOT_NULL" });
573
573
  delete queryInput[key];
574
574
  continue;
575
575
  }
@@ -577,8 +577,8 @@ const remapFromGraphQLSingleInput = (queryInput, table) => {
577
577
  }
578
578
  return queryInput;
579
579
  };
580
- const remapFromGraphQLArrayInput = (queryInput, table) => {
581
- for (const entry of queryInput) remapFromGraphQLSingleInput(entry, table);
580
+ const remapFromGraphQLArrayInput = (queryInput, table, operation = "insert") => {
581
+ for (const entry of queryInput) remapFromGraphQLSingleInput(entry, table, operation);
582
582
  return queryInput;
583
583
  };
584
584
  //#endregion
@@ -2980,10 +2980,14 @@ const splitFieldUpdateOperations = (values, table, tableName) => {
2980
2980
  *
2981
2981
  * Safe to call on every update path regardless of `features.fieldUpdateOperations` — see the
2982
2982
  * shape check in {@link splitFieldUpdateOperations}.
2983
+ *
2984
+ * This is the single funnel every update goes through — the plural and `Single` mutations,
2985
+ * `updateMany`, the `Count` mutations and the MySQL builder's own — which is why it is the
2986
+ * one place that has to tell the remapper it is serving an update rather than an insert.
2983
2987
  */
2984
2988
  const remapUpdateInput = (values, table, tableName) => {
2985
2989
  const { columns, expressions } = splitFieldUpdateOperations(values, table, tableName);
2986
- const remapped = remapFromGraphQLSingleInput(columns, table);
2990
+ const remapped = remapFromGraphQLSingleInput(columns, table, "update");
2987
2991
  return Object.keys(expressions).length ? {
2988
2992
  ...remapped,
2989
2993
  ...expressions
@@ -4740,6 +4744,150 @@ const resolveBuildConfig = (config, schema) => {
4740
4744
  };
4741
4745
  };
4742
4746
  //#endregion
4747
+ //#region src/util/parse-resolve-info.ts
4748
+ /** Unwraps `[T]!`-style wrappers down to the named type. `getNamedType` without the realm tie. */
4749
+ const namedTypeOf = (type) => {
4750
+ let current = type;
4751
+ while (current?.ofType) current = current.ofType;
4752
+ return current;
4753
+ };
4754
+ /**
4755
+ * Whether a field's named output type has sub-selections. Object types and interfaces expose
4756
+ * `getFields`, unions expose `getTypes`; scalars and enums expose neither. Input object types
4757
+ * also expose `getFields`, but an input type can never be a field's output type, so there is
4758
+ * nothing here for that to collide with.
4759
+ */
4760
+ const isCompositeLike = (type) => !!type && (typeof type.getFields === "function" || typeof type.getTypes === "function");
4761
+ /**
4762
+ * The fields declared on a type, or `undefined` when it has none to declare. A union is the
4763
+ * case that matters: it has no fields of its own, so a selection directly against one resolves
4764
+ * to nothing and is dropped — only the inline fragments underneath contribute.
4765
+ */
4766
+ const fieldsOf = (type) => typeof type?.getFields === "function" ? type.getFields() : void 0;
4767
+ /**
4768
+ * The runtime variable values, in the plain-map form the directive check wants. graphql 17
4769
+ * wraps them in `{ sources, coerced }`; graphql 16 hands over the map itself.
4770
+ */
4771
+ const coercedVariables = (info) => {
4772
+ const values = info.variableValues;
4773
+ if (values && typeof values === "object" && "coerced" in values) return values.coerced ?? {};
4774
+ return values ?? {};
4775
+ };
4776
+ /** The value of a `@skip` / `@include` `if:` argument — a literal or a variable reference. */
4777
+ const directiveIfValue = (info, value) => {
4778
+ if (value.kind === Kind.VARIABLE) return coercedVariables(info)[value.name.value];
4779
+ if (value.kind === Kind.BOOLEAN) return value.value;
4780
+ };
4781
+ /**
4782
+ * Whether `@skip` / `@include` on this selection exclude it. Applies to fields, fragment
4783
+ * spreads and inline fragments alike, which is where graphql puts them.
4784
+ */
4785
+ const isExcluded = (info, node) => {
4786
+ for (const directive of node.directives ?? []) {
4787
+ const directiveName = directive.name.value;
4788
+ if (directiveName !== "skip" && directiveName !== "include") continue;
4789
+ const ifArgument = directive.arguments?.find((argument) => argument.name.value === "if");
4790
+ if (!ifArgument) continue;
4791
+ const value = directiveIfValue(info, ifArgument.value);
4792
+ if (directiveName === "skip" ? !!value : !value) return true;
4793
+ }
4794
+ return false;
4795
+ };
4796
+ /** The type a fragment's `on Type` condition names, looked up in the executing schema. */
4797
+ const typeFromCondition = (info, condition) => info.schema.getType(condition.name.value);
4798
+ /**
4799
+ * Introspection meta-fields are not schema fields and never reach the database. `__typename` is
4800
+ * the one that turns up in practice; `__id` is excluded from the rule because a schema is free
4801
+ * to declare a field by that name.
4802
+ */
4803
+ const isMetaField = (name) => name.startsWith("__") && name !== "__id";
4804
+ /**
4805
+ * Merges one selection set into `tree`, which is a `fieldsByTypeName` map — the caller owns the
4806
+ * level, this owns the entries under `parentType`'s name.
4807
+ *
4808
+ * `activeFragments` is the set of fragment names on the current spread path. A document that
4809
+ * passed validation cannot contain a fragment cycle, but this parser also runs on trees a
4810
+ * caller assembled by hand, and an unbounded walk would hang rather than fail.
4811
+ */
4812
+ const collectSelections = (selections, info, tree, parentType, deep, activeFragments) => {
4813
+ const parentTypeName = parentType?.name;
4814
+ if (!parentTypeName) return tree;
4815
+ let fields = tree[parentTypeName];
4816
+ if (!fields) {
4817
+ fields = {};
4818
+ tree[parentTypeName] = fields;
4819
+ }
4820
+ for (const selection of selections) {
4821
+ if (isExcluded(info, selection)) continue;
4822
+ if (selection.kind === Kind.FIELD) {
4823
+ const name = selection.name.value;
4824
+ if (isMetaField(name)) continue;
4825
+ const fieldDef = fieldsOf(parentType)?.[name];
4826
+ if (!fieldDef) continue;
4827
+ const fieldType = namedTypeOf(fieldDef.type);
4828
+ if (!fieldType) continue;
4829
+ const composite = isCompositeLike(fieldType);
4830
+ const alias = selection.alias?.value || name;
4831
+ let node = fields[alias];
4832
+ if (!node) {
4833
+ node = {
4834
+ name,
4835
+ alias,
4836
+ args: { ...getArgumentValues(fieldDef, selection, info.variableValues) },
4837
+ fieldsByTypeName: composite && fieldType.name ? { [fieldType.name]: {} } : {}
4838
+ };
4839
+ fields[alias] = node;
4840
+ }
4841
+ if (selection.selectionSet && deep && composite) collectSelections(selection.selectionSet.selections, info, node.fieldsByTypeName, fieldType, deep, activeFragments);
4842
+ continue;
4843
+ }
4844
+ if (!deep) continue;
4845
+ if (selection.kind === Kind.FRAGMENT_SPREAD) {
4846
+ const fragmentName = selection.name.value;
4847
+ const fragment = info.fragments?.[fragmentName];
4848
+ if (!fragment) throw new Error(`Drizzle-GraphQL Error: unknown fragment '${fragmentName}' — it is spread in the query but not defined in the document.`);
4849
+ if (activeFragments.has(fragmentName)) continue;
4850
+ const fragmentType = fragment.typeCondition ? typeFromCondition(info, fragment.typeCondition) : parentType;
4851
+ if (!isCompositeLike(fragmentType)) continue;
4852
+ activeFragments.add(fragmentName);
4853
+ try {
4854
+ collectSelections(fragment.selectionSet.selections, info, tree, fragmentType, deep, activeFragments);
4855
+ } finally {
4856
+ activeFragments.delete(fragmentName);
4857
+ }
4858
+ continue;
4859
+ }
4860
+ if (selection.kind === Kind.INLINE_FRAGMENT) {
4861
+ const fragmentType = selection.typeCondition ? typeFromCondition(info, selection.typeCondition) : parentType;
4862
+ if (!isCompositeLike(fragmentType)) continue;
4863
+ collectSelections(selection.selectionSet.selections, info, tree, fragmentType, deep, activeFragments);
4864
+ }
4865
+ }
4866
+ return tree;
4867
+ };
4868
+ const firstKey = (object) => Object.keys(object)[0];
4869
+ /**
4870
+ * Reads the selection under a resolver's own field out of its `info`, as a tree of
4871
+ * {@link ResolveTree} nodes.
4872
+ *
4873
+ * ```ts
4874
+ * const parsed = parseResolveInfo(info, { deep: true })!;
4875
+ * const selected = parsed.fieldsByTypeName['Users']; // keyed by response key
4876
+ * ```
4877
+ *
4878
+ * Returns `undefined` when the resolver's field produced no node at all, which in practice
4879
+ * means `info` carried no field nodes.
4880
+ */
4881
+ const parseResolveInfo = (info, options = {}) => {
4882
+ const fieldNodes = info.fieldNodes;
4883
+ if (!fieldNodes) throw new Error("Drizzle-GraphQL Error: resolve info carries no fieldNodes, so no selection could be read from it.");
4884
+ const tree = collectSelections(fieldNodes, info, {}, info.parentType, options.deep ?? true, /* @__PURE__ */ new Set());
4885
+ const typeKey = firstKey(tree);
4886
+ const fields = typeKey === void 0 ? void 0 : tree[typeKey];
4887
+ const fieldKey = fields && firstKey(fields);
4888
+ return fieldKey === void 0 ? void 0 : fields?.[fieldKey];
4889
+ };
4890
+ //#endregion
4743
4891
  //#region src/util/builders/aggregates.ts
4744
4892
  /** Operations that aggregate over a set of column values. `count` is handled separately (whole rows). */
4745
4893
  const AGGREGATE_OPS = [
@@ -7428,6 +7576,6 @@ const buildSchema = (db, config) => {
7428
7576
  };
7429
7577
  };
7430
7578
  //#endregion
7431
- export { GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, resolveSelection, selectionToWith, singularizeMapper };
7579
+ export { GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, parseResolveInfo, resolveSelection, selectionToWith, singularizeMapper };
7432
7580
 
7433
7581
  //# sourceMappingURL=index.js.map