Socket
Socket
Sign inDemoInstall

graphql

Package Overview
Dependencies
Maintainers
7
Versions
259
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql - npm Package Compare versions

Comparing version 17.0.0-alpha.1.canary.pr.3673.53c289997f206acd10388d6a574341c68cc1a30e to 17.0.0-alpha.1.canary.pr.3703.9360805de6310b453b76a53431f921b44a76c2f9

execution/flattenAsyncIterable.d.ts

2

error/GraphQLError.d.ts

@@ -18,3 +18,3 @@ import type { Maybe } from '../jsutils/Maybe';

export interface GraphQLErrorOptions {
nodes?: ReadonlyArray<ASTNode> | ASTNode | null;
nodes?: ReadonlyArray<ASTNode> | ASTNode | null | undefined;
source?: Maybe<Source>;

@@ -21,0 +21,0 @@ positions?: Maybe<ReadonlyArray<number>>;

@@ -9,2 +9,10 @@ import type { ObjMap } from '../jsutils/ObjMap';

import type { GraphQLSchema } from '../type/schema';
export interface PatchFields {
label: string | undefined;
fields: Map<string, ReadonlyArray<FieldNode>>;
}
export interface FieldsAndPatches {
fields: Map<string, ReadonlyArray<FieldNode>>;
patches: Array<PatchFields>;
}
/**

@@ -27,3 +35,3 @@ * Given a selectionSet, collects all of the fields and returns them.

selectionSet: SelectionSetNode,
): Map<string, ReadonlyArray<FieldNode>>;
): FieldsAndPatches;
/**

@@ -47,2 +55,2 @@ * Given an array of field nodes, collects all of the subfields of the passed

fieldNodes: ReadonlyArray<FieldNode>,
): Map<string, ReadonlyArray<FieldNode>>;
): FieldsAndPatches;

@@ -5,2 +5,3 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js';

import {
GraphQLDeferDirective,
GraphQLIncludeDirective,

@@ -28,2 +29,3 @@ GraphQLSkipDirective,

const fields = new AccumulatorMap();
const patches = [];
collectFieldsImpl(

@@ -36,5 +38,6 @@ schema,

fields,
patches,
new Set(),
);
return fields;
return { fields, patches };
}

@@ -60,2 +63,7 @@ /**

const visitedFragmentNames = new Set();
const subPatches = [];
const subFieldsAndPatches = {
fields: subFieldNodes,
patches: subPatches,
};
for (const node of fieldNodes) {

@@ -70,2 +78,3 @@ if (node.selectionSet) {

subFieldNodes,
subPatches,
visitedFragmentNames,

@@ -75,3 +84,3 @@ );

}
return subFieldNodes;
return subFieldsAndPatches;
}

@@ -86,2 +95,3 @@ // eslint-disable-next-line max-params

fields,
patches,
visitedFragmentNames,

@@ -105,11 +115,31 @@ ) {

}
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
fields,
visitedFragmentNames,
);
const defer = getDeferValues(variableValues, selection);
if (defer) {
const patchFields = new AccumulatorMap();
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
patchFields,
patches,
visitedFragmentNames,
);
patches.push({
label: defer.label,
fields: patchFields,
});
} else {
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
fields,
patches,
visitedFragmentNames,
);
}
break;

@@ -119,9 +149,9 @@ }

const fragName = selection.name.value;
if (
visitedFragmentNames.has(fragName) ||
!shouldIncludeNode(variableValues, selection)
) {
if (!shouldIncludeNode(variableValues, selection)) {
continue;
}
visitedFragmentNames.add(fragName);
const defer = getDeferValues(variableValues, selection);
if (visitedFragmentNames.has(fragName) && !defer) {
continue;
}
const fragment = fragments[fragName];

@@ -134,11 +164,33 @@ if (

}
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
fields,
visitedFragmentNames,
);
if (!defer) {
visitedFragmentNames.add(fragName);
}
if (defer) {
const patchFields = new AccumulatorMap();
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
patchFields,
patches,
visitedFragmentNames,
);
patches.push({
label: defer.label,
fields: patchFields,
});
} else {
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
fields,
patches,
visitedFragmentNames,
);
}
break;

@@ -150,2 +202,19 @@ }

/**
* Returns an object containing the `@defer` arguments if a field should be
* deferred based on the experimental flag, defer directive present and
* not disabled by the "if" argument.
*/
function getDeferValues(variableValues, node) {
const defer = getDirectiveValues(GraphQLDeferDirective, node, variableValues);
if (!defer) {
return;
}
if (defer.if === false) {
return;
}
return {
label: typeof defer.label === 'string' ? defer.label : undefined,
};
}
/**
* Determines if a field should be included based on the `@include` and `@skip`

@@ -152,0 +221,0 @@ * directives, where `@skip` has higher precedence than `@include`.

@@ -59,2 +59,3 @@ import type { Maybe } from '../jsutils/Maybe';

errors: Array<GraphQLError>;
subsequentPayloads: Array<AsyncPayloadRecord>;
}

@@ -66,3 +67,5 @@ /**

* - `data` is the result of a successful execution of the query.
* - `hasNext` is true if a future payload is expected.
* - `extensions` is reserved for adding non-standard properties.
* - `incremental` is a list of the results from defer/stream directives.
*/

@@ -85,2 +88,95 @@ export interface ExecutionResult<

}
export declare type ExperimentalExecuteIncrementallyResults<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> =
| {
singleResult: ExecutionResult<TData, TExtensions>;
}
| {
initialResult: InitialIncrementalExecutionResult<TData, TExtensions>;
subsequentResults: AsyncGenerator<
SubsequentIncrementalExecutionResult<TData, TExtensions>,
void,
void
>;
};
export interface InitialIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends ExecutionResult<TData, TExtensions> {
hasNext: boolean;
incremental?: ReadonlyArray<IncrementalResult<TData, TExtensions>>;
extensions?: TExtensions;
}
export interface FormattedInitialIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends FormattedExecutionResult<TData, TExtensions> {
hasNext: boolean;
incremental?: ReadonlyArray<FormattedIncrementalResult<TData, TExtensions>>;
extensions?: TExtensions;
}
export interface SubsequentIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> {
hasNext: boolean;
incremental?: ReadonlyArray<IncrementalResult<TData, TExtensions>>;
extensions?: TExtensions;
}
export interface FormattedSubsequentIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> {
hasNext: boolean;
incremental?: ReadonlyArray<FormattedIncrementalResult<TData, TExtensions>>;
extensions?: TExtensions;
}
export interface IncrementalDeferResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends ExecutionResult<TData, TExtensions> {
path?: ReadonlyArray<string | number>;
label?: string;
}
export interface FormattedIncrementalDeferResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends FormattedExecutionResult<TData, TExtensions> {
path?: ReadonlyArray<string | number>;
label?: string;
}
export interface IncrementalStreamResult<
TData = Array<unknown>,
TExtensions = ObjMap<unknown>,
> {
errors?: ReadonlyArray<GraphQLError>;
items?: TData | null;
path?: ReadonlyArray<string | number>;
label?: string;
extensions?: TExtensions;
}
export interface FormattedIncrementalStreamResult<
TData = Array<unknown>,
TExtensions = ObjMap<unknown>,
> {
errors?: ReadonlyArray<GraphQLFormattedError>;
items?: TData | null;
path?: ReadonlyArray<string | number>;
label?: string;
extensions?: TExtensions;
}
export declare type IncrementalResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> =
| IncrementalDeferResult<TData, TExtensions>
| IncrementalStreamResult<TData, TExtensions>;
export declare type FormattedIncrementalResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> =
| FormattedIncrementalDeferResult<TData, TExtensions>
| FormattedIncrementalStreamResult<TData, TExtensions>;
export interface ExecutionArgs {

@@ -108,2 +204,7 @@ schema: GraphQLSchema;

* a GraphQLError will be thrown immediately explaining the invalid input.
*
* This function does not support incremental delivery (`@defer` and `@stream`).
* If an operation which would defer or stream data is executed with this function,
* it will throw or reject instead. Use `experimentalExecuteIncrementally` if you
* want to support incremental delivery.
*/

@@ -114,2 +215,17 @@ export declare function execute(

/**
* Implements the "Executing requests" section of the GraphQL specification,
* including `@defer` and `@stream` as proposed in
* https://github.com/graphql/graphql-spec/pull/742
*
* This function returns a Promise of an ExperimentalExecuteIncrementallyResults
* object. This object either contains a single ExecutionResult as
* `singleResult`, or an `initialResult` and a stream of `subsequentResults`.
*
* If the arguments to this function do not result in a legal execution context,
* a GraphQLError will be thrown immediately explaining the invalid input.
*/
export declare function experimentalExecuteIncrementally(
args: ExecutionArgs,
): Promise<ExperimentalExecuteIncrementallyResults>;
/**
* Also implements the "Executing requests" section of the GraphQL specification.

@@ -188,3 +304,10 @@ * However, it guarantees to complete synchronously (or throw an error) assuming

): PromiseOrValue<
AsyncGenerator<ExecutionResult, void, void> | ExecutionResult
| AsyncGenerator<
| ExecutionResult
| InitialIncrementalExecutionResult
| SubsequentIncrementalExecutionResult,
void,
void
>
| ExecutionResult
>;

@@ -222,1 +345,37 @@ /**

): PromiseOrValue<AsyncIterable<unknown> | ExecutionResult>;
declare class DeferredFragmentRecord {
type: 'defer';
errors: Array<GraphQLError>;
label: string | undefined;
path: Path | undefined;
data: PromiseOrValue<ObjMap<unknown> | null> | null;
parentContext: AsyncPayloadRecord | undefined;
constructor(opts: {
label: string | undefined;
path: Path | undefined;
parentContext: AsyncPayloadRecord | undefined;
});
addData(data: PromiseOrValue<ObjMap<unknown> | null>): void;
getData(): PromiseOrValue<ObjMap<unknown> | null>;
}
declare class StreamRecord {
type: 'stream';
errors: Array<GraphQLError>;
label: string | undefined;
path: Path | undefined;
items: PromiseOrValue<Array<unknown> | null>;
parentContext: AsyncPayloadRecord | undefined;
iterator: AsyncIterator<unknown> | undefined;
isCompletedIterator?: boolean;
constructor(opts: {
label: string | undefined;
path: Path | undefined;
iterator?: AsyncIterator<unknown>;
parentContext: AsyncPayloadRecord | undefined;
});
addItems(items: PromiseOrValue<Array<unknown> | null>): void;
getData(): PromiseOrValue<Array<unknown> | null>;
setIsCompletedIterator(): void;
}
declare type AsyncPayloadRecord = DeferredFragmentRecord | StreamRecord;
export {};

@@ -22,2 +22,3 @@ import { inspect } from '../jsutils/inspect.js';

} from '../type/definition.js';
import { GraphQLStreamDirective } from '../type/directives.js';
import { assertValidSchema } from '../type/validate.js';

@@ -28,4 +29,9 @@ import {

} from './collectFields.js';
import { mapAsyncIterator } from './mapAsyncIterator.js';
import { getArgumentValues, getVariableValues } from './values.js';
import { flattenAsyncIterable } from './flattenAsyncIterable.js';
import { mapAsyncIterable } from './mapAsyncIterable.js';
import {
getArgumentValues,
getDirectiveValues,
getVariableValues,
} from './values.js';
/* eslint-disable max-params */

@@ -57,4 +63,47 @@ // This file contains a lot of such errors but we plan to refactor it anyway

* a GraphQLError will be thrown immediately explaining the invalid input.
*
* This function does not support incremental delivery (`@defer` and `@stream`).
* If an operation which would defer or stream data is executed with this function,
* it will throw or reject instead. Use `experimentalExecuteIncrementally` if you
* want to support incremental delivery.
*/
export function execute(args) {
const result = executeSyncOrIncrementally(args);
if (!isPromise(result)) {
return result;
}
return result.then((incrementalResult) => {
if ('singleResult' in incrementalResult) {
return incrementalResult.singleResult;
}
throw new GraphQLError(
'Executing this GraphQL operation would unexpectedly produce multiple payloads (due to @defer or @stream directive)',
);
});
}
/**
* Implements the "Executing requests" section of the GraphQL specification,
* including `@defer` and `@stream` as proposed in
* https://github.com/graphql/graphql-spec/pull/742
*
* This function returns a Promise of an ExperimentalExecuteIncrementallyResults
* object. This object either contains a single ExecutionResult as
* `singleResult`, or an `initialResult` and a stream of `subsequentResults`.
*
* If the arguments to this function do not result in a legal execution context,
* a GraphQLError will be thrown immediately explaining the invalid input.
*/
export function experimentalExecuteIncrementally(args) {
const result = executeSyncOrIncrementally(args);
if (isPromise(result)) {
return result;
}
// Always return a Promise for a consistent API.
return Promise.resolve({ singleResult: result });
}
/**
* Helper for the other execute functions. Returns an ExecutionResult
* synchronously if all resolvers return non-Promises
*/
function executeSyncOrIncrementally(args) {
// If a valid execution context cannot be created due to incorrect arguments,

@@ -85,10 +134,32 @@ // a "Response" with only errors is returned.

return result.then(
(data) => buildResponse(data, exeContext.errors),
(data) => {
const initialResult = buildResponse(data, exeContext.errors);
if (exeContext.subsequentPayloads.length > 0) {
return {
initialResult: {
...initialResult,
hasNext: true,
},
subsequentResults: yieldSubsequentPayloads(exeContext),
};
}
return { singleResult: initialResult };
},
(error) => {
exeContext.errors.push(error);
return buildResponse(null, exeContext.errors);
return { singleResult: buildResponse(null, exeContext.errors) };
},
);
}
return buildResponse(result, exeContext.errors);
const initialResult = buildResponse(result, exeContext.errors);
if (exeContext.subsequentPayloads.length > 0) {
return Promise.resolve({
initialResult: {
...initialResult,
hasNext: true,
},
subsequentResults: yieldSubsequentPayloads(exeContext),
});
}
return initialResult;
} catch (error) {

@@ -195,2 +266,3 @@ exeContext.errors.push(error);

subscribeFieldResolver: subscribeFieldResolver ?? defaultFieldResolver,
subsequentPayloads: [],
errors: [],

@@ -219,3 +291,3 @@ };

}
const rootFields = collectFields(
const { fields: rootFields, patches } = collectFields(
schema,

@@ -228,7 +300,9 @@ fragments,

const path = undefined;
let result;
switch (operation.operation) {
case OperationTypeNode.QUERY:
return executeFields(exeContext, rootType, rootValue, path, rootFields);
result = executeFields(exeContext, rootType, rootValue, path, rootFields);
break;
case OperationTypeNode.MUTATION:
return executeFieldsSerially(
result = executeFieldsSerially(
exeContext,

@@ -240,7 +314,20 @@ rootType,

);
break;
case OperationTypeNode.SUBSCRIPTION:
// TODO: deprecate `subscribe` and move all logic here
// Temporary solution until we finish merging execute and subscribe together
return executeFields(exeContext, rootType, rootValue, path, rootFields);
result = executeFields(exeContext, rootType, rootValue, path, rootFields);
}
for (const patch of patches) {
const { label, fields: patchFields } = patch;
executeDeferredFragment(
exeContext,
rootType,
rootValue,
patchFields,
label,
path,
);
}
return result;
}

@@ -259,3 +346,3 @@ /**

return promiseReduce(
fields.entries(),
fields,
(results, [responseName, fieldNodes]) => {

@@ -289,6 +376,13 @@ const fieldPath = addPath(path, responseName, parentType.name);

*/
function executeFields(exeContext, parentType, sourceValue, path, fields) {
function executeFields(
exeContext,
parentType,
sourceValue,
path,
fields,
asyncPayloadRecord,
) {
const results = Object.create(null);
let containsPromise = false;
for (const [responseName, fieldNodes] of fields.entries()) {
for (const [responseName, fieldNodes] of fields) {
const fieldPath = addPath(path, responseName, parentType.name);

@@ -301,2 +395,3 @@ const result = executeField(

fieldPath,
asyncPayloadRecord,
);

@@ -325,3 +420,11 @@ if (result !== undefined) {

*/
function executeField(exeContext, parentType, source, fieldNodes, path) {
function executeField(
exeContext,
parentType,
source,
fieldNodes,
path,
asyncPayloadRecord,
) {
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
const fieldName = fieldNodes[0].name.value;

@@ -359,3 +462,11 @@ const fieldDef = exeContext.schema.getField(parentType, fieldName);

completed = result.then((resolved) =>
completeValue(exeContext, returnType, fieldNodes, info, path, resolved),
completeValue(
exeContext,
returnType,
fieldNodes,
info,
path,
resolved,
asyncPayloadRecord,
),
);

@@ -370,2 +481,3 @@ } else {

result,
asyncPayloadRecord,
);

@@ -378,3 +490,3 @@ }

const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, returnType, exeContext);
return handleFieldError(error, returnType, errors);
});

@@ -385,3 +497,3 @@ }

const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, returnType, exeContext);
return handleFieldError(error, returnType, errors);
}

@@ -415,3 +527,3 @@ }

}
function handleFieldError(error, returnType, exeContext) {
function handleFieldError(error, returnType, errors) {
// If the field type is non-nullable, then it is resolved without any

@@ -424,3 +536,3 @@ // protection from errors, however it still properly locates the error.

// a null value for this field if one is encountered.
exeContext.errors.push(error);
errors.push(error);
return null;

@@ -449,3 +561,11 @@ }

*/
function completeValue(exeContext, returnType, fieldNodes, info, path, result) {
function completeValue(
exeContext,
returnType,
fieldNodes,
info,
path,
result,
asyncPayloadRecord,
) {
// If result is an Error, throw a located error.

@@ -465,2 +585,3 @@ if (result instanceof Error) {

result,
asyncPayloadRecord,
);

@@ -487,2 +608,3 @@ if (completed === null) {

result,
asyncPayloadRecord,
);

@@ -505,2 +627,3 @@ }

result,
asyncPayloadRecord,
);

@@ -517,2 +640,3 @@ }

result,
asyncPayloadRecord,
);

@@ -529,2 +653,34 @@ }

/**
* Returns an object containing the `@stream` arguments if a field should be
* streamed based on the experimental flag, stream directive present and
* not disabled by the "if" argument.
*/
function getStreamValues(exeContext, fieldNodes, path) {
// do not stream inner lists of multi-dimensional lists
if (typeof path.key === 'number') {
return;
}
// validation only allows equivalent streams on multiple fields, so it is
// safe to only check the first fieldNode for the stream directive
const stream = getDirectiveValues(
GraphQLStreamDirective,
fieldNodes[0],
exeContext.variableValues,
);
if (!stream) {
return;
}
if (stream.if === false) {
return;
}
typeof stream.initialCount === 'number' ||
invariant(false, 'initialCount must be a number');
stream.initialCount >= 0 ||
invariant(false, 'initialCount must be a positive integer');
return {
initialCount: stream.initialCount,
label: typeof stream.label === 'string' ? stream.label : undefined,
};
}
/**
* Complete a async iterator value by completing the result and calling

@@ -540,3 +696,6 @@ * recursively until all the results are completed.

iterator,
asyncPayloadRecord,
) {
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
const stream = getStreamValues(exeContext, fieldNodes, path);
let containsPromise = false;

@@ -547,2 +706,21 @@ const completedResults = [];

while (true) {
if (
stream &&
typeof stream.initialCount === 'number' &&
index >= stream.initialCount
) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
executeStreamIterator(
index,
iterator,
exeContext,
fieldNodes,
info,
itemType,
path,
stream.label,
asyncPayloadRecord,
);
break;
}
const fieldPath = addPath(path, index, undefined);

@@ -564,2 +742,3 @@ try {

value,
asyncPayloadRecord,
);

@@ -577,3 +756,3 @@ if (isPromise(completedItem)) {

);
handleFieldError(error, itemType, exeContext);
handleFieldError(error, itemType, errors);
}

@@ -583,3 +762,3 @@ } catch (rawError) {

const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
handleFieldError(error, itemType, exeContext);
handleFieldError(error, itemType, errors);
break;

@@ -602,4 +781,6 @@ }

result,
asyncPayloadRecord,
) {
const itemType = returnType.ofType;
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
if (isAsyncIterable(result)) {

@@ -614,2 +795,3 @@ const iterator = result[Symbol.asyncIterator]();

iterator,
asyncPayloadRecord,
);

@@ -622,6 +804,10 @@ }

}
const stream = getStreamValues(exeContext, fieldNodes, path);
// This is specified as a simple map, however we're optimizing the path
// where the list contains no Promises by avoiding creating another Promise.
let containsPromise = false;
const completedResults = Array.from(result, (item, index) => {
let previousAsyncPayloadRecord = asyncPayloadRecord;
const completedResults = [];
let index = 0;
for (const item of result) {
// No need to modify the info object containing the path,

@@ -632,2 +818,20 @@ // since from here on it is not ever accessed by resolver functions.

let completedItem;
if (
stream &&
typeof stream.initialCount === 'number' &&
index >= stream.initialCount
) {
previousAsyncPayloadRecord = executeStreamField(
itemPath,
item,
exeContext,
fieldNodes,
info,
itemType,
stream.label,
previousAsyncPayloadRecord,
);
index++;
continue;
}
if (isPromise(item)) {

@@ -642,2 +846,3 @@ completedItem = item.then((resolved) =>

resolved,
asyncPayloadRecord,
),

@@ -653,2 +858,3 @@ );

item,
asyncPayloadRecord,
);

@@ -660,17 +866,21 @@ }

// to take a second callback for the error case.
return completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(itemPath),
);
return handleFieldError(error, itemType, exeContext);
});
completedResults.push(
completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(itemPath),
);
return handleFieldError(error, itemType, errors);
}),
);
} else {
completedResults.push(completedItem);
}
return completedItem;
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(itemPath));
return handleFieldError(error, itemType, exeContext);
completedResults.push(handleFieldError(error, itemType, errors));
}
});
index++;
}
return containsPromise ? Promise.all(completedResults) : completedResults;

@@ -703,2 +913,3 @@ }

result,
asyncPayloadRecord,
) {

@@ -724,2 +935,3 @@ const resolveTypeFn = returnType.resolveType ?? exeContext.typeResolver;

result,
asyncPayloadRecord,
),

@@ -742,2 +954,3 @@ );

result,
asyncPayloadRecord,
);

@@ -803,5 +1016,4 @@ }

result,
asyncPayloadRecord,
) {
// Collect sub-fields to execute to complete this value.
const subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes);
// If there is an isTypeOf predicate function, call it with the

@@ -817,8 +1029,9 @@ // current result. If isTypeOf returns false, then raise an error rather

}
return executeFields(
return collectAndExecuteSubfields(
exeContext,
returnType,
fieldNodes,
path,
result,
path,
subFieldNodes,
asyncPayloadRecord,
);

@@ -831,3 +1044,10 @@ });

}
return executeFields(exeContext, returnType, result, path, subFieldNodes);
return collectAndExecuteSubfields(
exeContext,
returnType,
fieldNodes,
path,
result,
asyncPayloadRecord,
);
}

@@ -840,2 +1060,38 @@ function invalidReturnTypeError(returnType, result, fieldNodes) {

}
function collectAndExecuteSubfields(
exeContext,
returnType,
fieldNodes,
path,
result,
asyncPayloadRecord,
) {
// Collect sub-fields to execute to complete this value.
const { fields: subFieldNodes, patches: subPatches } = collectSubfields(
exeContext,
returnType,
fieldNodes,
);
const subFields = executeFields(
exeContext,
returnType,
result,
path,
subFieldNodes,
asyncPayloadRecord,
);
for (const subPatch of subPatches) {
const { label, fields: subPatchFieldNodes } = subPatch;
executeDeferredFragment(
exeContext,
returnType,
result,
subPatchFieldNodes,
label,
path,
asyncPayloadRecord,
);
}
return subFields;
}
/**

@@ -943,2 +1199,17 @@ * If a resolveType function is not given, then a default resolve behavior is

}
async function* ensureAsyncIterable(someExecutionResult) {
if ('initialResult' in someExecutionResult) {
yield someExecutionResult.initialResult;
yield* someExecutionResult.subsequentResults;
} else if ('singleResult' in someExecutionResult) {
yield someExecutionResult.singleResult;
/* c8 ignore start */
// For some reason, c8 says that this function has complete statement
// coverage but that this `else` isn't branch-covered. Seems like a bug.
// And these comments have to be c8-ignored too!
} else {
/* c8 ignore stop */
yield someExecutionResult;
}
}
function mapSourceToResponse(exeContext, resultOrStream) {

@@ -954,4 +1225,8 @@ if (!isAsyncIterable(resultOrStream)) {

// "ExecuteQuery" algorithm, for which `execute` is also used.
return mapAsyncIterator(resultOrStream, (payload) =>
executeImpl(buildPerEventExecutionContext(exeContext, payload)),
return flattenAsyncIterable(
mapAsyncIterable(resultOrStream, async (payload) =>
ensureAsyncIterable(
await executeImpl(buildPerEventExecutionContext(exeContext, payload)),
),
),
);

@@ -1018,3 +1293,3 @@ }

}
const rootFields = collectFields(
const { fields: rootFields } = collectFields(
schema,

@@ -1026,3 +1301,4 @@ fragments,

);
const [responseName, fieldNodes] = [...rootFields.entries()][0];
const firstRootField = rootFields.entries().next().value;
const [responseName, fieldNodes] = firstRootField;
const fieldName = fieldNodes[0].name.value;

@@ -1081,1 +1357,371 @@ const fieldDef = schema.getField(rootType, fieldName);

}
function executeDeferredFragment(
exeContext,
parentType,
sourceValue,
fields,
label,
path,
parentContext,
) {
const asyncPayloadRecord = new DeferredFragmentRecord({
label,
path,
parentContext,
});
let promiseOrData;
try {
promiseOrData = executeFields(
exeContext,
parentType,
sourceValue,
path,
fields,
asyncPayloadRecord,
);
if (isPromise(promiseOrData)) {
promiseOrData = promiseOrData.then(null, (e) => {
asyncPayloadRecord.errors.push(e);
return null;
});
}
} catch (e) {
asyncPayloadRecord.errors.push(e);
promiseOrData = null;
}
asyncPayloadRecord.addData(promiseOrData);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
}
function executeStreamField(
path,
item,
exeContext,
fieldNodes,
info,
itemType,
label,
parentContext,
) {
const asyncPayloadRecord = new StreamRecord({
label,
path,
parentContext,
});
let completedItem;
let completedItems;
try {
try {
if (isPromise(item)) {
completedItem = item.then((resolved) =>
completeValue(
exeContext,
itemType,
fieldNodes,
info,
path,
resolved,
asyncPayloadRecord,
),
);
} else {
completedItem = completeValue(
exeContext,
itemType,
fieldNodes,
info,
path,
item,
asyncPayloadRecord,
);
}
if (isPromise(completedItem)) {
// Note: we don't rely on a `catch` method, but we do expect "thenable"
// to take a second callback for the error case.
completedItem = completedItem.then(undefined, (rawError) => {
const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, itemType, asyncPayloadRecord.errors);
});
}
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(path));
completedItems = handleFieldError(
error,
itemType,
asyncPayloadRecord.errors,
);
}
} catch (error) {
asyncPayloadRecord.errors.push(error);
asyncPayloadRecord.addItems(null);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
return asyncPayloadRecord;
}
if (isPromise(completedItem)) {
completedItems = completedItem.then(
(value) => [value],
(error) => {
asyncPayloadRecord.errors.push(error);
return null;
},
);
} else {
completedItems = [completedItem];
}
asyncPayloadRecord.addItems(completedItems);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
return asyncPayloadRecord;
}
async function executeStreamIteratorItem(
iterator,
exeContext,
fieldNodes,
info,
itemType,
asyncPayloadRecord,
fieldPath,
) {
let item;
try {
const { value, done } = await iterator.next();
if (done) {
asyncPayloadRecord.setIsCompletedIterator();
return { done, value: undefined };
}
item = value;
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
// don't continue if iterator throws
return { done: true, value };
}
let completedItem;
try {
completedItem = completeValue(
exeContext,
itemType,
fieldNodes,
info,
fieldPath,
item,
asyncPayloadRecord,
);
if (isPromise(completedItem)) {
completedItem = completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(fieldPath),
);
return handleFieldError(error, itemType, asyncPayloadRecord.errors);
});
}
return { done: false, value: completedItem };
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
return { done: false, value };
}
}
async function executeStreamIterator(
initialIndex,
iterator,
exeContext,
fieldNodes,
info,
itemType,
path,
label,
parentContext,
) {
const subsequentPayloads = exeContext.subsequentPayloads;
let index = initialIndex;
// eslint-disable-next-line no-constant-condition
while (true) {
const fieldPath = addPath(path, index, undefined);
const asyncPayloadRecord = new StreamRecord({
label,
path: fieldPath,
parentContext,
iterator,
});
const dataPromise = executeStreamIteratorItem(
iterator,
exeContext,
fieldNodes,
info,
itemType,
asyncPayloadRecord,
fieldPath,
);
asyncPayloadRecord.addItems(
dataPromise
.then(({ value }) => value)
.then(
(value) => [value],
(err) => {
asyncPayloadRecord.errors.push(err);
return null;
},
),
);
subsequentPayloads.push(asyncPayloadRecord);
try {
// eslint-disable-next-line no-await-in-loop
const { done } = await dataPromise;
if (done) {
break;
}
} catch (err) {
// do nothing, error is already handled above
}
index++;
}
}
function yieldSubsequentPayloads(exeContext) {
let isDone = false;
async function race() {
if (exeContext.subsequentPayloads.length === 0) {
// async iterable resolver just finished and no more pending payloads
return {
value: {
hasNext: false,
},
done: false,
};
}
const asyncPayloadRecord = await new Promise((resolve) => {
exeContext.subsequentPayloads.forEach((payload) => {
const data = payload.getData();
if (isPromise(data)) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
data.then(() => {
resolve(payload);
});
} else {
resolve(payload);
}
});
});
if (exeContext.subsequentPayloads.length === 0) {
// a different call to next has exhausted all payloads
return { value: undefined, done: true };
}
const index = exeContext.subsequentPayloads.indexOf(asyncPayloadRecord);
if (index === -1) {
// a different call to next has consumed this payload
return race();
}
exeContext.subsequentPayloads.splice(index, 1);
const incrementalResult = {};
if (isStreamPayload(asyncPayloadRecord)) {
const items = await asyncPayloadRecord.items;
if (asyncPayloadRecord.isCompletedIterator) {
// async iterable resolver just finished but there may be pending payloads
// return the next one
return race();
}
incrementalResult.items = items;
} else {
const data = await asyncPayloadRecord.data;
incrementalResult.data = data ?? null;
}
incrementalResult.path = asyncPayloadRecord.path
? pathToArray(asyncPayloadRecord.path)
: [];
if (asyncPayloadRecord.label) {
incrementalResult.label = asyncPayloadRecord.label;
}
if (asyncPayloadRecord.errors.length > 0) {
incrementalResult.errors = asyncPayloadRecord.errors;
}
return {
value: {
incremental: [incrementalResult],
hasNext: exeContext.subsequentPayloads.length > 0,
},
done: false,
};
}
return {
[Symbol.asyncIterator]() {
return this;
},
next: () => {
if (exeContext.subsequentPayloads.length === 0 || isDone) {
return Promise.resolve({ value: undefined, done: true });
}
return race();
},
async return() {
await Promise.all(
exeContext.subsequentPayloads.map((asyncPayloadRecord) => {
if (isStreamPayload(asyncPayloadRecord)) {
return asyncPayloadRecord.iterator?.return?.();
}
return undefined;
}),
);
isDone = true;
return { value: undefined, done: true };
},
async throw(error) {
await Promise.all(
exeContext.subsequentPayloads.map((asyncPayloadRecord) => {
if (isStreamPayload(asyncPayloadRecord)) {
return asyncPayloadRecord.iterator?.return?.();
}
return undefined;
}),
);
isDone = true;
return Promise.reject(error);
},
};
}
class DeferredFragmentRecord {
constructor(opts) {
this.type = 'defer';
this.data = null;
this.label = opts.label;
this.path = opts.path;
this.parentContext = opts.parentContext;
this.errors = [];
}
addData(data) {
this.data = data;
}
getData() {
const parentData = this.parentContext?.getData();
if (parentData) {
return Promise.resolve(parentData).then(() => this.data);
}
return this.data;
}
}
class StreamRecord {
constructor(opts) {
this.type = 'stream';
this.items = null;
this.label = opts.label;
this.path = opts.path;
this.parentContext = opts.parentContext;
this.iterator = opts.iterator;
this.errors = [];
}
addItems(items) {
this.items = items;
}
getData() {
const parentData = this.parentContext?.getData();
if (parentData) {
return Promise.resolve(parentData).then(() => this.items);
}
return this.items;
}
setIsCompletedIterator() {
this.isCompletedIterator = true;
}
}
function isStreamPayload(asyncPayload) {
return asyncPayload.type === 'stream';
}

@@ -13,3 +13,14 @@ export { pathToArray as responsePathAsArray } from '../jsutils/Path';

ExecutionResult,
ExperimentalExecuteIncrementallyResults,
InitialIncrementalExecutionResult,
SubsequentIncrementalExecutionResult,
IncrementalDeferResult,
IncrementalStreamResult,
IncrementalResult,
FormattedExecutionResult,
FormattedInitialIncrementalExecutionResult,
FormattedSubsequentIncrementalExecutionResult,
FormattedIncrementalDeferResult,
FormattedIncrementalStreamResult,
FormattedIncrementalResult,
} from './execute';

@@ -16,0 +27,0 @@ export {

@@ -71,3 +71,3 @@ import type { Maybe } from '../jsutils/Maybe';

node: {
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
},

@@ -74,0 +74,0 @@ variableValues?: Maybe<ObjMap<unknown>>,

@@ -18,2 +18,4 @@ import type { Maybe } from './jsutils/Maybe';

*
* This function does not support incremental delivery (`@defer` and `@stream`).
*
* Accepts either an object with named arguments, or individual arguments:

@@ -20,0 +22,0 @@ *

@@ -55,2 +55,4 @@ /**

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -300,3 +302,14 @@ GraphQLSpecifiedByDirective,

ExecutionResult,
ExperimentalExecuteIncrementallyResults,
InitialIncrementalExecutionResult,
SubsequentIncrementalExecutionResult,
IncrementalDeferResult,
IncrementalStreamResult,
IncrementalResult,
FormattedExecutionResult,
FormattedInitialIncrementalExecutionResult,
FormattedSubsequentIncrementalExecutionResult,
FormattedIncrementalDeferResult,
FormattedIncrementalStreamResult,
FormattedIncrementalResult,
} from './execution/index';

@@ -352,3 +365,2 @@ export {

export {
Anonymizer,
getIntrospectionQuery,

@@ -355,0 +367,0 @@ getOperationAST,

@@ -60,2 +60,4 @@ /**

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -239,3 +241,2 @@ GraphQLSpecifiedByDirective,

export {
Anonymizer,
// Produce the GraphQL query recommended for a full schema introspection.

@@ -242,0 +243,0 @@ // Accepts optional IntrospectionOptions.

@@ -9,6 +9,8 @@ /**

export function promiseForObject(object) {
return Promise.all(Object.values(object)).then((resolvedValues) => {
const keys = Object.keys(object);
const values = Object.values(object);
return Promise.all(values).then((resolvedValues) => {
const resolvedObject = Object.create(null);
for (const [i, key] of Object.keys(object).entries()) {
resolvedObject[key] = resolvedValues[i];
for (let i = 0; i < keys.length; ++i) {
resolvedObject[keys[i]] = resolvedValues[i];
}

@@ -15,0 +17,0 @@ return resolvedObject;

@@ -160,3 +160,3 @@ import type { Kind } from './kinds';

readonly kind: Kind.NAME;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: string;

@@ -167,3 +167,3 @@ }

readonly kind: Kind.DOCUMENT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly definitions: ReadonlyArray<DefinitionNode>;

@@ -180,7 +180,9 @@ }

readonly kind: Kind.OPERATION_DEFINITION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly operation: OperationTypeNode;
readonly name?: NameNode;
readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly name?: NameNode | undefined;
readonly variableDefinitions?:
| ReadonlyArray<VariableDefinitionNode>
| undefined;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
readonly selectionSet: SelectionSetNode;

@@ -195,11 +197,11 @@ }

readonly kind: Kind.VARIABLE_DEFINITION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly variable: VariableNode;
readonly type: TypeNode;
readonly defaultValue?: ConstValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly defaultValue?: ConstValueNode | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface VariableNode {
readonly kind: Kind.VARIABLE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -209,3 +211,3 @@ }

kind: Kind.SELECTION_SET;
loc?: Location;
loc?: Location | undefined;
selections: ReadonlyArray<SelectionNode>;

@@ -219,9 +221,9 @@ }

readonly kind: Kind.FIELD;
readonly loc?: Location;
readonly alias?: NameNode;
readonly loc?: Location | undefined;
readonly alias?: NameNode | undefined;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ArgumentNode>;
readonly nullabilityAssertion?: NullabilityAssertionNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet?: SelectionSetNode;
readonly arguments?: ReadonlyArray<ArgumentNode> | undefined;
readonly nullabilityAssertion?: NullabilityAssertionNode | undefined;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
readonly selectionSet?: SelectionSetNode | undefined;
}

@@ -234,18 +236,18 @@ export declare type NullabilityAssertionNode =

readonly kind: Kind.LIST_NULLABILITY_OPERATOR;
readonly loc?: Location;
readonly nullabilityAssertion?: NullabilityAssertionNode;
readonly loc?: Location | undefined;
readonly nullabilityAssertion?: NullabilityAssertionNode | undefined;
}
export interface NonNullAssertionNode {
readonly kind: Kind.NON_NULL_ASSERTION;
readonly loc?: Location;
readonly nullabilityAssertion?: ListNullabilityOperatorNode;
readonly loc?: Location | undefined;
readonly nullabilityAssertion?: ListNullabilityOperatorNode | undefined;
}
export interface ErrorBoundaryNode {
readonly kind: Kind.ERROR_BOUNDARY;
readonly loc?: Location;
readonly nullabilityAssertion?: ListNullabilityOperatorNode;
readonly loc?: Location | undefined;
readonly nullabilityAssertion?: ListNullabilityOperatorNode | undefined;
}
export interface ArgumentNode {
readonly kind: Kind.ARGUMENT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -256,3 +258,3 @@ readonly value: ValueNode;

readonly kind: Kind.ARGUMENT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -264,11 +266,11 @@ readonly value: ConstValueNode;

readonly kind: Kind.FRAGMENT_SPREAD;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
}
export interface InlineFragmentNode {
readonly kind: Kind.INLINE_FRAGMENT;
readonly loc?: Location;
readonly typeCondition?: NamedTypeNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly loc?: Location | undefined;
readonly typeCondition?: NamedTypeNode | undefined;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
readonly selectionSet: SelectionSetNode;

@@ -278,8 +280,10 @@ }

readonly kind: Kind.FRAGMENT_DEFINITION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
/** @deprecated variableDefinitions will be removed in v17.0.0 */
readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>;
readonly variableDefinitions?:
| ReadonlyArray<VariableDefinitionNode>
| undefined;
readonly typeCondition: NamedTypeNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
readonly selectionSet: SelectionSetNode;

@@ -309,3 +313,3 @@ }

readonly kind: Kind.INT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: string;

@@ -315,3 +319,3 @@ }

readonly kind: Kind.FLOAT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: string;

@@ -321,9 +325,9 @@ }

readonly kind: Kind.STRING;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: string;
readonly block?: boolean;
readonly block?: boolean | undefined;
}
export interface BooleanValueNode {
readonly kind: Kind.BOOLEAN;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: boolean;

@@ -333,7 +337,7 @@ }

readonly kind: Kind.NULL;
readonly loc?: Location;
readonly loc?: Location | undefined;
}
export interface EnumValueNode {
readonly kind: Kind.ENUM;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly value: string;

@@ -343,3 +347,3 @@ }

readonly kind: Kind.LIST;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly values: ReadonlyArray<ValueNode>;

@@ -349,3 +353,3 @@ }

readonly kind: Kind.LIST;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly values: ReadonlyArray<ConstValueNode>;

@@ -355,3 +359,3 @@ }

readonly kind: Kind.OBJECT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly fields: ReadonlyArray<ObjectFieldNode>;

@@ -361,3 +365,3 @@ }

readonly kind: Kind.OBJECT;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly fields: ReadonlyArray<ConstObjectFieldNode>;

@@ -367,3 +371,3 @@ }

readonly kind: Kind.OBJECT_FIELD;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -374,3 +378,3 @@ readonly value: ValueNode;

readonly kind: Kind.OBJECT_FIELD;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -382,11 +386,11 @@ readonly value: ConstValueNode;

readonly kind: Kind.DIRECTIVE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ArgumentNode>;
readonly arguments?: ReadonlyArray<ArgumentNode> | undefined;
}
export interface ConstDirectiveNode {
readonly kind: Kind.DIRECTIVE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ConstArgumentNode>;
readonly arguments?: ReadonlyArray<ConstArgumentNode> | undefined;
}

@@ -397,3 +401,3 @@ /** Type Reference */

readonly kind: Kind.NAMED_TYPE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;

@@ -403,3 +407,3 @@ }

readonly kind: Kind.LIST_TYPE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly type: TypeNode;

@@ -409,3 +413,3 @@ }

readonly kind: Kind.NON_NULL_TYPE;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly type: NamedTypeNode | ListTypeNode;

@@ -420,5 +424,5 @@ }

readonly kind: Kind.SCHEMA_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly operationTypes: ReadonlyArray<OperationTypeDefinitionNode>;

@@ -428,3 +432,3 @@ }

readonly kind: Kind.OPERATION_TYPE_DEFINITION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly operation: OperationTypeNode;

@@ -443,73 +447,73 @@ readonly type: NamedTypeNode;

readonly kind: Kind.SCALAR_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface ObjectTypeDefinitionNode {
readonly kind: Kind.OBJECT_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
readonly interfaces?: ReadonlyArray<NamedTypeNode> | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<FieldDefinitionNode> | undefined;
}
export interface FieldDefinitionNode {
readonly kind: Kind.FIELD_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode> | undefined;
readonly type: TypeNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface InputValueDefinitionNode {
readonly kind: Kind.INPUT_VALUE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly type: TypeNode;
readonly defaultValue?: ConstValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly defaultValue?: ConstValueNode | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface InterfaceTypeDefinitionNode {
readonly kind: Kind.INTERFACE_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
readonly interfaces?: ReadonlyArray<NamedTypeNode> | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<FieldDefinitionNode> | undefined;
}
export interface UnionTypeDefinitionNode {
readonly kind: Kind.UNION_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly types?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly types?: ReadonlyArray<NamedTypeNode> | undefined;
}
export interface EnumTypeDefinitionNode {
readonly kind: Kind.ENUM_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly values?: ReadonlyArray<EnumValueDefinitionNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly values?: ReadonlyArray<EnumValueDefinitionNode> | undefined;
}
export interface EnumValueDefinitionNode {
readonly kind: Kind.ENUM_VALUE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface InputObjectTypeDefinitionNode {
readonly kind: Kind.INPUT_OBJECT_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<InputValueDefinitionNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<InputValueDefinitionNode> | undefined;
}

@@ -519,6 +523,6 @@ /** Directive Definitions */

readonly kind: Kind.DIRECTIVE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly loc?: Location | undefined;
readonly description?: StringValueNode | undefined;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode> | undefined;
readonly repeatable: boolean;

@@ -533,5 +537,7 @@ readonly locations: ReadonlyArray<NameNode>;

readonly kind: Kind.SCHEMA_EXTENSION;
readonly loc?: Location;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly operationTypes?: ReadonlyArray<OperationTypeDefinitionNode>;
readonly loc?: Location | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly operationTypes?:
| ReadonlyArray<OperationTypeDefinitionNode>
| undefined;
}

@@ -548,42 +554,42 @@ /** Type Extensions */

readonly kind: Kind.SCALAR_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
}
export interface ObjectTypeExtensionNode {
readonly kind: Kind.OBJECT_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
readonly interfaces?: ReadonlyArray<NamedTypeNode> | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<FieldDefinitionNode> | undefined;
}
export interface InterfaceTypeExtensionNode {
readonly kind: Kind.INTERFACE_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
readonly interfaces?: ReadonlyArray<NamedTypeNode> | undefined;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<FieldDefinitionNode> | undefined;
}
export interface UnionTypeExtensionNode {
readonly kind: Kind.UNION_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly types?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly types?: ReadonlyArray<NamedTypeNode> | undefined;
}
export interface EnumTypeExtensionNode {
readonly kind: Kind.ENUM_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly values?: ReadonlyArray<EnumValueDefinitionNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly values?: ReadonlyArray<EnumValueDefinitionNode> | undefined;
}
export interface InputObjectTypeExtensionNode {
readonly kind: Kind.INPUT_OBJECT_TYPE_EXTENSION;
readonly loc?: Location;
readonly loc?: Location | undefined;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<InputValueDefinitionNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode> | undefined;
readonly fields?: ReadonlyArray<InputValueDefinitionNode> | undefined;
}

@@ -67,4 +67,12 @@ import type { Maybe } from '../jsutils/Maybe';

*/
noLocation?: boolean;
noLocation?: boolean | undefined;
/**
* Parser CPU and memory usage is linear to the number of tokens in a document
* however in extreme cases it becomes quadratic due to memory exhaustion.
* Parsing happens before validation so even invalid queries can burn lots of
* CPU time and memory.
* To prevent this you can set a maximum number of tokens allowed within a document.
*/
maxTokens?: number | undefined;
/**
* @deprecated will be removed in the v17.0.0

@@ -84,3 +92,3 @@ *

*/
allowLegacyFragmentVariables?: boolean;
allowLegacyFragmentVariables?: boolean | undefined;
/**

@@ -107,3 +115,3 @@ * EXPERIMENTAL:

*/
experimentalClientControlledNullability?: boolean;
experimentalClientControlledNullability?: boolean | undefined;
}

@@ -116,3 +124,3 @@ /**

source: string | Source,
options?: ParseOptions,
options?: ParseOptions | undefined,
): DocumentNode;

@@ -131,3 +139,3 @@ /**

source: string | Source,
options?: ParseOptions,
options?: ParseOptions | undefined,
): ValueNode;

@@ -140,3 +148,3 @@ /**

source: string | Source,
options?: ParseOptions,
options?: ParseOptions | undefined,
): ConstValueNode;

@@ -155,3 +163,3 @@ /**

source: string | Source,
options?: ParseOptions,
options?: ParseOptions | undefined,
): TypeNode;

@@ -170,4 +178,5 @@ /**

export declare class Parser {
protected _options: Maybe<ParseOptions>;
protected _options: ParseOptions;
protected _lexer: Lexer;
protected _tokenCounter: number;
constructor(source: string | Source, options?: ParseOptions);

@@ -522,3 +531,3 @@ /**

T extends {
loc?: Location;
loc?: Location | undefined;
},

@@ -587,2 +596,3 @@ >(startToken: Token, node: T): T;

delimitedMany<T>(delimiterKind: TokenKind, parseFn: () => T): Array<T>;
advanceLexer(): void;
}

@@ -73,6 +73,7 @@ import { syntaxError } from '../error/syntaxError.js';

export class Parser {
constructor(source, options) {
constructor(source, options = {}) {
const sourceObj = isSource(source) ? source : new Source(source);
this._lexer = new Lexer(sourceObj);
this._options = options;
this._tokenCounter = 0;
}

@@ -316,3 +317,3 @@ /**

// removed in the future.
if (this._options?.experimentalClientControlledNullability !== true) {
if (this._options.experimentalClientControlledNullability !== true) {
return undefined;

@@ -398,3 +399,3 @@ }

// - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
if (this._options?.allowLegacyFragmentVariables === true) {
if (this._options.allowLegacyFragmentVariables === true) {
return this.node(start, {

@@ -434,3 +435,3 @@ kind: Kind.FRAGMENT_DEFINITION,

case TokenKind.INT:
this._lexer.advance();
this.advanceLexer();
return this.node(token, {

@@ -441,3 +442,3 @@ kind: Kind.INT,

case TokenKind.FLOAT:
this._lexer.advance();
this.advanceLexer();
return this.node(token, {

@@ -451,3 +452,3 @@ kind: Kind.FLOAT,

case TokenKind.NAME:
this._lexer.advance();
this.advanceLexer();
switch (token.value) {

@@ -496,3 +497,3 @@ case 'true':

const token = this._lexer.token;
this._lexer.advance();
this.advanceLexer();
return this.node(token, {

@@ -1172,3 +1173,3 @@ kind: Kind.STRING,

node(startToken, node) {
if (this._options?.noLocation !== true) {
if (this._options.noLocation !== true) {
node.loc = new Location(

@@ -1195,3 +1196,3 @@ startToken,

if (token.kind === kind) {
this._lexer.advance();
this.advanceLexer();
return token;

@@ -1212,3 +1213,3 @@ }

if (token.kind === kind) {
this._lexer.advance();
this.advanceLexer();
return true;

@@ -1225,3 +1226,3 @@ }

if (token.kind === TokenKind.NAME && token.value === value) {
this._lexer.advance();
this.advanceLexer();
} else {

@@ -1242,3 +1243,3 @@ throw syntaxError(

if (token.kind === TokenKind.NAME && token.value === value) {
this._lexer.advance();
this.advanceLexer();
return true;

@@ -1314,2 +1315,16 @@ }

}
advanceLexer() {
const { maxTokens } = this._options;
const token = this._lexer.advance();
if (maxTokens !== undefined && token.kind !== TokenKind.EOF) {
++this._tokenCounter;
if (this._tokenCounter > maxTokens) {
throw syntaxError(
this._lexer.source,
token.start,
`Document contains more that ${maxTokens} tokens. Parsing aborted.`,
);
}
}
}
}

@@ -1316,0 +1331,0 @@ /**

@@ -14,4 +14,4 @@ import type { ASTNode } from './ast';

interface EnterLeaveVisitor<TVisitedNode extends ASTNode> {
readonly enter?: ASTVisitFn<TVisitedNode>;
readonly leave?: ASTVisitFn<TVisitedNode>;
readonly enter?: ASTVisitFn<TVisitedNode> | undefined;
readonly leave?: ASTVisitFn<TVisitedNode> | undefined;
}

@@ -18,0 +18,0 @@ /**

{
"name": "graphql",
"version": "17.0.0-alpha.1.canary.pr.3673.53c289997f206acd10388d6a574341c68cc1a30e",
"version": "17.0.0-alpha.1.canary.pr.3703.9360805de6310b453b76a53431f921b44a76c2f9",
"description": "A Query Language and Runtime which can target any service.",

@@ -35,3 +35,3 @@ "license": "MIT",

"publishConfig": {
"tag": "canary-pr-3673"
"tag": "canary-pr-3703"
},

@@ -50,3 +50,3 @@ "type": "module",

},
"deprecated": "You are using canary version build from https://github.com/graphql/graphql-js/pull/3673, no gurantees provided so please use your own discretion."
"deprecated": "You are using canary version build from https://github.com/graphql/graphql-js/pull/3703, no gurantees provided so please use your own discretion."
}

@@ -328,7 +328,7 @@ import type { Maybe } from '../jsutils/Maybe';

/** Serializes an internal value to include in a response. */
serialize?: GraphQLScalarSerializer<TExternal>;
serialize?: GraphQLScalarSerializer<TExternal> | undefined;
/** Parses an externally provided value to use as an input. */
parseValue?: GraphQLScalarValueParser<TInternal>;
parseValue?: GraphQLScalarValueParser<TInternal> | undefined;
/** Parses an externally provided literal value to use as an input. */
parseLiteral?: GraphQLScalarLiteralParser<TInternal>;
parseLiteral?: GraphQLScalarLiteralParser<TInternal> | undefined;
extensions?: Maybe<Readonly<GraphQLScalarTypeExtensions>>;

@@ -430,3 +430,3 @@ astNode?: Maybe<ScalarTypeDefinitionNode>;

description?: Maybe<string>;
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType>;
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType> | undefined;
fields: ThunkObjMap<GraphQLFieldConfig<TSource, TContext>>;

@@ -499,5 +499,5 @@ isTypeOf?: Maybe<GraphQLIsTypeOfFn<TSource, TContext>>;

type: GraphQLOutputType;
args?: GraphQLFieldConfigArgumentMap;
resolve?: GraphQLFieldResolver<TSource, TContext, TArgs>;
subscribe?: GraphQLFieldResolver<TSource, TContext, TArgs>;
args?: GraphQLFieldConfigArgumentMap | undefined;
resolve?: GraphQLFieldResolver<TSource, TContext, TArgs> | undefined;
subscribe?: GraphQLFieldResolver<TSource, TContext, TArgs> | undefined;
deprecationReason?: Maybe<string>;

@@ -539,4 +539,4 @@ extensions?: Maybe<

args: ReadonlyArray<GraphQLArgument>;
resolve?: GraphQLFieldResolver<TSource, TContext, TArgs>;
subscribe?: GraphQLFieldResolver<TSource, TContext, TArgs>;
resolve?: GraphQLFieldResolver<TSource, TContext, TArgs> | undefined;
subscribe?: GraphQLFieldResolver<TSource, TContext, TArgs> | undefined;
deprecationReason: Maybe<string>;

@@ -610,3 +610,3 @@ extensions: Readonly<GraphQLFieldExtensions<TSource, TContext, TArgs>>;

description?: Maybe<string>;
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType>;
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType> | undefined;
fields: ThunkObjMap<GraphQLFieldConfig<TSource, TContext>>;

@@ -613,0 +613,0 @@ /**

@@ -68,2 +68,10 @@ import type { Maybe } from '../jsutils/Maybe';

/**
* Used to conditionally defer fragments.
*/
export declare const GraphQLDeferDirective: GraphQLDirective;
/**
* Used to conditionally stream list fields.
*/
export declare const GraphQLStreamDirective: GraphQLDirective;
/**
* Constant string used for default reason for a deprecation.

@@ -70,0 +78,0 @@ */

@@ -11,3 +11,3 @@ import { inspect } from '../jsutils/inspect.js';

} from './definition.js';
import { GraphQLBoolean, GraphQLString } from './scalars.js';
import { GraphQLBoolean, GraphQLInt, GraphQLString } from './scalars.js';
/**

@@ -102,2 +102,48 @@ * Test if the given value is a GraphQL directive.

/**
* Used to conditionally defer fragments.
*/
export const GraphQLDeferDirective = new GraphQLDirective({
name: 'defer',
description:
'Directs the executor to defer this fragment when the `if` argument is true or undefined.',
locations: [
DirectiveLocation.FRAGMENT_SPREAD,
DirectiveLocation.INLINE_FRAGMENT,
],
args: {
if: {
type: GraphQLBoolean,
description: 'Deferred when true or undefined.',
},
label: {
type: GraphQLString,
description: 'Unique name',
},
},
});
/**
* Used to conditionally stream list fields.
*/
export const GraphQLStreamDirective = new GraphQLDirective({
name: 'stream',
description:
'Directs the executor to stream plural fields when the `if` argument is true or undefined.',
locations: [DirectiveLocation.FIELD],
args: {
if: {
type: GraphQLBoolean,
description: 'Stream when true or undefined.',
},
label: {
type: GraphQLString,
description: 'Unique name',
},
initialCount: {
defaultValue: 0,
type: GraphQLInt,
description: 'Number of items to return immediately',
},
},
});
/**
* Constant string used for default reason for a deprecation.

@@ -104,0 +150,0 @@ */

@@ -116,2 +116,4 @@ export type { Path as ResponsePath } from '../jsutils/Path';

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -118,0 +120,0 @@ GraphQLSpecifiedByDirective,

@@ -76,2 +76,4 @@ export {

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -78,0 +80,0 @@ GraphQLSpecifiedByDirective,

@@ -163,3 +163,3 @@ import type { Maybe } from '../jsutils/Maybe';

*/
assumeValid?: boolean;
assumeValid?: boolean | undefined;
}

@@ -166,0 +166,0 @@ export interface GraphQLSchemaConfig extends GraphQLSchemaValidationOptions {

@@ -144,3 +144,3 @@ import { inspect } from '../jsutils/inspect.js';

this._typeMap = Object.create(null);
this._subTypeMap = Object.create(null);
this._subTypeMap = new Map();
// Keep track of all implementations by interface name.

@@ -228,21 +228,16 @@ this._implementationsMap = Object.create(null);

isSubType(abstractType, maybeSubType) {
let map = this._subTypeMap[abstractType.name];
if (map === undefined) {
map = Object.create(null);
let set = this._subTypeMap.get(abstractType);
if (set === undefined) {
if (isUnionType(abstractType)) {
for (const type of abstractType.getTypes()) {
map[type.name] = true;
}
set = new Set(abstractType.getTypes());
} else {
const implementations = this.getImplementations(abstractType);
for (const type of implementations.objects) {
map[type.name] = true;
}
for (const type of implementations.interfaces) {
map[type.name] = true;
}
set = new Set([
...implementations.objects,
...implementations.interfaces,
]);
}
this._subTypeMap[abstractType.name] = map;
this._subTypeMap.set(abstractType, set);
}
return map[maybeSubType.name] !== undefined;
return set.has(maybeSubType);
}

@@ -249,0 +244,0 @@ getDirectives() {

@@ -95,3 +95,3 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js';

}
for (const [rootType, operationTypes] of rootTypesMap.entries()) {
for (const [rootType, operationTypes] of rootTypesMap) {
if (operationTypes.length > 1) {

@@ -243,3 +243,3 @@ const operationList = andList(operationTypes);

function validateInterfaces(context, type) {
const ifaceTypeNames = Object.create(null);
const ifaceTypeNames = new Set();
for (const iface of type.getInterfaces()) {

@@ -261,3 +261,3 @@ if (!isInterfaceType(iface)) {

}
if (ifaceTypeNames[iface.name]) {
if (ifaceTypeNames.has(iface.name)) {
context.reportError(

@@ -269,3 +269,3 @@ `Type ${type.name} can only implement ${iface.name} once.`,

}
ifaceTypeNames[iface.name] = true;
ifaceTypeNames.add(iface.name);
validateTypeImplementsAncestors(context, type, iface);

@@ -362,5 +362,5 @@ validateTypeImplementsInterface(context, type, iface);

}
const includedTypeNames = Object.create(null);
const includedTypeNames = new Set();
for (const memberType of memberTypes) {
if (includedTypeNames[memberType.name]) {
if (includedTypeNames.has(memberType.name)) {
context.reportError(

@@ -372,3 +372,3 @@ `Union type ${union.name} can only include type ${memberType.name} once.`,

}
includedTypeNames[memberType.name] = true;
includedTypeNames.add(memberType.name);
if (!isObjectType(memberType)) {

@@ -428,3 +428,3 @@ context.reportError(

// are not redundantly reported.
const visitedTypes = Object.create(null);
const visitedTypes = new Set();
// Array of types nodes used to produce meaningful errors

@@ -439,6 +439,6 @@ const fieldPath = [];

function detectCycleRecursive(inputObj) {
if (visitedTypes[inputObj.name]) {
if (visitedTypes.has(inputObj)) {
return;
}
visitedTypes[inputObj.name] = true;
visitedTypes.add(inputObj);
fieldPathIndexByTypeName[inputObj.name] = fieldPath.length;

@@ -445,0 +445,0 @@ const fields = Object.values(inputObj.getFields());

@@ -12,3 +12,3 @@ import type { DocumentNode } from '../language/ast';

*/
assumeValidSDL?: boolean;
assumeValidSDL?: boolean | undefined;
}

@@ -15,0 +15,0 @@ /**

@@ -115,3 +115,3 @@ import { didYouMean } from '../jsutils/didYouMean.js';

let parseResult;
// Scalars and Enums determine if a input value is valid via parseValue(),
// Scalars and Enums determine if an input value is valid via parseValue(),
// which can throw to indicate failure. If it throws, maintain a reference

@@ -118,0 +118,0 @@ // to the original error.

@@ -13,3 +13,3 @@ import type { DocumentNode } from '../language/ast';

*/
assumeValidSDL?: boolean;
assumeValidSDL?: boolean | undefined;
}

@@ -16,0 +16,0 @@ /**

@@ -0,1 +1,2 @@

import { AccumulatorMap } from '../jsutils/AccumulatorMap.js';
import { inspect } from '../jsutils/inspect.js';

@@ -7,6 +8,2 @@ import { invariant } from '../jsutils/invariant.js';

import {
isTypeDefinitionNode,
isTypeExtensionNode,
} from '../language/predicates.js';
import {
GraphQLEnumType,

@@ -76,3 +73,8 @@ GraphQLInputObjectType,

const typeDefs = [];
const typeExtensionsMap = Object.create(null);
const scalarExtensions = new AccumulatorMap();
const objectExtensions = new AccumulatorMap();
const interfaceExtensions = new AccumulatorMap();
const unionExtensions = new AccumulatorMap();
const enumExtensions = new AccumulatorMap();
const inputObjectExtensions = new AccumulatorMap();
// New directives and types are separate because a directives and types can

@@ -84,28 +86,50 @@ // have the same name. For example, a type named "skip".

const schemaExtensions = [];
let isSchemaChanged = false;
for (const def of documentAST.definitions) {
if (def.kind === Kind.SCHEMA_DEFINITION) {
schemaDef = def;
} else if (def.kind === Kind.SCHEMA_EXTENSION) {
schemaExtensions.push(def);
} else if (isTypeDefinitionNode(def)) {
typeDefs.push(def);
} else if (isTypeExtensionNode(def)) {
const extendedTypeName = def.name.value;
const existingTypeExtensions = typeExtensionsMap[extendedTypeName];
typeExtensionsMap[extendedTypeName] = existingTypeExtensions
? existingTypeExtensions.concat([def])
: [def];
} else if (def.kind === Kind.DIRECTIVE_DEFINITION) {
directiveDefs.push(def);
switch (def.kind) {
case Kind.SCHEMA_DEFINITION:
schemaDef = def;
break;
case Kind.SCHEMA_EXTENSION:
schemaExtensions.push(def);
break;
case Kind.DIRECTIVE_DEFINITION:
directiveDefs.push(def);
break;
// Type Definitions
case Kind.SCALAR_TYPE_DEFINITION:
case Kind.OBJECT_TYPE_DEFINITION:
case Kind.INTERFACE_TYPE_DEFINITION:
case Kind.UNION_TYPE_DEFINITION:
case Kind.ENUM_TYPE_DEFINITION:
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
typeDefs.push(def);
break;
// Type System Extensions
case Kind.SCALAR_TYPE_EXTENSION:
scalarExtensions.add(def.name.value, def);
break;
case Kind.OBJECT_TYPE_EXTENSION:
objectExtensions.add(def.name.value, def);
break;
case Kind.INTERFACE_TYPE_EXTENSION:
interfaceExtensions.add(def.name.value, def);
break;
case Kind.UNION_TYPE_EXTENSION:
unionExtensions.add(def.name.value, def);
break;
case Kind.ENUM_TYPE_EXTENSION:
enumExtensions.add(def.name.value, def);
break;
case Kind.INPUT_OBJECT_TYPE_EXTENSION:
inputObjectExtensions.add(def.name.value, def);
break;
default:
continue;
}
isSchemaChanged = true;
}
// If this document contains no new types, extensions, or directives then
// return the same unmodified GraphQLSchema instance.
if (
Object.keys(typeExtensionsMap).length === 0 &&
typeDefs.length === 0 &&
directiveDefs.length === 0 &&
schemaExtensions.length === 0 &&
schemaDef == null
) {
if (!isSchemaChanged) {
return schemaConfig;

@@ -205,3 +229,3 @@ }

const config = type.toConfig();
const extensions = typeExtensionsMap[config.name] ?? [];
const extensions = inputObjectExtensions.get(config.name) ?? [];
return new GraphQLInputObjectType({

@@ -221,3 +245,3 @@ ...config,

const config = type.toConfig();
const extensions = typeExtensionsMap[type.name] ?? [];
const extensions = enumExtensions.get(type.name) ?? [];
return new GraphQLEnumType({

@@ -234,3 +258,3 @@ ...config,

const config = type.toConfig();
const extensions = typeExtensionsMap[config.name] ?? [];
const extensions = scalarExtensions.get(config.name) ?? [];
let specifiedByURL = config.specifiedByURL;

@@ -248,3 +272,3 @@ for (const extensionNode of extensions) {

const config = type.toConfig();
const extensions = typeExtensionsMap[config.name] ?? [];
const extensions = objectExtensions.get(config.name) ?? [];
return new GraphQLObjectType({

@@ -265,3 +289,3 @@ ...config,

const config = type.toConfig();
const extensions = typeExtensionsMap[config.name] ?? [];
const extensions = interfaceExtensions.get(config.name) ?? [];
return new GraphQLInterfaceType({

@@ -282,3 +306,3 @@ ...config,

const config = type.toConfig();
const extensions = typeExtensionsMap[config.name] ?? [];
const extensions = unionExtensions.get(config.name) ?? [];
return new GraphQLUnionType({

@@ -447,5 +471,5 @@ ...config,

const name = astNode.name.value;
const extensionASTNodes = typeExtensionsMap[name] ?? [];
switch (astNode.kind) {
case Kind.OBJECT_TYPE_DEFINITION: {
const extensionASTNodes = objectExtensions.get(name) ?? [];
const allNodes = [astNode, ...extensionASTNodes];

@@ -462,2 +486,3 @@ return new GraphQLObjectType({

case Kind.INTERFACE_TYPE_DEFINITION: {
const extensionASTNodes = interfaceExtensions.get(name) ?? [];
const allNodes = [astNode, ...extensionASTNodes];

@@ -474,2 +499,3 @@ return new GraphQLInterfaceType({

case Kind.ENUM_TYPE_DEFINITION: {
const extensionASTNodes = enumExtensions.get(name) ?? [];
const allNodes = [astNode, ...extensionASTNodes];

@@ -485,2 +511,3 @@ return new GraphQLEnumType({

case Kind.UNION_TYPE_DEFINITION: {
const extensionASTNodes = unionExtensions.get(name) ?? [];
const allNodes = [astNode, ...extensionASTNodes];

@@ -496,2 +523,3 @@ return new GraphQLUnionType({

case Kind.SCALAR_TYPE_DEFINITION: {
const extensionASTNodes = scalarExtensions.get(name) ?? [];
return new GraphQLScalarType({

@@ -506,2 +534,3 @@ name,

case Kind.INPUT_OBJECT_TYPE_DEFINITION: {
const extensionASTNodes = inputObjectExtensions.get(name) ?? [];
const allNodes = [astNode, ...extensionASTNodes];

@@ -508,0 +537,0 @@ return new GraphQLInputObjectType({

@@ -1,2 +0,1 @@

export { Anonymizer } from './Anonymizer';
export { getIntrospectionQuery } from './getIntrospectionQuery';

@@ -3,0 +2,0 @@ export type {

@@ -1,2 +0,1 @@

export { Anonymizer } from './Anonymizer.js';
// Produce the GraphQL query recommended for a full schema introspection.

@@ -3,0 +2,0 @@ export { getIntrospectionQuery } from './getIntrospectionQuery.js';

@@ -5,2 +5,4 @@ export { validate } from './validate';

export { specifiedRules } from './specifiedRules';
export { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule';
export { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule';
export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule';

@@ -23,2 +25,3 @@ export { FieldsOnCorrectTypeRule } from './rules/FieldsOnCorrectTypeRule';

export { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule';
export { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule';
export { UniqueArgumentNamesRule } from './rules/UniqueArgumentNamesRule';

@@ -25,0 +28,0 @@ export { UniqueDirectivesPerLocationRule } from './rules/UniqueDirectivesPerLocationRule';

@@ -5,2 +5,6 @@ export { validate } from './validate.js';

export { specifiedRules } from './specifiedRules.js';
// Spec Section: "Defer And Stream Directive Labels Are Unique"
export { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule.js';
// Spec Section: "Defer And Stream Directives Are Used On Valid Root Field"
export { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule.js';
// Spec Section: "Executable Definitions"

@@ -40,2 +44,4 @@ export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule.js';

export { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule.js';
// Spec Section: "Stream Directives Are Used On List Fields"
export { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule.js';
// Spec Section: "Argument Uniqueness"

@@ -42,0 +48,0 @@ export { UniqueArgumentNamesRule } from './rules/UniqueArgumentNamesRule.js';

@@ -20,21 +20,15 @@ import { didYouMean } from '../../jsutils/didYouMean.js';

export function KnownTypeNamesRule(context) {
const schema = context.getSchema();
const existingTypesMap = schema ? schema.getTypeMap() : Object.create(null);
const definedTypes = Object.create(null);
for (const def of context.getDocument().definitions) {
if (isTypeDefinitionNode(def)) {
definedTypes[def.name.value] = true;
}
}
const typeNames = [
const { definitions } = context.getDocument();
const existingTypesMap = context.getSchema()?.getTypeMap() ?? {};
const typeNames = new Set([
...Object.keys(existingTypesMap),
...Object.keys(definedTypes),
];
...definitions.filter(isTypeDefinitionNode).map((def) => def.name.value),
]);
return {
NamedType(node, _1, parent, _2, ancestors) {
const typeName = node.name.value;
if (!existingTypesMap[typeName] && !definedTypes[typeName]) {
if (!typeNames.has(typeName)) {
const definitionNode = ancestors[2] ?? parent;
const isSDL = definitionNode != null && isSDLNode(definitionNode);
if (isSDL && standardTypeNames.includes(typeName)) {
if (isSDL && standardTypeNames.has(typeName)) {
return;

@@ -44,3 +38,3 @@ }

typeName,
isSDL ? standardTypeNames.concat(typeNames) : typeNames,
isSDL ? [...standardTypeNames, ...typeNames] : [...typeNames],
);

@@ -57,4 +51,4 @@ context.reportError(

}
const standardTypeNames = [...specifiedScalarTypes, ...introspectionTypes].map(
(type) => type.name,
const standardTypeNames = new Set(
[...specifiedScalarTypes, ...introspectionTypes].map((type) => type.name),
);

@@ -61,0 +55,0 @@ function isSDLNode(value) {

@@ -13,3 +13,3 @@ import { GraphQLError } from '../../error/GraphQLError.js';

// are not redundantly reported.
const visitedFrags = Object.create(null);
const visitedFrags = new Set();
// Array of AST nodes used to produce meaningful errors

@@ -30,7 +30,7 @@ const spreadPath = [];

function detectCycleRecursive(fragment) {
if (visitedFrags[fragment.name.value]) {
if (visitedFrags.has(fragment.name.value)) {
return;
}
const fragmentName = fragment.name.value;
visitedFrags[fragmentName] = true;
visitedFrags.add(fragmentName);
const spreadNodes = context.getFragmentSpreads(fragment.selectionSet);

@@ -37,0 +37,0 @@ if (spreadNodes.length === 0) {

@@ -11,29 +11,23 @@ import { GraphQLError } from '../../error/GraphQLError.js';

export function NoUndefinedVariablesRule(context) {
let variableNameDefined = Object.create(null);
return {
OperationDefinition: {
enter() {
variableNameDefined = Object.create(null);
},
leave(operation) {
const usages = context.getRecursiveVariableUsages(operation);
for (const { node } of usages) {
const varName = node.name.value;
if (variableNameDefined[varName] !== true) {
context.reportError(
new GraphQLError(
operation.name
? `Variable "$${varName}" is not defined by operation "${operation.name.value}".`
: `Variable "$${varName}" is not defined.`,
{ nodes: [node, operation] },
),
);
}
OperationDefinition(operation) {
const variableNameDefined = new Set(
operation.variableDefinitions?.map((node) => node.variable.name.value),
);
const usages = context.getRecursiveVariableUsages(operation);
for (const { node } of usages) {
const varName = node.name.value;
if (!variableNameDefined.has(varName)) {
context.reportError(
new GraphQLError(
operation.name
? `Variable "$${varName}" is not defined by operation "${operation.name.value}".`
: `Variable "$${varName}" is not defined.`,
{ nodes: [node, operation] },
),
);
}
},
}
},
VariableDefinition(node) {
variableNameDefined[node.variable.name.value] = true;
},
};
}

@@ -11,7 +11,11 @@ import { GraphQLError } from '../../error/GraphQLError.js';

export function NoUnusedFragmentsRule(context) {
const operationDefs = [];
const fragmentNameUsed = new Set();
const fragmentDefs = [];
return {
OperationDefinition(node) {
operationDefs.push(node);
OperationDefinition(operation) {
for (const fragment of context.getRecursivelyReferencedFragments(
operation,
)) {
fragmentNameUsed.add(fragment.name.value);
}
return false;

@@ -25,13 +29,5 @@ },

leave() {
const fragmentNameUsed = Object.create(null);
for (const operation of operationDefs) {
for (const fragment of context.getRecursivelyReferencedFragments(
operation,
)) {
fragmentNameUsed[fragment.name.value] = true;
}
}
for (const fragmentDef of fragmentDefs) {
const fragName = fragmentDef.name.value;
if (fragmentNameUsed[fragName] !== true) {
if (!fragmentNameUsed.has(fragName)) {
context.reportError(

@@ -38,0 +34,0 @@ new GraphQLError(`Fragment "${fragName}" is never used.`, {

@@ -11,33 +11,26 @@ import { GraphQLError } from '../../error/GraphQLError.js';

export function NoUnusedVariablesRule(context) {
let variableDefs = [];
return {
OperationDefinition: {
enter() {
variableDefs = [];
},
leave(operation) {
const variableNameUsed = Object.create(null);
const usages = context.getRecursiveVariableUsages(operation);
for (const { node } of usages) {
variableNameUsed[node.name.value] = true;
OperationDefinition(operation) {
const usages = context.getRecursiveVariableUsages(operation);
const variableNameUsed = new Set(
usages.map(({ node }) => node.name.value),
);
// FIXME: https://github.com/graphql/graphql-js/issues/2203
/* c8 ignore next */
const variableDefinitions = operation.variableDefinitions ?? [];
for (const variableDef of variableDefinitions) {
const variableName = variableDef.variable.name.value;
if (!variableNameUsed.has(variableName)) {
context.reportError(
new GraphQLError(
operation.name
? `Variable "$${variableName}" is never used in operation "${operation.name.value}".`
: `Variable "$${variableName}" is never used.`,
{ nodes: variableDef },
),
);
}
for (const variableDef of variableDefs) {
const variableName = variableDef.variable.name.value;
if (variableNameUsed[variableName] !== true) {
context.reportError(
new GraphQLError(
operation.name
? `Variable "$${variableName}" is never used in operation "${operation.name.value}".`
: `Variable "$${variableName}" is never used.`,
{ nodes: variableDef },
),
);
}
}
},
}
},
VariableDefinition(def) {
variableDefs.push(def);
},
};
}

@@ -530,2 +530,12 @@ import { inspect } from '../../jsutils/inspect.js';

}
// FIXME https://github.com/graphql/graphql-js/issues/2203
const directives1 = /* c8 ignore next */ node1.directives ?? [];
const directives2 = /* c8 ignore next */ node2.directives ?? [];
if (!sameStreams(directives1, directives2)) {
return [
[responseName, 'they have differing stream directives'],
[node1],
[node2],
];
}
// The return type for each field.

@@ -578,2 +588,18 @@ const type1 = def1?.type;

}
function getStreamDirective(directives) {
return directives.find((directive) => directive.name.value === 'stream');
}
function sameStreams(directives1, directives2) {
const stream1 = getStreamDirective(directives1);
const stream2 = getStreamDirective(directives2);
if (!stream1 && !stream2) {
// both fields do not have streams
return true;
} else if (stream1 && stream2) {
// check if both fields have equivalent streams
return stringifyArguments(stream1) === stringifyArguments(stream2);
}
// fields have a mix of stream and no stream
return false;
}
// Two types conflict if both types could not apply to a value simultaneously.

@@ -618,3 +644,3 @@ // Composite types are ignored as their individual field types will be compared

const nodeAndDefs = Object.create(null);
const fragmentNames = Object.create(null);
const fragmentNames = new Set();
_collectFieldsAndFragmentNames(

@@ -627,3 +653,3 @@ context,

);
const result = [nodeAndDefs, Object.keys(fragmentNames)];
const result = [nodeAndDefs, [...fragmentNames]];
cachedFieldsAndFragmentNames.set(selectionSet, result);

@@ -677,3 +703,3 @@ return result;

case Kind.FRAGMENT_SPREAD:
fragmentNames[selection.name.value] = true;
fragmentNames.add(selection.name.value);
break;

@@ -680,0 +706,0 @@ case Kind.INLINE_FRAGMENT: {

@@ -28,3 +28,3 @@ import { GraphQLError } from '../../error/GraphQLError.js';

}
const fields = collectFields(
const { fields } = collectFields(
schema,

@@ -50,4 +50,3 @@ fragments,

for (const fieldNodes of fields.values()) {
const field = fieldNodes[0];
const fieldName = field.name.value;
const fieldName = fieldNodes[0].name.value;
if (fieldName.startsWith('__')) {

@@ -54,0 +53,0 @@ context.reportError(

@@ -0,1 +1,5 @@

// Spec Section: "Defer And Stream Directive Labels Are Unique"
import { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule.js';
// Spec Section: "Defer And Stream Directives Are Used On Valid Root Field"
import { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule.js';
// Spec Section: "Executable Definitions"

@@ -44,2 +48,4 @@ import { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule.js';

import { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule.js';
// Spec Section: "Stream Directives Are Used On List Fields"
import { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule.js';
import { UniqueArgumentDefinitionNamesRule } from './rules/UniqueArgumentDefinitionNamesRule.js';

@@ -95,2 +101,5 @@ // Spec Section: "Argument Uniqueness"

UniqueDirectivesPerLocationRule,
DeferStreamDirectiveOnRootFieldRule,
DeferStreamDirectiveLabelRule,
StreamDirectiveOnListFieldRule,
KnownArgumentNamesRule,

@@ -97,0 +106,0 @@ UniqueArgumentNamesRule,

@@ -41,3 +41,5 @@ import { GraphQLError } from '../error/GraphQLError.js';

assertValidSchema(schema);
const abortObj = Object.freeze({});
const abortError = new GraphQLError(
'Too many validation errors, error limit reached. Validation aborted.',
);
const errors = [];

@@ -50,9 +52,3 @@ const context = new ValidationContext(

if (errors.length >= maxErrors) {
errors.push(
new GraphQLError(
'Too many validation errors, error limit reached. Validation aborted.',
),
);
// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw abortObj;
throw abortError;
}

@@ -69,3 +65,5 @@ errors.push(error);

} catch (e) {
if (e !== abortObj) {
if (e === abortError) {
errors.push(abortError);
} else {
throw e;

@@ -72,0 +70,0 @@ }

@@ -64,3 +64,3 @@ import { Kind } from '../language/kinds.js';

fragments = [];
const collectedNames = Object.create(null);
const collectedNames = new Set();
const nodesToVisit = [operation.selectionSet];

@@ -71,4 +71,4 @@ let node;

const fragName = spread.name.value;
if (collectedNames[fragName] !== true) {
collectedNames[fragName] = true;
if (!collectedNames.has(fragName)) {
collectedNames.add(fragName);
const fragment = this.getFragment(fragName);

@@ -75,0 +75,0 @@ if (fragment) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc