Skip to content

chore: update dependency @graphql-tools/utils to v13 - #11864

Draft
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/major-graphql-tools-monorepo
Draft

renovate[bot] wants to merge 1 commit into
masterfrom
renovate/major-graphql-tools-monorepo

Conversation

@renovate

@renovate renovate Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
@graphql-tools/utils (source) ^12.0.4 → ^13.1.3 age adoption passing confidence

Release Notes

ardatan/graphql-tools (@​graphql-tools/utils)

v13.1.3

Compare Source

Patch Changes
  • #​8575 7fbc6e7 Thanks @​ardatan! - mapSchema now remaps directive argument defaults the same way it already remaps field argument defaults.

    Use case: UserRole is remapped to internal ids, and @auth defaults to USER.

    const schema = mapSchema(originalSchema, {
      [MapperKind.ENUM_VALUE]: (valueConfig, typeName, _schema, externalValue) => {
        if (typeName === 'UserRole' && externalValue === 'USER') {
          return { ...valueConfig, value: '3user' };
        }
        return valueConfig;
      },
    });
    
    // directive @auth(role: UserRole = USER)
    schema.getDirective('auth').args.find(arg => arg.name === 'role').defaultValue;
    // before: "USER"
    // after:  "3user"

    mapSchema serializes the stored default with the source type before parsing with the remapped type, so an internal value that matches another enum name (USER -> "ADMIN") stays "ADMIN" instead of being parsed as that name.

    forEachDefaultValue walks directive arguments too, so makeExecutableSchema enum resolvers get the same result.

  • #​8574 5ceed9d Thanks @​ardatan! - Published Executor types include /// <reference lib="esnext.disposable" preserve="true" /> so consumers do not need skipLibCheck or a full esnext lib just to import this package.

    Use case: an app with "lib": ["es2022"] or ["es2024"] and skipLibCheck: false that imports @graphql-tools/utils:

    import type { Executor } from '@graphql-tools/utils';
    
    export const executor: Executor = async request => {
      // ...
    };

    Executor can return a Disposable / AsyncIterable result. Those names live in TypeScript's esnext.disposable lib, which is not part of es2022/es2024. Without the preserved reference, tsc reports Cannot find name 'Disposable'. With it, the published .d.ts pulls in that lib for the consumer automatically.

v13.1.2

Compare Source

Patch Changes
  • #​8558 501109b Thanks @​ardatan! - printSchemaWithDirectives no longer turns unquoted directive argument literals into strings.

    In GraphQL SDL, an unquoted identifier in value position is an EnumValue AST node. A quoted value is a StringValue. Those are different kinds even when the argument type is a custom scalar rather than an enum type. parseLiteral on that scalar receives the original kind, so a custom scalar can treat argument_value and "argument_value" as different inputs.

    The printer was reconstructing directive arguments from JS values. valueFromASTUntyped maps both kinds to the same string, and astFromValue then emits a StringValue. The printed SDL became @directive(arg: "argument_value") even though the schema AST still had @directive(arg: argument_value).

    That is a round-trip / fidelity bug: loaders, schema diffs, snapshots, and subgraph publishes see different SDL, and a scalar that distinguishes the two kinds changes meaning. Default scalars coerce both to the same JS string, so many runtime paths do not notice.

    When the original AST is still the source of truth, printSchemaWithDirectives now keeps those directive argument nodes, including nested list and input-object values. If directive values are supplied only through extensions (code-first), JS strings are still printed as strings because the original kind is not available.

    Fixes #​8557

v13.1.1

Compare Source

Patch Changes
  • #​8552 f87bdf4 Thanks @​ardatan! - INCREMENTAL_DELIVERY_SPECS is the shared HTTP contract for incrementalSpec. Each row maps an Accept / Content-Type parameter (deferSpec=20220824, incrementalSpec=v0.2, ...) to the executor payload id ('v0.1' | 'v0.2').

    GraphQL Yoga, Hive Gateway, HTTP executors, and other servers should look up this table instead of hardcoding spec strings. When a later incremental spec ships, the work stays in graphql-tools: add a row here and an executor publisher. Consumers bump @graphql-tools/utils / @graphql-tools/executor. Accept negotiation, Content-Type echo, and 406 for unknown spec params keep working without a Yoga / Gateway / executor-http patch for the new identifier.

    Unknown values for a registered parameter name stay unsupported (HTTP 406). Helpers: lookupIncrementalDeliverySpec, getMultipartContentType, getDefaultIncrementalDeliverySpec, getIncrementalSpecParameterNames.

v13.1.0

Compare Source

Minor Changes
  • #​8550 4db5750 Thanks @​ardatan! - @graphql-tools/executor can publish both incremental delivery payload formats from one execution kernel. Pass incrementalSpec: 'v0.1' | 'v0.2' on execute / subscribe / normalizedExecutor (also on ExecutionRequest for executorFromSchema). 'v0.1' remains the default and keeps the existing path / label patches used with multipart/mixed;deferSpec=20220824. 'v0.2' emits Apollo incremental v0.2 payloads (pending with id and path, incremental with id and optional subPath, completed) used with multipart/mixed;incrementalSpec=v0.2.

    Field execution, @defer / @stream scheduling, and AbortSignal cancellation are shared. Spec-specific JSON is built by a publisher: v0.1 still yields { incremental, hasNext }; v0.2 assigns ids when a pending group is first announced, groups streamed items under one pending path, and reports completion separately. Nested @defer patches are collected as children of the parent patch so v0.2 can announce the inner fragment only after the parent is pending, without making the nested fragment wait on the parent's promise (v0.1 sibling completion is unchanged aside from incremental array order).

    Publisher state (Map / Set of ids) is allocated only for 'v0.2'. StreamGroup is created only for v0.2 and only when items are actually streamed. v0.2 stream completion uses an open-count on the group instead of scanning subsequentPayloads.

    mergeIncrementalResult still merges v0.1 path / items patches. For v0.2 it records pending ids on the execution result, writes deferred data at pending.path + subPath, appends streamed items onto the list at pending.path, and folds completed.errors into errors. visitResult flattens nested deferred patches so result visiting still sees fields that live under a child @defer.

v13.0.2

Compare Source

Patch Changes
  • #​8546 34b740b Thanks @​ardatan! - Add asGetArgumentValuesVariables and coerceGetVariableValuesResult helpers for GraphQL 16/17 VariableValues compatibility when calling getArgumentValues / normalizing getVariableValues results for helpers like shouldIncludeNode.

v13.0.1

Compare Source

Patch Changes
  • #​8540 15efe55 Thanks @​ardatan! - Align memoize4 third-level cache initialization with the let + reassignment pattern used by memoize3 / memoize5.

    Previously a nested const cache4 inside if (!cache4) shadowed the outer binding. Runtime behavior was already safe (that branch stores the map and returns), but the declaration was easy to misread and fragile if the early return were removed. The helper now assigns to the outer let cache4 instead, with regression tests for the third-level cache path.

v13.0.0

Compare Source

Major Changes
  • #​8515 1d70c62 Thanks @​ardatan! - Drop GraphQL v14/v15 support and require Node.js >= 22.18.

    • graphql peer range is now ^16.0.0 || ^17.0.0.
    • engines.node is now >=22.18.0 (Node fs.glob + Babel 8).
    • Dev tooling and @graphql-tools/graphql-tag-pluck move to Babel 8 (@babel/core / parser / traverse / types).
    • The standalone cross-inspect package is discontinued. Use inspect from @graphql-tools/utils instead (Node util.inspect via process.getBuiltinModule, with a small JSON.stringify / String fallback).
Removed @graphql-tools/utils exports
Removed Use instead
getArgumentValues import { getArgumentValues } from 'graphql'
coerceInputs / graphqlJSCompat graphql@​16+ APIs (getArgumentValues, etc.)
createDeferred / createDeferredPromise const { promise, resolve, reject } = Promise.withResolvers()
createGraphQLError new GraphQLError(message, options) from graphql
mapMaybePromise handleMaybePromise from @whatwg-node/promise-helpers
isPromise / fakePromise / mapAsyncIterator / MaybePromise @whatwg-node/promise-helpers
registerAbortSignalListener / getAbortPromise AbortSignal APIs (throwIfAborted, addEventListener('abort', …, { once: true }), AbortSignal.any, …)
withCancel / getAsyncIterableWithCancel / getAsyncIteratorWithCancel Handle cancellation on the async iterator’s return() (or your transport abort path)
debugTimerStart / debugTimerEnd Your own timing / console.time if needed
PromiseWithResolvers (type) Built-in PromiseWithResolvers<T> / return type of Promise.withResolvers()

inspect and the WeakMap memoize1…memoize2of5 helpers remain on @graphql-tools/utils (inspect is no longer re-exported from cross-inspect).

File matching (globby → fs.glob)

Loaders and @graphql-tools/load-files now use Node’s fs.glob through:

import { matchFiles, matchFilesSync } from '@graphql-tools/load-files';

Directory symlinks are followed for recursive (**) patterns:

  • On Node.js ≥26.1 (and ≥24.16 where backported), fs.glob followSymlinks is used.
  • On older engines, symlink directories are discovered only under each pattern’s literal prefix (not the whole cwd) and patterns are re-rooted.
  • Non-recursive / literal patterns skip the symlink walk entirely.

@graphql-tools/executor hot-path caches (collectSubfields, argument coercion, @stream detection) use memoize2 / memoize3 from utils. collectSubFields in utils stays unmemoized so the executor can own a single memoize3 layer.

Errors and other cleanup
  • Prefer new GraphQLError(message, options) from graphql. Experimental schema coordinate support remains on locatedError / relocatedError / getSchemaCoordinate.
  • Removed GraphQL versions older than 16 compatibility branches (error construction, validation rule name suffixes, URL.canParse fallback).
  • Promise helpers should be imported from @whatwg-node/promise-helpers (handleMaybePromise, isPromise, fakePromise, mapAsyncIterator, MaybePromise) rather than re-exported from utils.
Patch Changes

v12.1.0

Compare Source

Minor Changes
  • #​8445 82457d1 Thanks @​ardatan! - Fix: Preserve symbol-keyed GraphQL extensions when building, merging, or extracting schemas.

    GraphQL.js v17 allows string | symbol keys on schema/type/field extensions (via toObjMapWithSymbols). @graphql-tools was dropping those symbol keys in two places:

    1. mergeDeep only walked enumerable string keys (for...in), so symbol extensions were lost when applying schemaExtensions.
    2. extractExtensionsFromSchema did not copy non-enumerable own symbol keys (enumerable symbols already survive object rest/spread; the explicit loop covers the non-enumerable case).
Example (bug)
import { makeExecutableSchema } from '@graphql-tools/schema'

const META = Symbol('META')

const schema = makeExecutableSchema({
  typeDefs: /* GraphQL */ `
    type Query {
      hello: String
    }
  `,
  schemaExtensions: {
    schemaExtensions: {
      [META]: { source: 'app' },
      tagged: true,
    },
    types: {},
  },
})

// Before: only string keys survived
// schema.extensions === { tagged: true }

// After: symbol keys are preserved
// schema.extensions[META] === { source: 'app' }
// schema.extensions.tagged === true

Schema extension merge/extract and resolver merging always enable { enumerable: true, nonEnumerable: true } so symbol keys survive in tools' own merge/extract paths on every supported GraphQL.js major. (GraphQL.js itself may still drop symbol keys from field configs below v17 when rebuilding types.)

mergeDeep API

mergeDeep now accepts an options object. The old positional boolean arguments still work but are deprecated.

import { mergeDeep } from '@graphql-tools/utils'

// Deprecated (still supported)
mergeDeep([a, b], false, true, false, true)
//                ^proto ^arrays ^len  ^non-enumerable symbols only

// Preferred
mergeDeep([a, b], {
  respectPrototype: false,
  respectArrays: true,
  respectArrayLength: false,
  respectSymbols: {
    enumerable: true, // merge `obj[sym] = value` keys
    nonEnumerable: true, // copy defineProperty(..., { enumerable: false }) symbols
  },
})

respectSymbols defaults to { enumerable: false, nonEnumerable: false } (symbols dropped), matching the historical default. The legacy 5th positional flag still maps to { nonEnumerable: true } only.

Resolver map types (IResolvers / field resolver extensions and type __extensions) now use ExtensionsObject (Record<string | symbol, any>), so symbol-keyed resolver extensions type-check under GraphQL.js v17+.

Patch Changes
  • #​8513 98673c3 Thanks @​ardatan! - fix(utils): coerce GraphQL 17 argument defaults in getArgumentValues via local input coercion (defaults, missing variables, nested sources)

  • #​8493 a75d725 Thanks @​cpruijsen! - Keep argument types of defined directives when pruning so that unused directives such as @key(fields: _FieldSet!) retain their full definitions instead of losing the argument together with its type.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate renovate Bot added the dependencies Pull requests that update a dependency file label Oct 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants