UNPKG

@apollo/client

Version:

A fully-featured caching GraphQL client.

150 lines 4.96 kB
import { WeakCache } from "@wry/caches"; import { Kind, visit } from "graphql"; import { wrap } from "optimism"; import { ApolloLink } from "@apollo/client/link"; import { cacheSizes, stripTypename } from "@apollo/client/utilities"; import { __DEV__ } from "@apollo/client/utilities/environment"; import { isPlainObject } from "@apollo/client/utilities/internal"; /** * Sentinel value used to indicate that `__typename` fields should be kept * for a specific field or input type. * * @remarks * Use this value in the `except` configuration to preserve `__typename` * fields in JSON scalar fields or other cases where you need to retain * the typename information. * * @example * * ```ts * import { * RemoveTypenameFromVariablesLink, * KEEP, * } from "@apollo/client/link/remove-typename"; * * const link = new RemoveTypenameFromVariablesLink({ * except: { * JSON: KEEP, // Keep __typename for all JSON scalar variables * DashboardInput: { * config: KEEP, // Keep __typename only for the config field * }, * }, * }); * ``` */ export const KEEP = "__KEEP"; /** * @deprecated * Use `RemoveTypenameFromVariablesLink` from `@apollo/client/link/remove-typename` instead. */ export function removeTypenameFromVariables(options) { return new RemoveTypenameFromVariablesLink(options); } /** * `RemoveTypenameFromVariablesLink` is a non-terminating link that automatically * removes `__typename` fields from operation variables to prevent GraphQL * validation errors. * * @remarks * * When reusing data from a query as input to another GraphQL operation, * `__typename` fields can cause server-side validation errors because input * types don't accept fields that start with double underscores (`__`). * `RemoveTypenameFromVariablesLink` automatically strips these fields from all * operation variables. * * @example * * ```ts * import { RemoveTypenameFromVariablesLink } from "@apollo/client/link/remove-typename"; * * const link = new RemoveTypenameFromVariablesLink(); * ``` */ export class RemoveTypenameFromVariablesLink extends ApolloLink { constructor(options = {}) { super((operation, forward) => { const { except } = options; const { query, variables } = operation; if (variables) { operation.variables = except ? maybeStripTypenameUsingConfig(query, variables, except) : stripTypename(variables); } return forward(operation); }); return Object.assign(this, __DEV__ ? { getMemoryInternals() { return { removeTypenameFromVariables: { getVariableDefinitions: getVariableDefinitions?.size ?? 0, }, }; }, } : {}); } } function maybeStripTypenameUsingConfig(query, variables, config) { const variableDefinitions = getVariableDefinitions(query); return Object.fromEntries(Object.entries(variables).map((keyVal) => { const [key, value] = keyVal; const typename = variableDefinitions[key]; const typenameConfig = config[typename]; keyVal[1] = typenameConfig ? maybeStripTypename(value, typenameConfig) : stripTypename(value); return keyVal; })); } function maybeStripTypename(value, config) { if (config === KEEP) { return value; } if (Array.isArray(value)) { return value.map((item) => maybeStripTypename(item, config)); } if (isPlainObject(value)) { const modified = {}; Object.keys(value).forEach((key) => { const child = value[key]; if (key === "__typename") { return; } const fieldConfig = config[key]; modified[key] = fieldConfig ? maybeStripTypename(child, fieldConfig) : stripTypename(child); }); return modified; } return value; } const getVariableDefinitions = wrap((document) => { const definitions = {}; visit(document, { VariableDefinition(node) { definitions[node.variable.name.value] = unwrapType(node.type); }, }); return definitions; }, { max: cacheSizes["removeTypenameFromVariables.getVariableDefinitions"] || 2000 /* defaultCacheSizes["removeTypenameFromVariables.getVariableDefinitions"] */, cache: WeakCache, }); function unwrapType(node) { switch (node.kind) { case Kind.NON_NULL_TYPE: return unwrapType(node.type); case Kind.LIST_TYPE: return unwrapType(node.type); case Kind.NAMED_TYPE: return node.name.value; } } //# sourceMappingURL=removeTypenameFromVariables.js.map