diff --git a/package.json b/package.json index 6bb8d034d38..566c293b8e3 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,12 @@ "test:double-dependency": "npm run build > /dev/null && mocha -r ts-node/register --full-trace src/__tests__/double-dependency.test.ts; rm -rf ./dist1", "lint": "eslint --cache --report-unused-disable-directives src resources", "benchmark": "node --noconcurrent_sweeping --expose-gc --predictable ./resources/benchmark.js", - "prettier": "prettier --ignore-path .gitignore --write --list-different \"**/*.{js,md,json,yml}\"", - "prettier:check": "prettier --ignore-path .gitignore --check \"**/*.{js,md,json,yml}\"", + "prettier": "prettier --ignore-path .gitignore --write --list-different \"**/*.{js,ts,md,json,yml}\"", + "prettier:check": "prettier --ignore-path .gitignore --check \"**/*.{js,ts,md,json,yml}\"", "check": "npm run check:flow && npm run check:tsc", "check:flow": "flow check", - "check:tsc": "tsc", + "check:ts": "tsc", + "check:dts": "dtslint tstypes", "check:cover": "node resources/check-cover.js && nyc report --nycrc-path .nycflowrc.yml", "build": "tsc -b tsconfig.build.json && node resources/build.js", "changelog": "node resources/gen-changelog.js", @@ -61,6 +62,7 @@ "@types/shelljs": "^0.8.5", "babel-eslint": "10.0.2", "chai": "4.2.0", + "dtslint": "^0.8.0", "eslint": "5.16.0", "eslint-plugin-flowtype": "3.12.1", "flow-bin": "0.105.1", diff --git a/resources/build.js b/resources/build.js index 49eee88afd8..2e4021f00ac 100644 --- a/resources/build.js +++ b/resources/build.js @@ -45,6 +45,16 @@ if (require.main === module) { } } + const tsFiles = readdirRecursive('./tstypes', { ignoreDir: /^__.*__$/ }); + for (const filepath of tsFiles) { + if (filepath.endsWith('.d.ts')) { + const srcPath = path.join('./tstypes', filepath); + const destPath = path.join('./dist', filepath); + + copyFile(srcPath, destPath); + } + } + const packageJSON = buildPackageJSON(); assert( packageJSON.version === require('../dist/version').version, diff --git a/tstypes/error/GraphQLError.d.ts b/tstypes/error/GraphQLError.d.ts new file mode 100644 index 00000000000..948007b5477 --- /dev/null +++ b/tstypes/error/GraphQLError.d.ts @@ -0,0 +1,78 @@ +import Maybe from '../tsutils/Maybe'; +import { getLocation } from '../language'; +import { ASTNode } from '../language/ast'; +import { Source } from '../language/source'; +import { SourceLocation } from '../language/location'; + +/** + * A GraphQLError describes an Error found during the parse, validate, or + * execute phases of performing a GraphQL operation. In addition to a message + * and stack trace, it also includes information about the locations in a + * GraphQL document and/or execution result that correspond to the Error. + */ +export class GraphQLError extends Error { + /** + * A message describing the Error for debugging purposes. + * + * Enumerable, and appears in the result of JSON.stringify(). + * + * Note: should be treated as readonly, despite invariant usage. + */ + message: string; + + /** + * An array of { line, column } locations within the source GraphQL document + * which correspond to this error. + * + * Errors during validation often contain multiple locations, for example to + * point out two things with the same name. Errors during execution include a + * single location, the field which produced the error. + * + * Enumerable, and appears in the result of JSON.stringify(). + */ + readonly locations: ReadonlyArray | undefined; + + /** + * An array describing the JSON-path into the execution response which + * corresponds to this error. Only included for errors during execution. + * + * Enumerable, and appears in the result of JSON.stringify(). + */ + readonly path: ReadonlyArray | undefined; + + /** + * An array of GraphQL AST Nodes corresponding to this error. + */ + readonly nodes: ReadonlyArray | undefined; + + /** + * The source GraphQL document corresponding to this error. + */ + readonly source: Source | undefined; + + /** + * An array of character offsets within the source GraphQL document + * which correspond to this error. + */ + readonly positions: ReadonlyArray | undefined; + + /** + * The original error thrown from a field resolver during execution. + */ + readonly originalError: Maybe; + + /** + * Extension fields to add to the formatted error. + */ + readonly extensions: { [key: string]: any } | undefined; + + constructor( + message: string, + nodes?: ReadonlyArray | ASTNode | undefined, + source?: Maybe, + positions?: Maybe>, + path?: Maybe>, + originalError?: Maybe, + extensions?: Maybe<{ [key: string]: any }>, + ); +} diff --git a/tstypes/error/formatError.d.ts b/tstypes/error/formatError.d.ts new file mode 100644 index 00000000000..ce2a206b4e8 --- /dev/null +++ b/tstypes/error/formatError.d.ts @@ -0,0 +1,39 @@ +import { GraphQLError } from './GraphQLError'; +import { SourceLocation } from '../language/location'; + +/** + * Given a GraphQLError, format it according to the rules described by the + * Response Format, Errors section of the GraphQL Specification. + */ +export function formatError(error: GraphQLError): GraphQLFormattedError; + +/** + * @see https://github.com/graphql/graphql-spec/blob/master/spec/Section%207%20--%20Response.md#errors + */ +export interface GraphQLFormattedError< + TExtensions extends Record = Record +> { + /** + * A short, human-readable summary of the problem that **SHOULD NOT** change + * from occurrence to occurrence of the problem, except for purposes of + * localization. + */ + readonly message: string; + /** + * If an error can be associated to a particular point in the requested + * GraphQL document, it should contain a list of locations. + */ + readonly locations?: ReadonlyArray; + /** + * If an error can be associated to a particular field in the GraphQL result, + * it _must_ contain an entry with the key `path` that details the path of + * the response field which experienced the error. This allows clients to + * identify whether a null result is intentional or caused by a runtime error. + */ + readonly path?: ReadonlyArray; + /** + * Reserved for implementors to extend the protocol however they see fit, + * and hence there are no additional restrictions on its contents. + */ + readonly extensions?: TExtensions; +} diff --git a/tstypes/error/index.d.ts b/tstypes/error/index.d.ts new file mode 100644 index 00000000000..b43bcdee005 --- /dev/null +++ b/tstypes/error/index.d.ts @@ -0,0 +1,5 @@ +export { GraphQLError } from './GraphQLError'; +export { syntaxError } from './syntaxError'; +export { locatedError } from './locatedError'; +export { printError } from './printError'; +export { formatError, GraphQLFormattedError } from './formatError'; diff --git a/tstypes/error/locatedError.d.ts b/tstypes/error/locatedError.d.ts new file mode 100644 index 00000000000..8573638680c --- /dev/null +++ b/tstypes/error/locatedError.d.ts @@ -0,0 +1,13 @@ +import { GraphQLError } from './GraphQLError'; +import { ASTNode } from '../language/ast'; + +/** + * Given an arbitrary Error, presumably thrown while attempting to execute a + * GraphQL operation, produce a new GraphQLError aware of the location in the + * document responsible for the original Error. + */ +export function locatedError( + originalError: Error | GraphQLError, + nodes: ReadonlyArray, + path: ReadonlyArray, +): GraphQLError; diff --git a/tstypes/error/printError.d.ts b/tstypes/error/printError.d.ts new file mode 100644 index 00000000000..d3a2036be6c --- /dev/null +++ b/tstypes/error/printError.d.ts @@ -0,0 +1,7 @@ +import { GraphQLError } from './GraphQLError'; + +/** + * Prints a GraphQLError to a string, representing useful location information + * about the error's position in the source. + */ +export function printError(error: GraphQLError): string; diff --git a/tstypes/error/syntaxError.d.ts b/tstypes/error/syntaxError.d.ts new file mode 100644 index 00000000000..ccf84044ca1 --- /dev/null +++ b/tstypes/error/syntaxError.d.ts @@ -0,0 +1,12 @@ +import { Source } from '../language/source'; +import { GraphQLError } from './GraphQLError'; + +/** + * Produces a GraphQLError representing a syntax error, containing useful + * descriptive information about the syntax error's position in the source. + */ +export function syntaxError( + source: Source, + position: number, + description: string, +): GraphQLError; diff --git a/tstypes/execution/execute.d.ts b/tstypes/execution/execute.d.ts new file mode 100644 index 00000000000..e6e46329117 --- /dev/null +++ b/tstypes/execution/execute.d.ts @@ -0,0 +1,189 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLError, locatedError } from '../error'; +import { GraphQLSchema } from '../type/schema'; +import { + GraphQLField, + GraphQLFieldResolver, + ResponsePath, + GraphQLObjectType, + GraphQLResolveInfo, +} from '../type/definition'; +import { + DirectiveNode, + DocumentNode, + OperationDefinitionNode, + SelectionSetNode, + FieldNode, + InlineFragmentNode, + FragmentDefinitionNode, +} from '../language/ast'; +import { PromiseOrValue } from '../jsutils/PromiseOrValue'; + +/** + * Data that must be available at all points during query execution. + * + * Namely, schema of the type system that is currently executing, + * and the fragments defined in the query document + */ +export interface ExecutionContext { + schema: GraphQLSchema; + fragments: { [key: string]: FragmentDefinitionNode }; + rootValue: any; + contextValue: any; + operation: OperationDefinitionNode; + variableValues: { [key: string]: any }; + fieldResolver: GraphQLFieldResolver; + errors: GraphQLError[]; +} + +export interface ExecutionResultDataDefault { + [key: string]: any; +} + +/** + * The result of GraphQL execution. + * + * - `errors` is included when any errors occurred as a non-empty array. + * - `data` is the result of a successful execution of the query. + */ +export interface ExecutionResult { + errors?: ReadonlyArray; + data?: TData; +} + +export type ExecutionArgs = { + schema: GraphQLSchema; + document: DocumentNode; + rootValue?: any; + contextValue?: any; + variableValues?: Maybe<{ [key: string]: any }>; + operationName?: Maybe; + fieldResolver?: Maybe>; +}; + +/** + * Implements the "Evaluating requests" section of the GraphQL specification. + * + * Returns either a synchronous ExecutionResult (if all encountered resolvers + * are synchronous), or a Promise of an ExecutionResult that will eventually be + * resolved and never rejected. + * + * If the arguments to this function do not result in a legal execution context, + * a GraphQLError will be thrown immediately explaining the invalid input. + * + * Accepts either an object with named arguments, or individual arguments. + */ +export function execute( + args: ExecutionArgs, +): PromiseOrValue>; +export function execute( + schema: GraphQLSchema, + document: DocumentNode, + rootValue?: any, + contextValue?: any, + variableValues?: Maybe<{ [key: string]: any }>, + operationName?: Maybe, + fieldResolver?: Maybe>, +): PromiseOrValue>; + +/** + * Given a ResponsePath (found in the `path` entry in the information provided + * as the last argument to a field resolver), return an Array of the path keys. + */ +export function responsePathAsArray( + path: ResponsePath, +): ReadonlyArray; + +/** + * Given a ResponsePath and a key, return a new ResponsePath containing the + * new key. + + */ +export function addPath( + prev: ResponsePath | undefined, + key: string | number, +): { prev: ResponsePath | undefined; key: string | number }; + +/** + * Essential assertions before executing to provide developer feedback for + * improper use of the GraphQL library. + */ +export function assertValidExecutionArguments( + schema: GraphQLSchema, + document: DocumentNode, + rawVariableValues: Maybe<{ [key: string]: any }>, +): void; + +/** + * Constructs a ExecutionContext object from the arguments passed to + * execute, which we will pass throughout the other execution methods. + * + * Throws a GraphQLError if a valid execution context cannot be created. + */ +export function buildExecutionContext( + schema: GraphQLSchema, + document: DocumentNode, + rootValue: any, + contextValue: any, + rawVariableValues: Maybe<{ [key: string]: any }>, + operationName: Maybe, + fieldResolver: Maybe>, +): ReadonlyArray | ExecutionContext; + +/** + * Given a selectionSet, adds all of the fields in that selection to + * the passed in map of fields, and returns it at the end. + * + * CollectFields requires the "runtime type" of an object. For a field which + * returns an Interface or Union type, the "runtime type" will be the actual + * Object type returned by that field. + */ +export function collectFields( + exeContext: ExecutionContext, + runtimeType: GraphQLObjectType, + selectionSet: SelectionSetNode, + fields: { [key: string]: Array }, + visitedFragmentNames: { [key: string]: boolean }, +): { [key: string]: Array }; + +export function buildResolveInfo( + exeContext: ExecutionContext, + fieldDef: GraphQLField, + fieldNodes: ReadonlyArray, + parentType: GraphQLObjectType, + path: ResponsePath, +): GraphQLResolveInfo; + +// Isolates the "ReturnOrAbrupt" behavior to not de-opt the `resolveField` +// function. Returns the result of resolveFn or the abrupt-return Error object. +export function resolveFieldValueOrError( + exeContext: ExecutionContext, + fieldDef: GraphQLField, + fieldNodes: ReadonlyArray, + resolveFn: GraphQLFieldResolver, + source: TSource, + info: GraphQLResolveInfo, +): Error | any; + +/** + * If a resolve function is not given, then a default resolve behavior is used + * which takes the property of the source object of the same name as the field + * and returns it as the result, or if it's a function, returns the result + * of calling that function while passing along args and context. + */ +export const defaultFieldResolver: GraphQLFieldResolver; + +/** + * This method looks up the field on the given type defintion. + * It has special casing for the two introspection fields, __schema + * and __typename. __typename is special because it can always be + * queried as a field, even in situations where no other fields + * are allowed, like on a Union. __schema could get automatically + * added to the query type, but that would require mutating type + * definitions, which would cause issues. + */ +export function getFieldDef( + schema: GraphQLSchema, + parentType: GraphQLObjectType, + fieldName: string, +): Maybe>; diff --git a/tstypes/execution/index.d.ts b/tstypes/execution/index.d.ts new file mode 100644 index 00000000000..a5c4980c0a1 --- /dev/null +++ b/tstypes/execution/index.d.ts @@ -0,0 +1,9 @@ +export { + execute, + defaultFieldResolver, + responsePathAsArray, + ExecutionArgs, + ExecutionResult, +} from './execute'; + +export { getDirectiveValues } from './values'; diff --git a/tstypes/execution/values.d.ts b/tstypes/execution/values.d.ts new file mode 100644 index 00000000000..3a7398f76f4 --- /dev/null +++ b/tstypes/execution/values.d.ts @@ -0,0 +1,67 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLError } from '../error/GraphQLError'; +import { + GraphQLInputType, + GraphQLField, + GraphQLArgument, +} from '../type/definition'; +import { GraphQLDirective } from '../type/directives'; +import { GraphQLSchema } from '../type/schema'; +import { + FieldNode, + DirectiveNode, + VariableDefinitionNode, +} from '../language/ast'; + +interface CoercedVariableValues { + errors: ReadonlyArray | undefined; + coerced: { [key: string]: any } | undefined; +} + +/** + * Prepares an object map of variableValues of the correct type based on the + * provided variable definitions and arbitrary input. If the input cannot be + * parsed to match the variable definitions, a GraphQLError will be thrown. + * + * Note: The returned value is a plain Object with a prototype, since it is + * exposed to user code. Care should be taken to not pull values from the + * Object prototype. + */ +export function getVariableValues( + schema: GraphQLSchema, + varDefNodes: VariableDefinitionNode[], + inputs: { [key: string]: any }, +): CoercedVariableValues; + +/** + * Prepares an object map of argument values given a list of argument + * definitions and list of argument AST nodes. + * + * Note: The returned value is a plain Object with a prototype, since it is + * exposed to user code. Care should be taken to not pull values from the + * Object prototype. + */ +export function getArgumentValues( + def: GraphQLField | GraphQLDirective, + node: FieldNode | DirectiveNode, + variableValues?: Maybe<{ [key: string]: any }>, +): { [key: string]: any }; + +/** + * Prepares an object map of argument values given a directive definition + * and a AST node which may contain directives. Optionally also accepts a map + * of variable values. + * + * If the directive does not exist on the node, returns undefined. + * + * Note: The returned value is a plain Object with a prototype, since it is + * exposed to user code. Care should be taken to not pull values from the + * Object prototype. + */ +export function getDirectiveValues( + directiveDef: GraphQLDirective, + node: { + readonly directives?: ReadonlyArray; + }, + variableValues?: Maybe<{ [key: string]: any }>, +): undefined | { [key: string]: any }; diff --git a/tstypes/graphql.d.ts b/tstypes/graphql.d.ts new file mode 100644 index 00000000000..a1c43c0d5fc --- /dev/null +++ b/tstypes/graphql.d.ts @@ -0,0 +1,85 @@ +import Maybe from './tsutils/Maybe'; +import { Source } from './language/source'; +import { GraphQLFieldResolver } from './type/definition'; +import { GraphQLSchema } from './type/schema'; +import { + ExecutionResult, + ExecutionResultDataDefault, +} from './execution/execute'; + +/** + * This is the primary entry point function for fulfilling GraphQL operations + * by parsing, validating, and executing a GraphQL document along side a + * GraphQL schema. + * + * More sophisticated GraphQL servers, such as those which persist queries, + * may wish to separate the validation and execution phases to a static time + * tooling step, and a server runtime step. + * + * Accepts either an object with named arguments, or individual arguments: + * + * schema: + * The GraphQL type system to use when validating and executing a query. + * source: + * A GraphQL language formatted string representing the requested operation. + * rootValue: + * The value provided as the first argument to resolver functions on the top + * level type (e.g. the query object type). + * contextValue: + * The context value is provided as an argument to resolver functions after + * field arguments. It is used to pass shared information useful at any point + * during executing this query, for example the currently logged in user and + * connections to databases or other services. + * variableValues: + * A mapping of variable name to runtime value to use for all variables + * defined in the requestString. + * operationName: + * The name of the operation to use if requestString contains multiple + * possible operations. Can be omitted if requestString contains only + * one operation. + * fieldResolver: + * A resolver function to use when one is not provided by the schema. + * If not provided, the default field resolver is used (which looks for a + * value or method on the source value with the field's name). + */ +export interface GraphQLArgs { + schema: GraphQLSchema; + source: Source | string; + rootValue?: any; + contextValue?: any; + variableValues?: Maybe<{ [key: string]: any }>; + operationName?: Maybe; + fieldResolver?: Maybe>; +} + +export function graphql( + args: GraphQLArgs, +): Promise>; +export function graphql( + schema: GraphQLSchema, + source: Source | string, + rootValue?: any, + contextValue?: any, + variableValues?: Maybe<{ [key: string]: any }>, + operationName?: Maybe, + fieldResolver?: Maybe>, +): Promise>; + +/** + * The graphqlSync function also fulfills GraphQL operations by parsing, + * validating, and executing a GraphQL document along side a GraphQL schema. + * However, it guarantees to complete synchronously (or throw an error) assuming + * that all field resolvers are also synchronous. + */ +export function graphqlSync( + args: GraphQLArgs, +): ExecutionResult; +export function graphqlSync( + schema: GraphQLSchema, + source: Source | string, + rootValue?: any, + contextValue?: any, + variableValues?: Maybe<{ [key: string]: any }>, + operationName?: Maybe, + fieldResolver?: Maybe>, +): ExecutionResult; diff --git a/tstypes/index.d.ts b/tstypes/index.d.ts new file mode 100644 index 00000000000..f9a5acbdd74 --- /dev/null +++ b/tstypes/index.d.ts @@ -0,0 +1,393 @@ +// TypeScript Version: 2.6 + +// The primary entry point into fulfilling a GraphQL request. +export { graphql, graphqlSync, GraphQLArgs } from './graphql'; + +// Create and operate on GraphQL type definitions and schema. +export { + GraphQLSchema, + // Definitions + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLDirective, + // "Enum" of Type Kinds + TypeKind, + // Scalars + specifiedScalarTypes, + GraphQLInt, + GraphQLFloat, + GraphQLString, + GraphQLBoolean, + GraphQLID, + // Built-in Directives defined by the Spec + specifiedDirectives, + GraphQLIncludeDirective, + GraphQLSkipDirective, + GraphQLDeprecatedDirective, + // Constant Deprecation Reason + DEFAULT_DEPRECATION_REASON, + // Meta-field definitions. + SchemaMetaFieldDef, + TypeMetaFieldDef, + TypeNameMetaFieldDef, + // GraphQL Types for introspection. + introspectionTypes, + __Schema, + __Directive, + __DirectiveLocation, + __Type, + __Field, + __InputValue, + __EnumValue, + __TypeKind, + // Predicates + isSchema, + isDirective, + isType, + isScalarType, + isObjectType, + isInterfaceType, + isUnionType, + isEnumType, + isInputObjectType, + isListType, + isNonNullType, + isInputType, + isOutputType, + isLeafType, + isCompositeType, + isAbstractType, + isWrappingType, + isNullableType, + isNamedType, + isRequiredArgument, + isRequiredInputField, + isSpecifiedScalarType, + isIntrospectionType, + isSpecifiedDirective, + // Assertions + assertType, + assertScalarType, + assertObjectType, + assertInterfaceType, + assertUnionType, + assertEnumType, + assertInputObjectType, + assertListType, + assertNonNullType, + assertInputType, + assertOutputType, + assertLeafType, + assertCompositeType, + assertAbstractType, + assertWrappingType, + assertNullableType, + assertNamedType, + // Un-modifiers + getNullableType, + getNamedType, + // Validate GraphQL schema. + validateSchema, + assertValidSchema, + // type + GraphQLType, + GraphQLInputType, + GraphQLOutputType, + GraphQLLeafType, + GraphQLCompositeType, + GraphQLAbstractType, + GraphQLWrappingType, + GraphQLNullableType, + GraphQLNamedType, + Thunk, + GraphQLSchemaConfig, + GraphQLArgument, + GraphQLArgumentConfig, + GraphQLEnumTypeConfig, + GraphQLEnumValue, + GraphQLEnumValueConfig, + GraphQLEnumValueConfigMap, + GraphQLField, + GraphQLFieldConfig, + GraphQLFieldConfigArgumentMap, + GraphQLFieldConfigMap, + GraphQLFieldMap, + GraphQLFieldResolver, + GraphQLInputField, + GraphQLInputFieldConfig, + GraphQLInputFieldConfigMap, + GraphQLInputFieldMap, + GraphQLInputObjectTypeConfig, + GraphQLInterfaceTypeConfig, + GraphQLIsTypeOfFn, + GraphQLObjectTypeConfig, + GraphQLResolveInfo, + ResponsePath, + GraphQLScalarTypeConfig, + GraphQLTypeResolver, + GraphQLUnionTypeConfig, + GraphQLDirectiveConfig, + GraphQLScalarSerializer, + GraphQLScalarValueParser, + GraphQLScalarLiteralParser, +} from './type'; + +// Parse and operate on GraphQL language source files. +export { + Source, + getLocation, + // Parse + parse, + parseValue, + parseType, + // Print + print, + // Visit + visit, + visitInParallel, + visitWithTypeInfo, + getVisitFn, + Kind, + TokenKind, + DirectiveLocation, + BREAK, + // Predicates + isDefinitionNode, + isExecutableDefinitionNode, + isSelectionNode, + isValueNode, + isTypeNode, + isTypeSystemDefinitionNode, + isTypeDefinitionNode, + isTypeSystemExtensionNode, + isTypeExtensionNode, + // type + Lexer, + ParseOptions, + SourceLocation, + // Visitor utilities + ASTVisitor, + Visitor, + VisitFn, + VisitorKeyMap, + // AST nodes + Location, + Token, + ASTNode, + ASTKindToNode, + NameNode, + DocumentNode, + DefinitionNode, + ExecutableDefinitionNode, + OperationDefinitionNode, + OperationTypeNode, + VariableDefinitionNode, + VariableNode, + SelectionSetNode, + SelectionNode, + FieldNode, + ArgumentNode, + FragmentSpreadNode, + InlineFragmentNode, + FragmentDefinitionNode, + ValueNode, + IntValueNode, + FloatValueNode, + StringValueNode, + BooleanValueNode, + NullValueNode, + EnumValueNode, + ListValueNode, + ObjectValueNode, + ObjectFieldNode, + DirectiveNode, + TypeNode, + NamedTypeNode, + ListTypeNode, + NonNullTypeNode, + TypeSystemDefinitionNode, + SchemaDefinitionNode, + OperationTypeDefinitionNode, + TypeDefinitionNode, + ScalarTypeDefinitionNode, + ObjectTypeDefinitionNode, + FieldDefinitionNode, + InputValueDefinitionNode, + InterfaceTypeDefinitionNode, + UnionTypeDefinitionNode, + EnumTypeDefinitionNode, + EnumValueDefinitionNode, + InputObjectTypeDefinitionNode, + DirectiveDefinitionNode, + TypeSystemExtensionNode, + SchemaExtensionNode, + TypeExtensionNode, + ScalarTypeExtensionNode, + ObjectTypeExtensionNode, + InterfaceTypeExtensionNode, + UnionTypeExtensionNode, + EnumTypeExtensionNode, + InputObjectTypeExtensionNode, + KindEnum, + TokenKindEnum, + DirectiveLocationEnum, +} from './language'; + +// Execute GraphQL queries. +export { + execute, + defaultFieldResolver, + responsePathAsArray, + getDirectiveValues, + // type + ExecutionArgs, + ExecutionResult, +} from './execution'; + +export { subscribe, createSourceEventStream } from './subscription'; + +// Validate GraphQL queries. +export { + validate, + ValidationContext, + // All validation rules in the GraphQL Specification. + specifiedRules, + // Individual validation rules. + FieldsOnCorrectTypeRule, + FragmentsOnCompositeTypesRule, + KnownArgumentNamesRule, + KnownDirectivesRule, + KnownFragmentNamesRule, + KnownTypeNamesRule, + LoneAnonymousOperationRule, + NoFragmentCyclesRule, + NoUndefinedVariablesRule, + NoUnusedFragmentsRule, + NoUnusedVariablesRule, + OverlappingFieldsCanBeMergedRule, + PossibleFragmentSpreadsRule, + ProvidedRequiredArgumentsRule, + ScalarLeafsRule, + SingleFieldSubscriptionsRule, + UniqueArgumentNamesRule, + UniqueDirectivesPerLocationRule, + UniqueFragmentNamesRule, + UniqueInputFieldNamesRule, + UniqueOperationNamesRule, + UniqueVariableNamesRule, + ValuesOfCorrectTypeRule, + VariablesAreInputTypesRule, + VariablesInAllowedPositionRule, +} from './validation'; + +// Create and format GraphQL errors. +export { + GraphQLError, + formatError, + printError, + GraphQLFormattedError, +} from './error'; + +// Utilities for operating on GraphQL type schema and parsed sources. +export { + // Produce the GraphQL query recommended for a full schema introspection. + // Accepts optional IntrospectionOptions. + getIntrospectionQuery, + // @deprecated: use getIntrospectionQuery - will be removed in v15 + introspectionQuery, + // Gets the target Operation from a Document + getOperationAST, + // Gets the Type for the target Operation AST. + getOperationRootType, + // Convert a GraphQLSchema to an IntrospectionQuery + introspectionFromSchema, + // Build a GraphQLSchema from an introspection result. + buildClientSchema, + // Build a GraphQLSchema from a parsed GraphQL Schema language AST. + buildASTSchema, + // Build a GraphQLSchema from a GraphQL schema language document. + buildSchema, + // @deprecated: Get the description from a schema AST node and supports legacy + // syntax for specifying descriptions - will be removed in v16 + getDescription, + // Extends an existing GraphQLSchema from a parsed GraphQL Schema + // language AST. + extendSchema, + // Sort a GraphQLSchema. + lexicographicSortSchema, + // Print a GraphQLSchema to GraphQL Schema language. + printSchema, + // Prints the built-in introspection schema in the Schema Language + // format. + printIntrospectionSchema, + // Print a GraphQLType to GraphQL Schema language. + printType, + // Create a GraphQLType from a GraphQL language AST. + typeFromAST, + // Create a JavaScript value from a GraphQL language AST with a Type. + valueFromAST, + // Create a JavaScript value from a GraphQL language AST without a Type. + valueFromASTUntyped, + // Create a GraphQL language AST from a JavaScript value. + astFromValue, + // A helper to use within recursive-descent visitors which need to be aware of + // the GraphQL type system. + TypeInfo, + // Coerces a JavaScript value to a GraphQL type, or produces errors. + coerceValue, + // @deprecated use coerceValue - will be removed in v15 + isValidJSValue, + // @deprecated use validation - will be removed in v15 + isValidLiteralValue, + // Concatenates multiple AST together. + concatAST, + // Separates an AST into an AST per Operation. + separateOperations, + // Comparators for types + isEqualType, + isTypeSubTypeOf, + doTypesOverlap, + // Asserts a string is a valid GraphQL name. + assertValidName, + // Determine if a string is a valid GraphQL name. + isValidNameError, + // Compares two GraphQLSchemas and detects breaking changes. + findBreakingChanges, + findDangerousChanges, + BreakingChangeType, + DangerousChangeType, + // Report all deprecated usage within a GraphQL document. + findDeprecatedUsages, + // type + BuildSchemaOptions, + BreakingChange, + DangerousChange, + IntrospectionOptions, + IntrospectionDirective, + IntrospectionEnumType, + IntrospectionEnumValue, + IntrospectionField, + IntrospectionInputObjectType, + IntrospectionInputType, + IntrospectionInputTypeRef, + IntrospectionInputValue, + IntrospectionInterfaceType, + IntrospectionListTypeRef, + IntrospectionNamedTypeRef, + IntrospectionNonNullTypeRef, + IntrospectionObjectType, + IntrospectionOutputType, + IntrospectionOutputTypeRef, + IntrospectionQuery, + IntrospectionScalarType, + IntrospectionSchema, + IntrospectionType, + IntrospectionTypeRef, + IntrospectionUnionType, +} from './utilities'; diff --git a/tstypes/jsutils/PromiseOrValue.d.ts b/tstypes/jsutils/PromiseOrValue.d.ts new file mode 100644 index 00000000000..6b2517ee625 --- /dev/null +++ b/tstypes/jsutils/PromiseOrValue.d.ts @@ -0,0 +1 @@ +export type PromiseOrValue = Promise | T; diff --git a/tstypes/language/ast.d.ts b/tstypes/language/ast.d.ts new file mode 100644 index 00000000000..5721080c206 --- /dev/null +++ b/tstypes/language/ast.d.ts @@ -0,0 +1,573 @@ +import { Source } from './source'; +import { TokenKindEnum } from './lexer'; + +/** + * Contains a range of UTF-8 character offsets and token references that + * identify the region of the source from which the AST derived. + */ +export interface Location { + /** + * The character offset at which this Node begins. + */ + readonly start: number; + + /** + * The character offset at which this Node ends. + */ + readonly end: number; + + /** + * The Token at which this Node begins. + */ + readonly startToken: Token; + + /** + * The Token at which this Node ends. + */ + readonly endToken: Token; + + /** + * The Source document the AST represents. + */ + readonly source: Source; +} + +/** + * Represents a range of characters represented by a lexical token + * within a Source. + */ +export interface Token { + /** + * The kind of Token. + */ + readonly kind: TokenKindEnum; + + /** + * The character offset at which this Node begins. + */ + readonly start: number; + + /** + * The character offset at which this Node ends. + */ + readonly end: number; + + /** + * The 1-indexed line number on which this Token appears. + */ + readonly line: number; + + /** + * The 1-indexed column number at which this Token begins. + */ + readonly column: number; + + /** + * For non-punctuation tokens, represents the interpreted value of the token. + */ + readonly value: string | undefined; + + /** + * Tokens exist as nodes in a double-linked-list amongst all tokens + * including ignored tokens. is always the first node and + * the last. + */ + readonly prev: Token | null; + readonly next: Token | null; +} + +/** + * The list of all possible AST node types. + */ +export type ASTNode = + | NameNode + | DocumentNode + | OperationDefinitionNode + | VariableDefinitionNode + | VariableNode + | SelectionSetNode + | FieldNode + | ArgumentNode + | FragmentSpreadNode + | InlineFragmentNode + | FragmentDefinitionNode + | IntValueNode + | FloatValueNode + | StringValueNode + | BooleanValueNode + | NullValueNode + | EnumValueNode + | ListValueNode + | ObjectValueNode + | ObjectFieldNode + | DirectiveNode + | NamedTypeNode + | ListTypeNode + | NonNullTypeNode + | SchemaDefinitionNode + | OperationTypeDefinitionNode + | ScalarTypeDefinitionNode + | ObjectTypeDefinitionNode + | FieldDefinitionNode + | InputValueDefinitionNode + | InterfaceTypeDefinitionNode + | UnionTypeDefinitionNode + | EnumTypeDefinitionNode + | EnumValueDefinitionNode + | InputObjectTypeDefinitionNode + | DirectiveDefinitionNode + | SchemaExtensionNode + | ScalarTypeExtensionNode + | ObjectTypeExtensionNode + | InterfaceTypeExtensionNode + | UnionTypeExtensionNode + | EnumTypeExtensionNode + | InputObjectTypeExtensionNode; + +/** + * Utility type listing all nodes indexed by their kind. + */ +export interface ASTKindToNode { + Name: NameNode; + Document: DocumentNode; + OperationDefinition: OperationDefinitionNode; + VariableDefinition: VariableDefinitionNode; + Variable: VariableNode; + SelectionSet: SelectionSetNode; + Field: FieldNode; + Argument: ArgumentNode; + FragmentSpread: FragmentSpreadNode; + InlineFragment: InlineFragmentNode; + FragmentDefinition: FragmentDefinitionNode; + IntValue: IntValueNode; + FloatValue: FloatValueNode; + StringValue: StringValueNode; + BooleanValue: BooleanValueNode; + NullValue: NullValueNode; + EnumValue: EnumValueNode; + ListValue: ListValueNode; + ObjectValue: ObjectValueNode; + ObjectField: ObjectFieldNode; + Directive: DirectiveNode; + NamedType: NamedTypeNode; + ListType: ListTypeNode; + NonNullType: NonNullTypeNode; + SchemaDefinition: SchemaDefinitionNode; + OperationTypeDefinition: OperationTypeDefinitionNode; + ScalarTypeDefinition: ScalarTypeDefinitionNode; + ObjectTypeDefinition: ObjectTypeDefinitionNode; + FieldDefinition: FieldDefinitionNode; + InputValueDefinition: InputValueDefinitionNode; + InterfaceTypeDefinition: InterfaceTypeDefinitionNode; + UnionTypeDefinition: UnionTypeDefinitionNode; + EnumTypeDefinition: EnumTypeDefinitionNode; + EnumValueDefinition: EnumValueDefinitionNode; + InputObjectTypeDefinition: InputObjectTypeDefinitionNode; + DirectiveDefinition: DirectiveDefinitionNode; + SchemaExtension: SchemaExtensionNode; + ScalarTypeExtension: ScalarTypeExtensionNode; + ObjectTypeExtension: ObjectTypeExtensionNode; + InterfaceTypeExtension: InterfaceTypeExtensionNode; + UnionTypeExtension: UnionTypeExtensionNode; + EnumTypeExtension: EnumTypeExtensionNode; + InputObjectTypeExtension: InputObjectTypeExtensionNode; +} + +// Name + +export interface NameNode { + readonly kind: 'Name'; + readonly loc?: Location; + readonly value: string; +} + +// Document + +export interface DocumentNode { + readonly kind: 'Document'; + readonly loc?: Location; + readonly definitions: ReadonlyArray; +} + +export type DefinitionNode = + | ExecutableDefinitionNode + | TypeSystemDefinitionNode + | TypeSystemExtensionNode; + +export type ExecutableDefinitionNode = + | OperationDefinitionNode + | FragmentDefinitionNode; + +export interface OperationDefinitionNode { + readonly kind: 'OperationDefinition'; + readonly loc?: Location; + readonly operation: OperationTypeNode; + readonly name?: NameNode; + readonly variableDefinitions?: ReadonlyArray; + readonly directives?: ReadonlyArray; + readonly selectionSet: SelectionSetNode; +} + +export type OperationTypeNode = 'query' | 'mutation' | 'subscription'; + +export interface VariableDefinitionNode { + readonly kind: 'VariableDefinition'; + readonly loc?: Location; + readonly variable: VariableNode; + readonly type: TypeNode; + readonly defaultValue?: ValueNode; + readonly directives?: ReadonlyArray; +} + +export interface VariableNode { + readonly kind: 'Variable'; + readonly loc?: Location; + readonly name: NameNode; +} + +export interface SelectionSetNode { + kind: 'SelectionSet'; + loc?: Location; + selections: ReadonlyArray; +} + +export type SelectionNode = FieldNode | FragmentSpreadNode | InlineFragmentNode; + +export interface FieldNode { + readonly kind: 'Field'; + readonly loc?: Location; + readonly alias?: NameNode; + readonly name: NameNode; + readonly arguments?: ReadonlyArray; + readonly directives?: ReadonlyArray; + readonly selectionSet?: SelectionSetNode; +} + +export interface ArgumentNode { + readonly kind: 'Argument'; + readonly loc?: Location; + readonly name: NameNode; + readonly value: ValueNode; +} + +// Fragments + +export interface FragmentSpreadNode { + readonly kind: 'FragmentSpread'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; +} + +export interface InlineFragmentNode { + readonly kind: 'InlineFragment'; + readonly loc?: Location; + readonly typeCondition?: NamedTypeNode; + readonly directives?: ReadonlyArray; + readonly selectionSet: SelectionSetNode; +} + +export interface FragmentDefinitionNode { + readonly kind: 'FragmentDefinition'; + readonly loc?: Location; + readonly name: NameNode; + // Note: fragment variable definitions are experimental and may be changed + // or removed in the future. + readonly variableDefinitions?: ReadonlyArray; + readonly typeCondition: NamedTypeNode; + readonly directives?: ReadonlyArray; + readonly selectionSet: SelectionSetNode; +} + +// Values + +export type ValueNode = + | VariableNode + | IntValueNode + | FloatValueNode + | StringValueNode + | BooleanValueNode + | NullValueNode + | EnumValueNode + | ListValueNode + | ObjectValueNode; + +export interface IntValueNode { + readonly kind: 'IntValue'; + readonly loc?: Location; + readonly value: string; +} + +export interface FloatValueNode { + readonly kind: 'FloatValue'; + readonly loc?: Location; + readonly value: string; +} + +export interface StringValueNode { + readonly kind: 'StringValue'; + readonly loc?: Location; + readonly value: string; + readonly block?: boolean; +} + +export interface BooleanValueNode { + readonly kind: 'BooleanValue'; + readonly loc?: Location; + readonly value: boolean; +} + +export interface NullValueNode { + readonly kind: 'NullValue'; + readonly loc?: Location; +} + +export interface EnumValueNode { + readonly kind: 'EnumValue'; + readonly loc?: Location; + readonly value: string; +} + +export interface ListValueNode { + readonly kind: 'ListValue'; + readonly loc?: Location; + readonly values: ReadonlyArray; +} + +export interface ObjectValueNode { + readonly kind: 'ObjectValue'; + readonly loc?: Location; + readonly fields: ReadonlyArray; +} + +export interface ObjectFieldNode { + readonly kind: 'ObjectField'; + readonly loc?: Location; + readonly name: NameNode; + readonly value: ValueNode; +} + +// Directives + +export interface DirectiveNode { + readonly kind: 'Directive'; + readonly loc?: Location; + readonly name: NameNode; + readonly arguments?: ReadonlyArray; +} + +// Type Reference + +export type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode; + +export interface NamedTypeNode { + readonly kind: 'NamedType'; + readonly loc?: Location; + readonly name: NameNode; +} + +export interface ListTypeNode { + readonly kind: 'ListType'; + readonly loc?: Location; + readonly type: TypeNode; +} + +export interface NonNullTypeNode { + readonly kind: 'NonNullType'; + readonly loc?: Location; + readonly type: NamedTypeNode | ListTypeNode; +} + +// Type System Definition + +export type TypeSystemDefinitionNode = + | SchemaDefinitionNode + | TypeDefinitionNode + | DirectiveDefinitionNode; + +export interface SchemaDefinitionNode { + readonly kind: 'SchemaDefinition'; + readonly loc?: Location; + readonly directives?: ReadonlyArray; + readonly operationTypes: ReadonlyArray; +} + +export interface OperationTypeDefinitionNode { + readonly kind: 'OperationTypeDefinition'; + readonly loc?: Location; + readonly operation: OperationTypeNode; + readonly type: NamedTypeNode; +} + +// Type Definition + +export type TypeDefinitionNode = + | ScalarTypeDefinitionNode + | ObjectTypeDefinitionNode + | InterfaceTypeDefinitionNode + | UnionTypeDefinitionNode + | EnumTypeDefinitionNode + | InputObjectTypeDefinitionNode; + +export interface ScalarTypeDefinitionNode { + readonly kind: 'ScalarTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; +} + +export interface ObjectTypeDefinitionNode { + readonly kind: 'ObjectTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly interfaces?: ReadonlyArray; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} + +export interface FieldDefinitionNode { + readonly kind: 'FieldDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly arguments?: ReadonlyArray; + readonly type: TypeNode; + readonly directives?: ReadonlyArray; +} + +export interface InputValueDefinitionNode { + readonly kind: 'InputValueDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly type: TypeNode; + readonly defaultValue?: ValueNode; + readonly directives?: ReadonlyArray; +} + +export interface InterfaceTypeDefinitionNode { + readonly kind: 'InterfaceTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} + +export interface UnionTypeDefinitionNode { + readonly kind: 'UnionTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly types?: ReadonlyArray; +} + +export interface EnumTypeDefinitionNode { + readonly kind: 'EnumTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly values?: ReadonlyArray; +} + +export interface EnumValueDefinitionNode { + readonly kind: 'EnumValueDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; +} + +export interface InputObjectTypeDefinitionNode { + readonly kind: 'InputObjectTypeDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} + +// Directive Definitions + +export interface DirectiveDefinitionNode { + readonly kind: 'DirectiveDefinition'; + readonly loc?: Location; + readonly description?: StringValueNode; + readonly name: NameNode; + readonly arguments?: ReadonlyArray; + readonly repeatable: boolean; + readonly locations: ReadonlyArray; +} + +// Type System Extensions + +export type TypeSystemExtensionNode = SchemaExtensionNode | TypeExtensionNode; + +export type SchemaExtensionNode = { + readonly kind: 'SchemaExtension'; + readonly loc?: Location; + readonly directives?: ReadonlyArray; + readonly operationTypes?: ReadonlyArray; +}; + +// Type Extensions + +export type TypeExtensionNode = + | ScalarTypeExtensionNode + | ObjectTypeExtensionNode + | InterfaceTypeExtensionNode + | UnionTypeExtensionNode + | EnumTypeExtensionNode + | InputObjectTypeExtensionNode; + +export interface ScalarTypeExtensionNode { + readonly kind: 'ScalarTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; +} + +export interface ObjectTypeExtensionNode { + readonly kind: 'ObjectTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly interfaces?: ReadonlyArray; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} + +export interface InterfaceTypeExtensionNode { + readonly kind: 'InterfaceTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} + +export interface UnionTypeExtensionNode { + readonly kind: 'UnionTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly types?: ReadonlyArray; +} + +export interface EnumTypeExtensionNode { + readonly kind: 'EnumTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly values?: ReadonlyArray; +} + +export interface InputObjectTypeExtensionNode { + readonly kind: 'InputObjectTypeExtension'; + readonly loc?: Location; + readonly name: NameNode; + readonly directives?: ReadonlyArray; + readonly fields?: ReadonlyArray; +} diff --git a/tstypes/language/blockString.d.ts b/tstypes/language/blockString.d.ts new file mode 100644 index 00000000000..a6bf5f6f0c4 --- /dev/null +++ b/tstypes/language/blockString.d.ts @@ -0,0 +1,7 @@ +/** + * Produces the value of a block string from its parsed raw value, similar to + * Coffeescript's block string, Python's docstring trim or Ruby's strip_heredoc. + * + * This implements the GraphQL spec's BlockStringValue() static algorithm. + */ +export function dedentBlockStringValue(rawString: string): string; diff --git a/tstypes/language/directiveLocation.d.ts b/tstypes/language/directiveLocation.d.ts new file mode 100644 index 00000000000..7b1bd51bcae --- /dev/null +++ b/tstypes/language/directiveLocation.d.ts @@ -0,0 +1,35 @@ +/** + * The set of allowed directive location values. + */ +export const DirectiveLocation: _DirectiveLocation; + +// @internal +type _DirectiveLocation = { + // Request Definitions + QUERY: 'QUERY'; + MUTATION: 'MUTATION'; + SUBSCRIPTION: 'SUBSCRIPTION'; + FIELD: 'FIELD'; + FRAGMENT_DEFINITION: 'FRAGMENT_DEFINITION'; + FRAGMENT_SPREAD: 'FRAGMENT_SPREAD'; + INLINE_FRAGMENT: 'INLINE_FRAGMENT'; + VARIABLE_DEFINITION: 'VARIABLE_DEFINITION'; + + // Type System Definitions + SCHEMA: 'SCHEMA'; + SCALAR: 'SCALAR'; + OBJECT: 'OBJECT'; + FIELD_DEFINITION: 'FIELD_DEFINITION'; + ARGUMENT_DEFINITION: 'ARGUMENT_DEFINITION'; + INTERFACE: 'INTERFACE'; + UNION: 'UNION'; + ENUM: 'ENUM'; + ENUM_VALUE: 'ENUM_VALUE'; + INPUT_OBJECT: 'INPUT_OBJECT'; + INPUT_FIELD_DEFINITION: 'INPUT_FIELD_DEFINITION'; +}; + +/** + * The enum type representing the directive location values. + */ +export type DirectiveLocationEnum = _DirectiveLocation[keyof _DirectiveLocation]; diff --git a/tstypes/language/index.d.ts b/tstypes/language/index.d.ts new file mode 100644 index 00000000000..d8a1d3fb4f1 --- /dev/null +++ b/tstypes/language/index.d.ts @@ -0,0 +1,93 @@ +export { getLocation, SourceLocation } from './location'; +export { Kind, KindEnum } from './kinds'; +export { createLexer, TokenKind, Lexer, TokenKindEnum } from './lexer'; +export { parse, parseValue, parseType, ParseOptions } from './parser'; +export { print } from './printer'; +export { Source } from './source'; +export { + visit, + visitInParallel, + visitWithTypeInfo, + getVisitFn, + BREAK, + // type + ASTVisitor, + Visitor, + VisitFn, + VisitorKeyMap, +} from './visitor'; + +export { + Location, + Token, + ASTNode, + ASTKindToNode, + // Each kind of AST node + NameNode, + DocumentNode, + DefinitionNode, + ExecutableDefinitionNode, + OperationDefinitionNode, + OperationTypeNode, + VariableDefinitionNode, + VariableNode, + SelectionSetNode, + SelectionNode, + FieldNode, + ArgumentNode, + FragmentSpreadNode, + InlineFragmentNode, + FragmentDefinitionNode, + ValueNode, + IntValueNode, + FloatValueNode, + StringValueNode, + BooleanValueNode, + NullValueNode, + EnumValueNode, + ListValueNode, + ObjectValueNode, + ObjectFieldNode, + DirectiveNode, + TypeNode, + NamedTypeNode, + ListTypeNode, + NonNullTypeNode, + TypeSystemDefinitionNode, + SchemaDefinitionNode, + OperationTypeDefinitionNode, + TypeDefinitionNode, + ScalarTypeDefinitionNode, + ObjectTypeDefinitionNode, + FieldDefinitionNode, + InputValueDefinitionNode, + InterfaceTypeDefinitionNode, + UnionTypeDefinitionNode, + EnumTypeDefinitionNode, + EnumValueDefinitionNode, + InputObjectTypeDefinitionNode, + DirectiveDefinitionNode, + TypeSystemExtensionNode, + SchemaExtensionNode, + TypeExtensionNode, + ScalarTypeExtensionNode, + ObjectTypeExtensionNode, + InterfaceTypeExtensionNode, + UnionTypeExtensionNode, + EnumTypeExtensionNode, + InputObjectTypeExtensionNode, +} from './ast'; + +export { + isDefinitionNode, + isExecutableDefinitionNode, + isSelectionNode, + isValueNode, + isTypeNode, + isTypeSystemDefinitionNode, + isTypeDefinitionNode, + isTypeSystemExtensionNode, + isTypeExtensionNode, +} from './predicates'; + +export { DirectiveLocation, DirectiveLocationEnum } from './directiveLocation'; diff --git a/tstypes/language/kinds.d.ts b/tstypes/language/kinds.d.ts new file mode 100644 index 00000000000..f61ace5fc46 --- /dev/null +++ b/tstypes/language/kinds.d.ts @@ -0,0 +1,77 @@ +/** + * The set of allowed kind values for AST nodes. + */ +export const Kind: _Kind; + +// @internal +type _Kind = { + // Name + NAME: 'Name'; + + // Document + DOCUMENT: 'Document'; + OPERATION_DEFINITION: 'OperationDefinition'; + VARIABLE_DEFINITION: 'VariableDefinition'; + SELECTION_SET: 'SelectionSet'; + FIELD: 'Field'; + ARGUMENT: 'Argument'; + + // Fragments + FRAGMENT_SPREAD: 'FragmentSpread'; + INLINE_FRAGMENT: 'InlineFragment'; + FRAGMENT_DEFINITION: 'FragmentDefinition'; + + // Values + VARIABLE: 'Variable'; + INT: 'IntValue'; + FLOAT: 'FloatValue'; + STRING: 'StringValue'; + BOOLEAN: 'BooleanValue'; + NULL: 'NullValue'; + ENUM: 'EnumValue'; + LIST: 'ListValue'; + OBJECT: 'ObjectValue'; + OBJECT_FIELD: 'ObjectField'; + + // Directives + DIRECTIVE: 'Directive'; + + // Types + NAMED_TYPE: 'NamedType'; + LIST_TYPE: 'ListType'; + NON_NULL_TYPE: 'NonNullType'; + + // Type System Definitions + SCHEMA_DEFINITION: 'SchemaDefinition'; + OPERATION_TYPE_DEFINITION: 'OperationTypeDefinition'; + + // Type Definitions + SCALAR_TYPE_DEFINITION: 'ScalarTypeDefinition'; + OBJECT_TYPE_DEFINITION: 'ObjectTypeDefinition'; + FIELD_DEFINITION: 'FieldDefinition'; + INPUT_VALUE_DEFINITION: 'InputValueDefinition'; + INTERFACE_TYPE_DEFINITION: 'InterfaceTypeDefinition'; + UNION_TYPE_DEFINITION: 'UnionTypeDefinition'; + ENUM_TYPE_DEFINITION: 'EnumTypeDefinition'; + ENUM_VALUE_DEFINITION: 'EnumValueDefinition'; + INPUT_OBJECT_TYPE_DEFINITION: 'InputObjectTypeDefinition'; + + // Directive Definitions + DIRECTIVE_DEFINITION: 'DirectiveDefinition'; + + // Type System Extensions + SCHEMA_EXTENSION: 'SchemaExtension'; + + // Type Extensions + SCALAR_TYPE_EXTENSION: 'ScalarTypeExtension'; + OBJECT_TYPE_EXTENSION: 'ObjectTypeExtension'; + INTERFACE_TYPE_EXTENSION: 'InterfaceTypeExtension'; + UNION_TYPE_EXTENSION: 'UnionTypeExtension'; + ENUM_TYPE_EXTENSION: 'EnumTypeExtension'; + INPUT_OBJECT_TYPE_EXTENSION: 'InputObjectTypeExtension'; +}; + +/** + * The enum type representing the possible kind values of AST nodes. + */ +export type KindEnum = _Kind[keyof _Kind]; diff --git a/tstypes/language/lexer.d.ts b/tstypes/language/lexer.d.ts new file mode 100644 index 00000000000..42bd460ced2 --- /dev/null +++ b/tstypes/language/lexer.d.ts @@ -0,0 +1,97 @@ +import { Token } from './ast'; +import { Source } from './source'; +import { syntaxError } from '../error'; + +/** + * Given a Source object, this returns a Lexer for that source. + * A Lexer is a stateful stream generator in that every time + * it is advanced, it returns the next token in the Source. Assuming the + * source lexes, the final Token emitted by the lexer will be of kind + * EOF, after which the lexer will repeatedly return the same EOF token + * whenever called. + */ +export function createLexer( + source: Source, + options: TOptions, +): Lexer; + +/** + * The return type of createLexer. + */ +export interface Lexer { + source: Source; + options: TOptions; + + /** + * The previously focused non-ignored token. + */ + lastToken: Token; + + /** + * The currently focused non-ignored token. + */ + token: Token; + + /** + * The (1-indexed) line containing the current token. + */ + line: number; + + /** + * The character offset at which the current line begins. + */ + lineStart: number; + + /** + * Advances the token stream to the next non-ignored token. + */ + advance(): Token; + + /** + * Looks ahead and returns the next non-ignored token, but does not change + * the Lexer's state. + */ + lookahead(): Token; +} + +/** + * An exported enum describing the different kinds of tokens that the + * lexer emits. + */ +export const TokenKind: _TokenKind; + +// @internal +type _TokenKind = { + SOF: ''; + EOF: ''; + BANG: '!'; + DOLLAR: '$'; + AMP: '&'; + PAREN_L: '('; + PAREN_R: ')'; + SPREAD: '...'; + COLON: ':'; + EQUALS: '='; + AT: '@'; + BRACKET_L: '['; + BRACKET_R: ']'; + BRACE_L: '{'; + PIPE: '|'; + BRACE_R: '}'; + NAME: 'Name'; + INT: 'Int'; + FLOAT: 'Float'; + STRING: 'String'; + BLOCK_STRING: 'BlockString'; + COMMENT: 'Comment'; +}; + +/** + * The enum type representing the token kinds values. + */ +export type TokenKindEnum = _TokenKind[keyof _TokenKind]; + +/** + * A helper function to describe a token as a string for debugging + */ +export function getTokenDesc(token: Token): string; diff --git a/tstypes/language/location.d.ts b/tstypes/language/location.d.ts new file mode 100644 index 00000000000..a41e82f41e2 --- /dev/null +++ b/tstypes/language/location.d.ts @@ -0,0 +1,15 @@ +import { Source } from './source'; + +/** + * Represents a location in a Source. + */ +export interface SourceLocation { + readonly line: number; + readonly column: number; +} + +/** + * Takes a Source and a UTF-8 character offset, and returns the corresponding + * line and column as a SourceLocation. + */ +export function getLocation(source: Source, position: number): SourceLocation; diff --git a/tstypes/language/parser.d.ts b/tstypes/language/parser.d.ts new file mode 100644 index 00000000000..f6a49557b2d --- /dev/null +++ b/tstypes/language/parser.d.ts @@ -0,0 +1,115 @@ +import { NamedTypeNode, TypeNode, ValueNode, DocumentNode } from './ast'; +import { Source } from './source'; +import { Lexer } from './lexer'; + +/** + * Configuration options to control parser behavior + */ +export interface ParseOptions { + /** + * By default, the parser creates AST nodes that know the location + * in the source that they correspond to. This configuration flag + * disables that behavior for performance or testing. + */ + noLocation?: boolean; + + /** + * If enabled, the parser will parse empty fields sets in the Schema + * Definition Language. Otherwise, the parser will follow the current + * specification. + * + * This option is provided to ease adoption of the final SDL specification + * and will be removed in v16. + */ + allowLegacySDLEmptyFields?: boolean; + + /** + * If enabled, the parser will parse implemented interfaces with no `&` + * character between each interface. Otherwise, the parser will follow the + * current specification. + * + * This option is provided to ease adoption of the final SDL specification + * and will be removed in v16. + */ + allowLegacySDLImplementsInterfaces?: boolean; + + /** + * EXPERIMENTAL: + * + * If enabled, the parser will understand and parse variable definitions + * contained in a fragment definition. They'll be represented in the + * `variableDefinitions` field of the FragmentDefinitionNode. + * + * The syntax is identical to normal, query-defined variables. For example: + * + * fragment A($var: Boolean = false) on T { + * ... + * } + * + * Note: this feature is experimental and may change or be removed in the + * future. + */ + experimentalFragmentVariables?: boolean; + + /** + * EXPERIMENTAL: + * + * If enabled, the parser understands directives on variable definitions: + * + * query Foo($var: String = "abc" @variable_definition_directive) { + * ... + * } + */ + experimentalVariableDefinitionDirectives?: boolean; +} + +/** + * Given a GraphQL source, parses it into a Document. + * Throws GraphQLError if a syntax error is encountered. + */ +export function parse( + source: string | Source, + options?: ParseOptions, +): DocumentNode; + +/** + * Given a string containing a GraphQL value, parse the AST for that value. + * Throws GraphQLError if a syntax error is encountered. + * + * This is useful within tools that operate upon GraphQL Values directly and + * in isolation of complete GraphQL documents. + */ +export function parseValue( + source: string | Source, + options?: ParseOptions, +): ValueNode; + +/** + * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for + * that type. + * Throws GraphQLError if a syntax error is encountered. + * + * This is useful within tools that operate upon GraphQL Types directly and + * in isolation of complete GraphQL documents. + * + * Consider providing the results to the utility function: typeFromAST(). + */ +export function parseType( + source: string | Source, + options?: ParseOptions, +): TypeNode; + +export function parseConstValue(lexer: Lexer): ValueNode; + +/** + * Type : + * - NamedType + * - ListType + * - NonNullType + */ +export function parseTypeReference(lexer: Lexer): TypeNode; + +/** + * NamedType : Name + */ +export function parseNamedType(lexer: Lexer): NamedTypeNode; diff --git a/tstypes/language/predicates.d.ts b/tstypes/language/predicates.d.ts new file mode 100644 index 00000000000..cdbe1f9fd69 --- /dev/null +++ b/tstypes/language/predicates.d.ts @@ -0,0 +1,36 @@ +import { + ASTNode, + DefinitionNode, + ExecutableDefinitionNode, + SelectionNode, + ValueNode, + TypeNode, + TypeSystemDefinitionNode, + TypeDefinitionNode, + TypeSystemExtensionNode, + TypeExtensionNode, +} from './ast'; + +export function isDefinitionNode(node: ASTNode): node is DefinitionNode; + +export function isExecutableDefinitionNode( + node: ASTNode, +): node is ExecutableDefinitionNode; + +export function isSelectionNode(node: ASTNode): node is SelectionNode; + +export function isValueNode(node: ASTNode): node is ValueNode; + +export function isTypeNode(node: ASTNode): node is TypeNode; + +export function isTypeSystemDefinitionNode( + node: ASTNode, +): node is TypeSystemDefinitionNode; + +export function isTypeDefinitionNode(node: ASTNode): node is TypeDefinitionNode; + +export function isTypeSystemExtensionNode( + node: ASTNode, +): node is TypeSystemExtensionNode; + +export function isTypeExtensionNode(node: ASTNode): node is TypeExtensionNode; diff --git a/tstypes/language/printer.d.ts b/tstypes/language/printer.d.ts new file mode 100644 index 00000000000..9329b459560 --- /dev/null +++ b/tstypes/language/printer.d.ts @@ -0,0 +1,7 @@ +import { ASTNode } from './ast'; + +/** + * Converts an AST into a string, using one set of reasonable + * formatting rules. + */ +export function print(ast: ASTNode): string; diff --git a/tstypes/language/source.d.ts b/tstypes/language/source.d.ts new file mode 100644 index 00000000000..4517784b220 --- /dev/null +++ b/tstypes/language/source.d.ts @@ -0,0 +1,19 @@ +interface Location { + line: number; + column: number; +} + +/** + * A representation of source input to GraphQL. + * `name` and `locationOffset` are optional. They are useful for clients who + * store GraphQL documents in source files; for example, if the GraphQL input + * starts at line 40 in a file named Foo.graphql, it might be useful for name to + * be "Foo.graphql" and location to be `{ line: 40, column: 0 }`. + * line and column in locationOffset are 1-indexed + */ +export class Source { + body: string; + name: string; + locationOffset: Location; + constructor(body: string, name?: string, locationOffset?: Location); +} diff --git a/tstypes/language/visitor.d.ts b/tstypes/language/visitor.d.ts new file mode 100644 index 00000000000..930523163d5 --- /dev/null +++ b/tstypes/language/visitor.d.ts @@ -0,0 +1,172 @@ +import Maybe from '../tsutils/Maybe'; +import { ASTNode, ASTKindToNode } from './ast'; +import { TypeInfo } from '../utilities/TypeInfo'; + +interface EnterLeave { + readonly enter?: T; + readonly leave?: T; +} + +type EnterLeaveVisitor = EnterLeave< + VisitFn | { [K in keyof KindToNode]?: VisitFn } +>; + +type ShapeMapVisitor = { + [K in keyof KindToNode]?: + | VisitFn + | EnterLeave>; +}; + +export type ASTVisitor = Visitor; +export type Visitor = + | EnterLeaveVisitor + | ShapeMapVisitor; + +/** + * A visitor is comprised of visit functions, which are called on each node + * during the visitor's traversal. + */ +export type VisitFn = ( + // The current node being visiting. + node: TVisitedNode, + // The index or key to this node from the parent node or Array. + key: string | number | undefined, + // The parent immediately above this node, which may be an Array. + parent: TAnyNode | ReadonlyArray | undefined, + // The key path to get to this node from the root node. + path: ReadonlyArray, + // All nodes and Arrays visited before reaching parent of this node. + // These correspond to array indices in `path`. + // Note: ancestors includes arrays which contain the parent of visited node. + ancestors: ReadonlyArray>, +) => any; + +/** + * A KeyMap describes each the traversable properties of each kind of node. + */ +export type VisitorKeyMap = { [P in keyof T]: ReadonlyArray }; + +export const QueryDocumentKeys: { [key: string]: string[] }; + +export const BREAK: any; + +/** + * visit() will walk through an AST using a depth first traversal, calling + * the visitor's enter function at each node in the traversal, and calling the + * leave function after visiting that node and all of its child nodes. + * + * By returning different values from the enter and leave functions, the + * behavior of the visitor can be altered, including skipping over a sub-tree of + * the AST (by returning false), editing the AST by returning a value or null + * to remove the value, or to stop the whole traversal by returning BREAK. + * + * When using visit() to edit an AST, the original AST will not be modified, and + * a new version of the AST with the changes applied will be returned from the + * visit function. + * + * const editedAST = visit(ast, { + * enter(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: skip visiting this node + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * }, + * leave(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: no action + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * } + * }); + * + * Alternatively to providing enter() and leave() functions, a visitor can + * instead provide functions named the same as the kinds of AST nodes, or + * enter/leave visitors at a named key, leading to four permutations of + * visitor API: + * + * 1) Named visitors triggered when entering a node a specific kind. + * + * visit(ast, { + * Kind(node) { + * // enter the "Kind" node + * } + * }) + * + * 2) Named visitors that trigger upon entering and leaving a node of + * a specific kind. + * + * visit(ast, { + * Kind: { + * enter(node) { + * // enter the "Kind" node + * } + * leave(node) { + * // leave the "Kind" node + * } + * } + * }) + * + * 3) Generic visitors that trigger upon entering and leaving any node. + * + * visit(ast, { + * enter(node) { + * // enter any node + * }, + * leave(node) { + * // leave any node + * } + * }) + * + * 4) Parallel visitors for entering and leaving nodes of a specific kind. + * + * visit(ast, { + * enter: { + * Kind(node) { + * // enter the "Kind" node + * } + * }, + * leave: { + * Kind(node) { + * // leave the "Kind" node + * } + * } + * }) + */ +export function visit( + root: ASTNode, + visitor: Visitor, + visitorKeys?: VisitorKeyMap, // default: QueryDocumentKeys +): any; + +/** + * Creates a new visitor instance which delegates to many visitors to run in + * parallel. Each visitor will be visited for each node before moving on. + * + * If a prior visitor edits a node, no following visitors will see that node. + */ +export function visitInParallel( + visitors: Array>, +): Visitor; + +/** + * Creates a new visitor instance which maintains a provided TypeInfo instance + * along with visiting visitor. + */ +export function visitWithTypeInfo( + typeInfo: TypeInfo, + visitor: Visitor, +): Visitor; + +/** + * Given a visitor instance, if it is leaving or not, and a node kind, return + * the function the visitor runtime should call. + */ +export function getVisitFn( + visitor: Visitor, + kind: string, + isLeaving: boolean, +): Maybe>; diff --git a/tstypes/subscription/index.d.ts b/tstypes/subscription/index.d.ts new file mode 100644 index 00000000000..11b0a7f26d6 --- /dev/null +++ b/tstypes/subscription/index.d.ts @@ -0,0 +1 @@ +export { subscribe, createSourceEventStream } from './subscribe'; diff --git a/tstypes/subscription/subscribe.d.ts b/tstypes/subscription/subscribe.d.ts new file mode 100644 index 00000000000..632af63c016 --- /dev/null +++ b/tstypes/subscription/subscribe.d.ts @@ -0,0 +1,82 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLSchema } from '../type/schema'; +import { DocumentNode } from '../language/ast'; +import { GraphQLFieldResolver } from '../type/definition'; +import { + ExecutionResult, + ExecutionResultDataDefault, +} from '../execution/execute'; + +/** + * Implements the "Subscribe" algorithm described in the GraphQL specification. + * + * Returns a Promise which resolves to either an AsyncIterator (if successful) + * or an ExecutionResult (client error). The promise will be rejected if a + * server error occurs. + * + * If the client-provided arguments to this function do not result in a + * compliant subscription, a GraphQL Response (ExecutionResult) with + * descriptive errors and no data will be returned. + * + * If the the source stream could not be created due to faulty subscription + * resolver logic or underlying systems, the promise will resolve to a single + * ExecutionResult containing `errors` and no `data`. + * + * If the operation succeeded, the promise resolves to an AsyncIterator, which + * yields a stream of ExecutionResults representing the response stream. + * + * Accepts either an object with named arguments, or individual arguments. + */ +export function subscribe(args: { + schema: GraphQLSchema; + document: DocumentNode; + rootValue?: any; + contextValue?: any; + variableValues?: Maybe<{ [key: string]: any }>; + operationName?: Maybe; + fieldResolver?: Maybe>; + subscribeFieldResolver?: Maybe>; +}): Promise< + AsyncIterableIterator> | ExecutionResult +>; + +export function subscribe( + schema: GraphQLSchema, + document: DocumentNode, + rootValue?: any, + contextValue?: any, + variableValues?: Maybe<{ [key: string]: any }>, + operationName?: Maybe, + fieldResolver?: Maybe>, + subscribeFieldResolver?: Maybe>, +): Promise< + AsyncIterableIterator> | ExecutionResult +>; + +/** + * Implements the "CreateSourceEventStream" algorithm described in the + * GraphQL specification, resolving the subscription source event stream. + * + * Returns a Promise. + * + * If the client-provided invalid arguments, the source stream could not be + * created, or the resolver did not return an AsyncIterable, this function will + * will throw an error, which should be caught and handled by the caller. + * + * A Source Event Stream represents a sequence of events, each of which triggers + * a GraphQL execution for that event. + * + * This may be useful when hosting the stateful subscription service in a + * different process or machine than the stateless GraphQL execution engine, + * or otherwise separating these two steps. For more on this, see the + * "Supporting Subscriptions at Scale" information in the GraphQL specification. + */ +export function createSourceEventStream( + schema: GraphQLSchema, + document: DocumentNode, + rootValue?: any, + contextValue?: any, + variableValues?: { [key: string]: any }, + operationName?: Maybe, + fieldResolver?: Maybe>, +): Promise | ExecutionResult>; diff --git a/tstypes/tsconfig.json b/tstypes/tsconfig.json new file mode 100644 index 00000000000..07994c2495f --- /dev/null +++ b/tstypes/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6", "esnext.asynciterable"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": ["../"], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts"] +} diff --git a/tstypes/tslint.json b/tstypes/tslint.json new file mode 100644 index 00000000000..8c08a13eb39 --- /dev/null +++ b/tstypes/tslint.json @@ -0,0 +1,20 @@ +{ + "extends": "dtslint/dtslint.json", + "rules": { + // All are TODOs + "array-type": false, + "interface-over-type-literal": false, + "jsdoc-format": false, + "no-any-union": false, + "no-consecutive-blank-lines": false, + "no-duplicate-imports": false, + "no-empty-interface": false, + "no-redundant-undefined": false, + "no-unnecessary-generics": false, + "semicolon": false, + "strict-export-declare-modifiers": false, + "unified-signatures": false, + "use-default-type-parameter": false, + "void-return": false + } +} diff --git a/tstypes/tsutils/Maybe.d.ts b/tstypes/tsutils/Maybe.d.ts new file mode 100644 index 00000000000..6a3391138f7 --- /dev/null +++ b/tstypes/tsutils/Maybe.d.ts @@ -0,0 +1,4 @@ +// Conveniently represents flow's "Maybe" type https://flow.org/en/docs/types/maybe/ +type Maybe = null | undefined | T; + +export default Maybe; diff --git a/tstypes/type/definition.d.ts b/tstypes/type/definition.d.ts new file mode 100644 index 00000000000..28b68dd7ac8 --- /dev/null +++ b/tstypes/type/definition.d.ts @@ -0,0 +1,774 @@ +import Maybe from '../tsutils/Maybe'; +import { PromiseOrValue } from '../jsutils/PromiseOrValue'; +import { + ScalarTypeDefinitionNode, + ObjectTypeDefinitionNode, + FieldDefinitionNode, + InputValueDefinitionNode, + InterfaceTypeDefinitionNode, + UnionTypeDefinitionNode, + EnumTypeDefinitionNode, + EnumValueDefinitionNode, + InputObjectTypeDefinitionNode, + ObjectTypeExtensionNode, + InterfaceTypeExtensionNode, + OperationDefinitionNode, + FieldNode, + FragmentDefinitionNode, + ValueNode, + ScalarTypeExtensionNode, + UnionTypeExtensionNode, + EnumTypeExtensionNode, + InputObjectTypeExtensionNode, +} from '../language/ast'; +import { GraphQLSchema } from './schema'; + +/** + * These are all of the possible kinds of types. + */ +export type GraphQLType = + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + | GraphQLNonNull; + +export function isType(type: any): type is GraphQLType; + +export function assertType(type: any): GraphQLType; + +export function isScalarType(type: any): type is GraphQLScalarType; + +export function assertScalarType(type: any): GraphQLScalarType; + +export function isObjectType(type: any): type is GraphQLObjectType; + +export function assertObjectType(type: any): GraphQLObjectType; + +export function isInterfaceType(type: any): type is GraphQLInterfaceType; + +export function assertInterfaceType(type: any): GraphQLInterfaceType; + +export function isUnionType(type: any): type is GraphQLUnionType; + +export function assertUnionType(type: any): GraphQLUnionType; + +export function isEnumType(type: any): type is GraphQLEnumType; + +export function assertEnumType(type: any): GraphQLEnumType; + +export function isInputObjectType(type: any): type is GraphQLInputObjectType; + +export function assertInputObjectType(type: any): GraphQLInputObjectType; + +export function isListType(type: any): type is GraphQLList; + +export function assertListType(type: any): GraphQLList; + +export function isNonNullType(type: any): type is GraphQLNonNull; + +export function assertNonNullType(type: any): GraphQLNonNull; + +/** + * These types may be used as input types for arguments and directives. + */ +export type GraphQLInputType = + | GraphQLScalarType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + | GraphQLNonNull< + | GraphQLScalarType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + >; + +export function isInputType(type: any): type is GraphQLInputType; + +export function assertInputType(type: any): GraphQLInputType; + +/** + * These types may be used as output types as the result of fields. + */ +export type GraphQLOutputType = + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLList + | GraphQLNonNull< + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLList + >; + +export function isOutputType(type: any): type is GraphQLOutputType; + +export function assertOutputType(type: any): GraphQLOutputType; + +/** + * These types may describe types which may be leaf values. + */ +export type GraphQLLeafType = GraphQLScalarType | GraphQLEnumType; + +export function isLeafType(type: any): type is GraphQLLeafType; + +export function assertLeafType(type: any): GraphQLLeafType; + +/** + * These types may describe the parent context of a selection set. + */ +export type GraphQLCompositeType = + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType; + +export function isCompositeType(type: any): type is GraphQLCompositeType; + +export function assertCompositeType(type: any): GraphQLCompositeType; + +/** + * These types may describe the parent context of a selection set. + */ +export type GraphQLAbstractType = GraphQLInterfaceType | GraphQLUnionType; + +export function isAbstractType(type: any): type is GraphQLAbstractType; + +export function assertAbstractType(type: any): GraphQLAbstractType; + +/** + * List Modifier + * + * A list is a kind of type marker, a wrapping type which points to another + * type. Lists are often created within the context of defining the fields + * of an object type. + * + * Example: + * + * const PersonType = new GraphQLObjectType({ + * name: 'Person', + * fields: () => ({ + * parents: { type: new GraphQLList(Person) }, + * children: { type: new GraphQLList(Person) }, + * }) + * }) + * + */ +interface GraphQLList { + readonly ofType: T; + toString(): string; + toJSON(): string; + inspect(): string; +} + +interface _GraphQLList { + (type: T): GraphQLList; + new (type: T): GraphQLList; +} + +export const GraphQLList: _GraphQLList; + +/** + * Non-Null Modifier + * + * A non-null is a kind of type marker, a wrapping type which points to another + * type. Non-null types enforce that their values are never null and can ensure + * an error is raised if this ever occurs during a request. It is useful for + * fields which you can make a strong guarantee on non-nullability, for example + * usually the id field of a database row will never be null. + * + * Example: + * + * const RowType = new GraphQLObjectType({ + * name: 'Row', + * fields: () => ({ + * id: { type: new GraphQLNonNull(GraphQLString) }, + * }) + * }) + * + * Note: the enforcement of non-nullability occurs within the executor. + */ +interface GraphQLNonNull { + readonly ofType: T; + toString(): string; + toJSON(): string; + inspect(): string; +} + +interface _GraphQLNonNull { + (type: T): GraphQLNonNull; + new (type: T): GraphQLNonNull; +} + +export const GraphQLNonNull: _GraphQLNonNull; + +export type GraphQLWrappingType = GraphQLList | GraphQLNonNull; + +export function isWrappingType(type: any): type is GraphQLWrappingType; + +export function assertWrappingType(type: any): GraphQLWrappingType; + +/** + * These types can all accept null as a value. + */ +export type GraphQLNullableType = + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList; + +export function isNullableType(type: any): type is GraphQLNullableType; + +export function assertNullableType(type: any): GraphQLNullableType; + +export function getNullableType(type: void): undefined; +export function getNullableType(type: T): T; +export function getNullableType( + type: GraphQLNonNull, +): T; + +/** + * These named types do not include modifiers like List or NonNull. + */ +export type GraphQLNamedType = + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType; + +export function isNamedType(type: any): type is GraphQLNamedType; + +export function assertNamedType(type: any): GraphQLNamedType; + +export function getNamedType(type: void): undefined; +export function getNamedType(type: GraphQLType): GraphQLNamedType; + +/** + * Used while defining GraphQL types to allow for circular references in + * otherwise immutable type definitions. + */ +export type Thunk = (() => T) | T; + +/** + * Scalar Type Definition + * + * The leaf values of any request and input values to arguments are + * Scalars (or Enums) and are defined with a name and a series of functions + * used to parse input from ast or variables and to ensure validity. + * + * Example: + * + * const OddType = new GraphQLScalarType({ + * name: 'Odd', + * serialize(value) { + * return value % 2 === 1 ? value : null; + * } + * }); + * + */ +export class GraphQLScalarType { + name: string; + description: Maybe; + serialize: GraphQLScalarSerializer; + parseValue: GraphQLScalarValueParser; + parseLiteral: GraphQLScalarLiteralParser; + astNode: Maybe; + extensionASTNodes: Maybe>; + constructor(config: GraphQLScalarTypeConfig); + + toConfig(): GraphQLScalarTypeConfig & { + parseValue: GraphQLScalarValueParser; + parseLiteral: GraphQLScalarLiteralParser; + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export type GraphQLScalarSerializer = ( + value: any, +) => Maybe; +export type GraphQLScalarValueParser = ( + value: any, +) => Maybe; +export type GraphQLScalarLiteralParser = ( + valueNode: ValueNode, + variables: Maybe<{ [key: string]: any }>, +) => Maybe; + +export interface GraphQLScalarTypeConfig { + name: string; + description?: Maybe; + // Serializes an internal value to include in a response. + serialize: GraphQLScalarSerializer; + // Parses an externally provided value to use as an input. + parseValue?: GraphQLScalarValueParser; + // Parses an externally provided literal value to use as an input. + parseLiteral?: GraphQLScalarLiteralParser; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +/** + * Object Type Definition + * + * Almost all of the GraphQL types you define will be object types. Object types + * have a name, but most importantly describe their fields. + * + * Example: + * + * const AddressType = new GraphQLObjectType({ + * name: 'Address', + * fields: { + * street: { type: GraphQLString }, + * number: { type: GraphQLInt }, + * formatted: { + * type: GraphQLString, + * resolve(obj) { + * return obj.number + ' ' + obj.street + * } + * } + * } + * }); + * + * When two types need to refer to each other, or a type needs to refer to + * itself in a field, you can use a function expression (aka a closure or a + * thunk) to supply the fields lazily. + * + * Example: + * + * const PersonType = new GraphQLObjectType({ + * name: 'Person', + * fields: () => ({ + * name: { type: GraphQLString }, + * bestFriend: { type: PersonType }, + * }) + * }); + * + */ +export class GraphQLObjectType< + TSource = any, + TContext = any, + TArgs = { [key: string]: any } +> { + name: string; + description: Maybe; + astNode: Maybe; + extensionASTNodes: Maybe>; + isTypeOf: Maybe>; + + constructor(config: GraphQLObjectTypeConfig); + getFields(): GraphQLFieldMap; + getInterfaces(): GraphQLInterfaceType[]; + + toConfig(): GraphQLObjectTypeConfig & { + interfaces: GraphQLInterfaceType[]; + fields: GraphQLFieldConfigMap; + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export interface GraphQLObjectTypeConfig< + TSource, + TContext, + TArgs = { [key: string]: any } +> { + name: string; + interfaces?: Thunk>; + fields: Thunk>; + isTypeOf?: Maybe>; + description?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +export type GraphQLTypeResolver< + TSource, + TContext, + TArgs = { [key: string]: any } +> = ( + value: TSource, + context: TContext, + info: GraphQLResolveInfo, +) => PromiseOrValue< + Maybe | string> +>; + +export type GraphQLIsTypeOfFn = ( + source: TSource, + context: TContext, + info: GraphQLResolveInfo, +) => PromiseOrValue; + +export type GraphQLFieldResolver< + TSource, + TContext, + TArgs = { [argName: string]: any } +> = ( + source: TSource, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo, +) => any; + +export interface GraphQLResolveInfo { + readonly fieldName: string; + readonly fieldNodes: ReadonlyArray; + readonly returnType: GraphQLOutputType; + readonly parentType: GraphQLObjectType; + readonly path: ResponsePath; + readonly schema: GraphQLSchema; + readonly fragments: { [key: string]: FragmentDefinitionNode }; + readonly rootValue: any; + readonly operation: OperationDefinitionNode; + readonly variableValues: { [variableName: string]: any }; +} + +export type ResponsePath = { + readonly prev: ResponsePath | undefined; + readonly key: string | number; +}; + +export interface GraphQLFieldConfig< + TSource, + TContext, + TArgs = { [argName: string]: any } +> { + type: GraphQLOutputType; + args?: GraphQLFieldConfigArgumentMap; + resolve?: GraphQLFieldResolver; + subscribe?: GraphQLFieldResolver; + deprecationReason?: Maybe; + description?: Maybe; + astNode?: Maybe; +} + +export type GraphQLFieldConfigArgumentMap = { + [key: string]: GraphQLArgumentConfig; +}; + +export interface GraphQLArgumentConfig { + type: GraphQLInputType; + defaultValue?: any; + description?: Maybe; + astNode?: Maybe; +} + +export type GraphQLFieldConfigMap< + TSource, + TContext, + TArgs = { [key: string]: any } +> = { + [key: string]: GraphQLFieldConfig; +}; + +export interface GraphQLField< + TSource, + TContext, + TArgs = { [key: string]: any } +> { + name: string; + description: Maybe; + type: GraphQLOutputType; + args: GraphQLArgument[]; + resolve?: GraphQLFieldResolver; + subscribe?: GraphQLFieldResolver; + isDeprecated?: boolean; + deprecationReason?: Maybe; + astNode?: Maybe; +} + +export interface GraphQLArgument { + name: string; + type: GraphQLInputType; + defaultValue?: any; + description?: Maybe; + astNode?: Maybe; +} + +export function isRequiredArgument(arg: GraphQLArgument): boolean; + +export type GraphQLFieldMap< + TSource, + TContext, + TArgs = { [key: string]: any } +> = { + [key: string]: GraphQLField; +}; + +/** + * Interface Type Definition + * + * When a field can return one of a heterogeneous set of types, a Interface type + * is used to describe what types are possible, what fields are in common across + * all types, as well as a function to determine which type is actually used + * when the field is resolved. + * + * Example: + * + * const EntityType = new GraphQLInterfaceType({ + * name: 'Entity', + * fields: { + * name: { type: GraphQLString } + * } + * }); + * + */ +export class GraphQLInterfaceType { + name: string; + description: Maybe; + astNode?: Maybe; + extensionASTNodes: Maybe>; + resolveType: Maybe>; + + constructor(config: GraphQLInterfaceTypeConfig); + + getFields(): GraphQLFieldMap; + + toConfig(): GraphQLInterfaceTypeConfig & { + fields: GraphQLFieldConfigMap; + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export interface GraphQLInterfaceTypeConfig< + TSource, + TContext, + TArgs = { [key: string]: any } +> { + name: string; + fields: Thunk>; + /** + * Optionally provide a custom type resolver function. If one is not provided, + * the default implementation will call `isTypeOf` on each implementing + * Object type. + */ + resolveType?: Maybe>; + description?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +/** + * Union Type Definition + * + * When a field can return one of a heterogeneous set of types, a Union type + * is used to describe what types are possible as well as providing a function + * to determine which type is actually used when the field is resolved. + * + * Example: + * + * const PetType = new GraphQLUnionType({ + * name: 'Pet', + * types: [ DogType, CatType ], + * resolveType(value) { + * if (value instanceof Dog) { + * return DogType; + * } + * if (value instanceof Cat) { + * return CatType; + * } + * } + * }); + * + */ +export class GraphQLUnionType { + name: string; + description: Maybe; + astNode: Maybe; + extensionASTNodes: Maybe>; + resolveType: Maybe>; + + constructor(config: GraphQLUnionTypeConfig); + + getTypes(): GraphQLObjectType[]; + + toConfig(): GraphQLUnionTypeConfig & { + types: GraphQLObjectType[]; + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export interface GraphQLUnionTypeConfig { + name: string; + types: Thunk; + /** + * Optionally provide a custom type resolver function. If one is not provided, + * the default implementation will call `isTypeOf` on each implementing + * Object type. + */ + resolveType?: Maybe>; + description?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +/** + * Enum Type Definition + * + * Some leaf values of requests and input values are Enums. GraphQL serializes + * Enum values as strings, however internally Enums can be represented by any + * kind of type, often integers. + * + * Example: + * + * const RGBType = new GraphQLEnumType({ + * name: 'RGB', + * values: { + * RED: { value: 0 }, + * GREEN: { value: 1 }, + * BLUE: { value: 2 } + * } + * }); + * + * Note: If a value is not provided in a definition, the name of the enum value + * will be used as its internal value. + */ +export class GraphQLEnumType { + name: string; + description: Maybe; + astNode: Maybe; + extensionASTNodes: Maybe>; + + constructor(config: GraphQLEnumTypeConfig); + getValues(): GraphQLEnumValue[]; + getValue(name: string): Maybe; + serialize(value: any): Maybe; + parseValue(value: any): Maybe; + parseLiteral( + valueNode: ValueNode, + _variables: Maybe<{ [key: string]: any }>, + ): Maybe; + + toConfig(): GraphQLEnumTypeConfig & { + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export interface GraphQLEnumTypeConfig { + name: string; + values: GraphQLEnumValueConfigMap; + description?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +export type GraphQLEnumValueConfigMap = { + [key: string]: GraphQLEnumValueConfig; +}; + +export interface GraphQLEnumValueConfig { + value?: any; + deprecationReason?: Maybe; + description?: Maybe; + astNode?: Maybe; +} + +export interface GraphQLEnumValue { + name: string; + description: Maybe; + isDeprecated?: boolean; + deprecationReason: Maybe; + astNode?: Maybe; + value: any; +} + +/** + * Input Object Type Definition + * + * An input object defines a structured collection of fields which may be + * supplied to a field argument. + * + * Using `NonNull` will ensure that a value must be provided by the query + * + * Example: + * + * const GeoPoint = new GraphQLInputObjectType({ + * name: 'GeoPoint', + * fields: { + * lat: { type: new GraphQLNonNull(GraphQLFloat) }, + * lon: { type: new GraphQLNonNull(GraphQLFloat) }, + * alt: { type: GraphQLFloat, defaultValue: 0 }, + * } + * }); + * + */ +export class GraphQLInputObjectType { + name: string; + description: Maybe; + astNode: Maybe; + extensionASTNodes: Maybe>; + constructor(config: GraphQLInputObjectTypeConfig); + getFields(): GraphQLInputFieldMap; + + toConfig(): GraphQLInputObjectTypeConfig & { + fields: GraphQLInputFieldConfigMap; + extensionASTNodes: ReadonlyArray; + }; + + toString(): string; + toJSON(): string; + inspect(): string; +} + +export interface GraphQLInputObjectTypeConfig { + name: string; + fields: Thunk; + description?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} + +export interface GraphQLInputFieldConfig { + type: GraphQLInputType; + defaultValue?: any; + description?: Maybe; + astNode?: Maybe; +} + +export type GraphQLInputFieldConfigMap = { + [key: string]: GraphQLInputFieldConfig; +}; + +export interface GraphQLInputField { + name: string; + type: GraphQLInputType; + defaultValue?: any; + description?: Maybe; + astNode?: Maybe; +} + +export function isRequiredInputField(field: GraphQLInputField): boolean; + +export type GraphQLInputFieldMap = { [key: string]: GraphQLInputField }; diff --git a/tstypes/type/directives.d.ts b/tstypes/type/directives.d.ts new file mode 100644 index 00000000000..c085aee35be --- /dev/null +++ b/tstypes/type/directives.d.ts @@ -0,0 +1,64 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLFieldConfigArgumentMap, GraphQLArgument } from './definition'; +import { DirectiveDefinitionNode } from '../language/ast'; +import { DirectiveLocationEnum } from '../language/directiveLocation'; + +/** + * Test if the given value is a GraphQL directive. + */ +export function isDirective(directive: any): directive is GraphQLDirective; + +/** + * Directives are used by the GraphQL runtime as a way of modifying execution + * behavior. Type system creators will usually not create these directly. + */ +export class GraphQLDirective { + name: string; + description: Maybe; + locations: DirectiveLocationEnum[]; + isRepeatable: boolean; + args: GraphQLArgument[]; + astNode: Maybe; + + constructor(config: GraphQLDirectiveConfig); + + toConfig(): GraphQLDirectiveConfig & { + args: GraphQLFieldConfigArgumentMap; + }; +} + +export interface GraphQLDirectiveConfig { + name: string; + description?: Maybe; + locations: DirectiveLocationEnum[]; + args?: Maybe; + isRepeatable?: Maybe; + astNode?: Maybe; +} + +/** + * Used to conditionally include fields or fragments. + */ +export const GraphQLIncludeDirective: GraphQLDirective; + +/** + * Used to conditionally skip (exclude) fields or fragments. + */ +export const GraphQLSkipDirective: GraphQLDirective; + +/** + * Constant string used for default reason for a deprecation. + */ +export const DEFAULT_DEPRECATION_REASON: 'No longer supported'; + +/** + * Used to declare element of a GraphQL schema as deprecated. + */ +export const GraphQLDeprecatedDirective: GraphQLDirective; + +/** + * The full list of specified directives. + */ +export const specifiedDirectives: ReadonlyArray; + +export function isSpecifiedDirective(directive: GraphQLDirective): boolean; diff --git a/tstypes/type/index.d.ts b/tstypes/type/index.d.ts new file mode 100644 index 00000000000..209582cb466 --- /dev/null +++ b/tstypes/type/index.d.ts @@ -0,0 +1,150 @@ +export { + // Predicate + isSchema, + // GraphQL Schema definition + GraphQLSchema, + GraphQLSchemaConfig, +} from './schema'; + +export { + // Predicates + isType, + isScalarType, + isObjectType, + isInterfaceType, + isUnionType, + isEnumType, + isInputObjectType, + isListType, + isNonNullType, + isInputType, + isOutputType, + isLeafType, + isCompositeType, + isAbstractType, + isWrappingType, + isNullableType, + isNamedType, + isRequiredArgument, + isRequiredInputField, + // Assertions + assertType, + assertScalarType, + assertObjectType, + assertInterfaceType, + assertUnionType, + assertEnumType, + assertInputObjectType, + assertListType, + assertNonNullType, + assertInputType, + assertOutputType, + assertLeafType, + assertCompositeType, + assertAbstractType, + assertWrappingType, + assertNullableType, + assertNamedType, + // Un-modifiers + getNullableType, + getNamedType, + // Definitions + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + // Type Wrappers + GraphQLList, + GraphQLNonNull, + // type + GraphQLType, + GraphQLInputType, + GraphQLOutputType, + GraphQLLeafType, + GraphQLCompositeType, + GraphQLAbstractType, + GraphQLWrappingType, + GraphQLNullableType, + GraphQLNamedType, + Thunk, + GraphQLArgument, + GraphQLArgumentConfig, + GraphQLEnumTypeConfig, + GraphQLEnumValue, + GraphQLEnumValueConfig, + GraphQLEnumValueConfigMap, + GraphQLField, + GraphQLFieldConfig, + GraphQLFieldConfigArgumentMap, + GraphQLFieldConfigMap, + GraphQLFieldMap, + GraphQLFieldResolver, + GraphQLInputField, + GraphQLInputFieldConfig, + GraphQLInputFieldConfigMap, + GraphQLInputFieldMap, + GraphQLInputObjectTypeConfig, + GraphQLInterfaceTypeConfig, + GraphQLIsTypeOfFn, + GraphQLObjectTypeConfig, + GraphQLResolveInfo, + ResponsePath, + GraphQLScalarTypeConfig, + GraphQLTypeResolver, + GraphQLUnionTypeConfig, + GraphQLScalarSerializer, + GraphQLScalarValueParser, + GraphQLScalarLiteralParser, +} from './definition'; + +export { + // Predicate + isDirective, + // Directives Definition + GraphQLDirective, + // Built-in Directives defined by the Spec + isSpecifiedDirective, + specifiedDirectives, + GraphQLIncludeDirective, + GraphQLSkipDirective, + GraphQLDeprecatedDirective, + // Constant Deprecation Reason + DEFAULT_DEPRECATION_REASON, + // type + GraphQLDirectiveConfig, +} from './directives'; + +// Common built-in scalar instances. +export { + isSpecifiedScalarType, + specifiedScalarTypes, + GraphQLInt, + GraphQLFloat, + GraphQLString, + GraphQLBoolean, + GraphQLID, +} from './scalars'; + +export { + // "Enum" of Type Kinds + TypeKind, + // GraphQL Types for introspection. + isIntrospectionType, + introspectionTypes, + __Schema, + __Directive, + __DirectiveLocation, + __Type, + __Field, + __InputValue, + __EnumValue, + __TypeKind, + // Meta-field definitions. + SchemaMetaFieldDef, + TypeMetaFieldDef, + TypeNameMetaFieldDef, +} from './introspection'; + +export { validateSchema, assertValidSchema } from './validate'; diff --git a/tstypes/type/introspection.d.ts b/tstypes/type/introspection.d.ts new file mode 100644 index 00000000000..9a4dd874eda --- /dev/null +++ b/tstypes/type/introspection.d.ts @@ -0,0 +1,45 @@ +import { + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, +} from './definition'; +import { GraphQLField } from './definition'; + +export const __Schema: GraphQLObjectType; +export const __Directive: GraphQLObjectType; +export const __DirectiveLocation: GraphQLEnumType; +export const __Type: GraphQLObjectType; +export const __Field: GraphQLObjectType; +export const __InputValue: GraphQLObjectType; +export const __EnumValue: GraphQLObjectType; + +export const TypeKind: { + SCALAR: 'SCALAR'; + OBJECT: 'OBJECT'; + INTERFACE: 'INTERFACE'; + UNION: 'UNION'; + ENUM: 'ENUM'; + INPUT_OBJECT: 'INPUT_OBJECT'; + LIST: 'LIST'; + NON_NULL: 'NON_NULL'; +}; + +export const __TypeKind: GraphQLEnumType; + +/** + * Note that these are GraphQLField and not GraphQLFieldConfig, + * so the format for args is different. + */ + +export const SchemaMetaFieldDef: GraphQLField; +export const TypeMetaFieldDef: GraphQLField; +export const TypeNameMetaFieldDef: GraphQLField; + +export const introspectionTypes: ReadonlyArray; + +export function isIntrospectionType(type: any): boolean; diff --git a/tstypes/type/scalars.d.ts b/tstypes/type/scalars.d.ts new file mode 100644 index 00000000000..3cd8ad537c4 --- /dev/null +++ b/tstypes/type/scalars.d.ts @@ -0,0 +1,11 @@ +import { GraphQLScalarType } from './definition'; + +export const GraphQLInt: GraphQLScalarType; +export const GraphQLFloat: GraphQLScalarType; +export const GraphQLString: GraphQLScalarType; +export const GraphQLBoolean: GraphQLScalarType; +export const GraphQLID: GraphQLScalarType; + +export const specifiedScalarTypes: ReadonlyArray; + +export function isSpecifiedScalarType(type: GraphQLScalarType): boolean; diff --git a/tstypes/type/schema.d.ts b/tstypes/type/schema.d.ts new file mode 100644 index 00000000000..749eae4a92a --- /dev/null +++ b/tstypes/type/schema.d.ts @@ -0,0 +1,102 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLObjectType } from './definition'; +import { + GraphQLType, + GraphQLNamedType, + GraphQLAbstractType, +} from './definition'; +import { SchemaDefinitionNode, SchemaExtensionNode } from '../language/ast'; +import { GraphQLDirective } from './directives'; + +/** + * Test if the given value is a GraphQL schema. + */ +export function isSchema(schema: any): schema is GraphQLSchema; + +/** + * Schema Definition + * + * A Schema is created by supplying the root types of each type of operation, + * query and mutation (optional). A schema definition is then supplied to the + * validator and executor. + * + * Example: + * + * const MyAppSchema = new GraphQLSchema({ + * query: MyAppQueryRootType, + * mutation: MyAppMutationRootType, + * }) + * + * Note: If an array of `directives` are provided to GraphQLSchema, that will be + * the exact list of directives represented and allowed. If `directives` is not + * provided then a default set of the specified directives (e.g. @include and + * @skip) will be used. If you wish to provide *additional* directives to these + * specified directives, you must explicitly declare them. Example: + * + * const MyAppSchema = new GraphQLSchema({ + * ... + * directives: specifiedDirectives.concat([ myCustomDirective ]), + * }) + * + */ +export class GraphQLSchema { + astNode: Maybe; + extensionASTNodes: Maybe>; + + constructor(config: GraphQLSchemaConfig); + + getQueryType(): Maybe; + getMutationType(): Maybe; + getSubscriptionType(): Maybe; + getTypeMap(): TypeMap; + getType(name: string): Maybe; + getPossibleTypes( + abstractType: GraphQLAbstractType, + ): ReadonlyArray; + + isPossibleType( + abstractType: GraphQLAbstractType, + possibleType: GraphQLObjectType, + ): boolean; + + getDirectives(): ReadonlyArray; + getDirective(name: string): Maybe; + + toConfig(): GraphQLSchemaConfig & { + types: GraphQLNamedType[]; + directives: GraphQLDirective[]; + extensionASTNodes: ReadonlyArray; + }; +} + +type TypeMap = { [key: string]: GraphQLNamedType }; + +export interface GraphQLSchemaValidationOptions { + /** + * When building a schema from a GraphQL service's introspection result, it + * might be safe to assume the schema is valid. Set to true to assume the + * produced schema is valid. + * + * Default: false + */ + assumeValid?: boolean; + + /** + * If provided, the schema will consider fields or types with names included + * in this list valid, even if they do not adhere to the specification's + * schema validation rules. + * + * This option is provided to ease adoption and will be removed in v15. + */ + allowedLegacyNames?: Maybe>; +} + +export interface GraphQLSchemaConfig extends GraphQLSchemaValidationOptions { + query: Maybe; + mutation?: Maybe; + subscription?: Maybe; + types?: Maybe; + directives?: Maybe; + astNode?: Maybe; + extensionASTNodes?: Maybe>; +} diff --git a/tstypes/type/validate.d.ts b/tstypes/type/validate.d.ts new file mode 100644 index 00000000000..f6283f652a9 --- /dev/null +++ b/tstypes/type/validate.d.ts @@ -0,0 +1,19 @@ +import { GraphQLSchema } from './schema'; +import { GraphQLError } from '../error/GraphQLError'; + +/** + * Implements the "Type Validation" sub-sections of the specification's + * "Type System" section. + * + * Validation runs synchronously, returning an array of encountered errors, or + * an empty array if no errors were encountered and the Schema is valid. + */ +export function validateSchema( + schema: GraphQLSchema, +): ReadonlyArray; + +/** + * Utility function which asserts a schema is valid by throwing an error if + * it is invalid. + */ +export function assertValidSchema(schema: GraphQLSchema): void; diff --git a/tstypes/utilities/TypeInfo.d.ts b/tstypes/utilities/TypeInfo.d.ts new file mode 100644 index 00000000000..74d740b23d4 --- /dev/null +++ b/tstypes/utilities/TypeInfo.d.ts @@ -0,0 +1,49 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLSchema } from '../type/schema'; +import { + GraphQLOutputType, + GraphQLCompositeType, + GraphQLInputType, + GraphQLField, + GraphQLArgument, + GraphQLEnumValue, + GraphQLType, +} from '../type/definition'; +import { GraphQLDirective } from '../type/directives'; +import { ASTNode, FieldNode } from '../language/ast'; + +/** + * TypeInfo is a utility class which, given a GraphQL schema, can keep track + * of the current field and type definitions at any point in a GraphQL document + * AST during a recursive descent by calling `enter(node)` and `leave(node)`. + */ +export class TypeInfo { + constructor( + schema: GraphQLSchema, + // NOTE: this experimental optional second parameter is only needed in order + // to support non-spec-compliant codebases. You should never need to use it. + // It may disappear in the future. + getFieldDefFn?: getFieldDef, + // Initial type may be provided in rare cases to facilitate traversals + // beginning somewhere other than documents. + initialType?: GraphQLType, + ); + + getType(): Maybe; + getParentType(): Maybe; + getInputType(): Maybe; + getParentInputType(): Maybe; + getFieldDef(): GraphQLField>; + getDefaultValue(): Maybe; + getDirective(): Maybe; + getArgument(): Maybe; + getEnumValue(): Maybe; + enter(node: ASTNode): any; + leave(node: ASTNode): any; +} + +type getFieldDef = ( + schema: GraphQLSchema, + parentType: GraphQLType, + fieldNode: FieldNode, +) => Maybe>; diff --git a/tstypes/utilities/assertValidName.d.ts b/tstypes/utilities/assertValidName.d.ts new file mode 100644 index 00000000000..07d9b06ab73 --- /dev/null +++ b/tstypes/utilities/assertValidName.d.ts @@ -0,0 +1,15 @@ +import { GraphQLError } from '../error/GraphQLError'; +import { ASTNode } from '../language/ast'; + +/** + * Upholds the spec rules about naming. + */ +export function assertValidName(name: string): string; + +/** + * Returns an Error if a name is invalid. + */ +export function isValidNameError( + name: string, + node?: ASTNode | undefined, +): GraphQLError | undefined; diff --git a/tstypes/utilities/astFromValue.d.ts b/tstypes/utilities/astFromValue.d.ts new file mode 100644 index 00000000000..ed84eb458f1 --- /dev/null +++ b/tstypes/utilities/astFromValue.d.ts @@ -0,0 +1,25 @@ +import Maybe from '../tsutils/Maybe'; +import { ValueNode } from '../language/ast'; +import { GraphQLInputType } from '../type/definition'; + +/** + * Produces a GraphQL Value AST given a JavaScript value. + * + * A GraphQL type must be provided, which will be used to interpret different + * JavaScript values. + * + * | JSON Value | GraphQL Value | + * | ------------- | -------------------- | + * | Object | Input Object | + * | Array | List | + * | Boolean | Boolean | + * | String | String / Enum Value | + * | Number | Int / Float | + * | Mixed | Enum Value | + * | null | NullValue | + * + */ +export function astFromValue( + value: any, + type: GraphQLInputType, +): Maybe; diff --git a/tstypes/utilities/buildASTSchema.d.ts b/tstypes/utilities/buildASTSchema.d.ts new file mode 100644 index 00000000000..9c4c58adb6e --- /dev/null +++ b/tstypes/utilities/buildASTSchema.d.ts @@ -0,0 +1,112 @@ +import Maybe from '../tsutils/Maybe'; +import { + DocumentNode, + Location, + StringValueNode, + TypeDefinitionNode, + NamedTypeNode, + DirectiveDefinitionNode, + FieldDefinitionNode, + InputValueDefinitionNode, + EnumValueDefinitionNode, +} from '../language/ast'; +import { + GraphQLNamedType, + GraphQLFieldConfig, + GraphQLInputField, + GraphQLEnumValueConfig, +} from '../type/definition'; +import { GraphQLDirective } from '../type/directives'; +import { Source } from '../language/source'; +import { GraphQLSchema, GraphQLSchemaValidationOptions } from '../type/schema'; +import { ParseOptions } from '../language/parser'; +import { dedentBlockStringValue } from '../language/blockString'; + +interface BuildSchemaOptions extends GraphQLSchemaValidationOptions { + /** + * Descriptions are defined as preceding string literals, however an older + * experimental version of the SDL supported preceding comments as + * descriptions. Set to true to enable this deprecated behavior. + * This option is provided to ease adoption and will be removed in v16. + * + * Default: false + */ + commentDescriptions?: boolean; + + /** + * Set to true to assume the SDL is valid. + * + * Default: false + */ + assumeValidSDL?: boolean; +} + +/** + * This takes the ast of a schema document produced by the parse function in + * src/language/parser.js. + * + * If no schema definition is provided, then it will look for types named Query + * and Mutation. + * + * Given that AST it constructs a GraphQLSchema. The resulting schema + * has no resolve methods, so execution will use default resolvers. + * + * Accepts options as a second argument: + * + * - commentDescriptions: + * Provide true to use preceding comments as the description. + * + */ +export function buildASTSchema( + documentAST: DocumentNode, + options?: BuildSchemaOptions, +): GraphQLSchema; + +type TypeDefinitionsMap = { [key: string]: TypeDefinitionNode }; +type TypeResolver = (typeRef: NamedTypeNode) => GraphQLNamedType; + +export class ASTDefinitionBuilder { + constructor( + typeDefinitionsMap: TypeDefinitionsMap, + options: Maybe, + resolveType: TypeResolver, + ); + + buildTypes( + nodes: ReadonlyArray, + ): Array; + + buildType(node: NamedTypeNode | TypeDefinitionNode): GraphQLNamedType; + + buildDirective(directiveNode: DirectiveDefinitionNode): GraphQLDirective; + + buildField(field: FieldDefinitionNode): GraphQLFieldConfig; + + buildInputField(value: InputValueDefinitionNode): GraphQLInputField; + + buildEnumValue(value: EnumValueDefinitionNode): GraphQLEnumValueConfig; +} + +/** + * Given an ast node, returns its string description. + * @deprecated: provided to ease adoption and will be removed in v16. + * + * Accepts options as a second argument: + * + * - commentDescriptions: + * Provide true to use preceding comments as the description. + * + */ +export function getDescription( + node: { readonly description?: StringValueNode; readonly loc?: Location }, + options: Maybe, +): string | undefined; + +/** + * A helper function to build a GraphQLSchema directly from a source + * document. + */ +export function buildSchema( + source: string | Source, + options?: BuildSchemaOptions & ParseOptions, +): GraphQLSchema; diff --git a/tstypes/utilities/buildClientSchema.d.ts b/tstypes/utilities/buildClientSchema.d.ts new file mode 100644 index 00000000000..42bd106cf18 --- /dev/null +++ b/tstypes/utilities/buildClientSchema.d.ts @@ -0,0 +1,21 @@ +import { IntrospectionQuery } from './introspectionQuery'; +import { GraphQLSchema, GraphQLSchemaValidationOptions } from '../type/schema'; + +interface Options extends GraphQLSchemaValidationOptions {} + +/** + * Build a GraphQLSchema for use by client tools. + * + * Given the result of a client running the introspection query, creates and + * returns a GraphQLSchema instance which can be then used with all graphql-js + * tools, but cannot be used to execute a query, as introspection does not + * represent the "resolver", "parse" or "serialize" functions or any other + * server-internal mechanisms. + * + * This function expects a complete introspection result. Don't forget to check + * the "errors" field of a server response before calling this function. + */ +export function buildClientSchema( + introspection: IntrospectionQuery, + options?: Options, +): GraphQLSchema; diff --git a/tstypes/utilities/coerceValue.d.ts b/tstypes/utilities/coerceValue.d.ts new file mode 100644 index 00000000000..96fafdca6a9 --- /dev/null +++ b/tstypes/utilities/coerceValue.d.ts @@ -0,0 +1,27 @@ +import { GraphQLError } from '../error/GraphQLError'; +import { ASTNode } from '../language/ast'; +import { GraphQLInputType } from '../type/definition'; + +interface CoercedValue { + readonly errors: ReadonlyArray | undefined; + readonly value: any; +} + +interface Path { + readonly prev: Path | undefined; + readonly key: string | number; +} + +/** + * Coerces a JavaScript value given a GraphQL Type. + * + * Returns either a value which is valid for the provided type or a list of + * encountered coercion errors. + * + */ +export function coerceValue( + value: any, + type: GraphQLInputType, + blameNode?: ASTNode, + path?: Path, +): CoercedValue; diff --git a/tstypes/utilities/concatAST.d.ts b/tstypes/utilities/concatAST.d.ts new file mode 100644 index 00000000000..03d441e1cae --- /dev/null +++ b/tstypes/utilities/concatAST.d.ts @@ -0,0 +1,8 @@ +import { DocumentNode } from '../language/ast'; + +/** + * Provided a collection of ASTs, presumably each from different files, + * concatenate the ASTs together into batched AST, useful for validating many + * GraphQL source files which together represent one conceptual application. + */ +export function concatAST(asts: ReadonlyArray): DocumentNode; diff --git a/tstypes/utilities/extendSchema.d.ts b/tstypes/utilities/extendSchema.d.ts new file mode 100644 index 00000000000..2f0007ba89a --- /dev/null +++ b/tstypes/utilities/extendSchema.d.ts @@ -0,0 +1,46 @@ +import { DocumentNode } from '../language/ast'; +import { GraphQLSchema } from '../type/schema'; +import { GraphQLSchemaValidationOptions } from '../type/schema'; + +interface Options extends GraphQLSchemaValidationOptions { + /** + * Descriptions are defined as preceding string literals, however an older + * experimental version of the SDL supported preceding comments as + * descriptions. Set to true to enable this deprecated behavior. + * This option is provided to ease adoption and will be removed in v16. + * + * Default: false + */ + commentDescriptions?: boolean; + + /** + * Set to true to assume the SDL is valid. + * + * Default: false + */ + assumeValidSDL?: boolean; +} + +/** + * Produces a new schema given an existing schema and a document which may + * contain GraphQL type extensions and definitions. The original schema will + * remain unaltered. + * + * Because a schema represents a graph of references, a schema cannot be + * extended without effectively making an entire copy. We do not know until it's + * too late if subgraphs remain unchanged. + * + * This algorithm copies the provided schema, applying extensions while + * producing the copy. The original schema remains unaltered. + * + * Accepts options as a third argument: + * + * - commentDescriptions: + * Provide true to use preceding comments as the description. + * + */ +export function extendSchema( + schema: GraphQLSchema, + documentAST: DocumentNode, + options?: Options, +): GraphQLSchema; diff --git a/tstypes/utilities/findBreakingChanges.d.ts b/tstypes/utilities/findBreakingChanges.d.ts new file mode 100644 index 00000000000..75daa4f946f --- /dev/null +++ b/tstypes/utilities/findBreakingChanges.d.ts @@ -0,0 +1,190 @@ +import { + getNamedType, + GraphQLScalarType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLObjectType, + GraphQLUnionType, + GraphQLNamedType, +} from '../type/definition'; +import { GraphQLDirective } from '../type/directives'; +import { GraphQLSchema } from '../type/schema'; +import { DirectiveLocationEnum } from '../language/directiveLocation'; + +export const BreakingChangeType: _BreakingChangeType; + +// @internal +type _BreakingChangeType = { + FIELD_CHANGED_KIND: 'FIELD_CHANGED_KIND'; + FIELD_REMOVED: 'FIELD_REMOVED'; + TYPE_CHANGED_KIND: 'TYPE_CHANGED_KIND'; + TYPE_REMOVED: 'TYPE_REMOVED'; + TYPE_REMOVED_FROM_UNION: 'TYPE_REMOVED_FROM_UNION'; + VALUE_REMOVED_FROM_ENUM: 'VALUE_REMOVED_FROM_ENUM'; + ARG_REMOVED: 'ARG_REMOVED'; + ARG_CHANGED_KIND: 'ARG_CHANGED_KIND'; + REQUIRED_ARG_ADDED: 'REQUIRED_ARG_ADDED'; + REQUIRED_INPUT_FIELD_ADDED: 'REQUIRED_INPUT_FIELD_ADDED'; + INTERFACE_REMOVED_FROM_OBJECT: 'INTERFACE_REMOVED_FROM_OBJECT'; + DIRECTIVE_REMOVED: 'DIRECTIVE_REMOVED'; + DIRECTIVE_ARG_REMOVED: 'DIRECTIVE_ARG_REMOVED'; + DIRECTIVE_LOCATION_REMOVED: 'DIRECTIVE_LOCATION_REMOVED'; + REQUIRED_DIRECTIVE_ARG_ADDED: 'REQUIRED_DIRECTIVE_ARG_ADDED'; +}; + +export const DangerousChangeType: _DangerousChangeType; + +// @internal +type _DangerousChangeType = { + ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE'; + VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM'; + INTERFACE_ADDED_TO_OBJECT: 'INTERFACE_ADDED_TO_OBJECT'; + TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION'; + OPTIONAL_INPUT_FIELD_ADDED: 'OPTIONAL_INPUT_FIELD_ADDED'; + OPTIONAL_ARG_ADDED: 'OPTIONAL_ARG_ADDED'; +}; + +export interface BreakingChange { + type: keyof _BreakingChangeType; + description: string; +} + +export interface DangerousChange { + type: keyof _DangerousChangeType; + description: string; +} + +/** + * Given two schemas, returns an Array containing descriptions of all the types + * of breaking changes covered by the other functions down below. + */ +export function findBreakingChanges( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of all the types + * of potentially dangerous changes covered by the other functions down below. + */ +export function findDangerousChanges( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any breaking + * changes in the newSchema related to removing an entire type. + */ +export function findRemovedTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any breaking + * changes in the newSchema related to changing the type of a type. + */ +export function findTypesThatChangedKind( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any + * breaking or dangerous changes in the newSchema related to arguments + * (such as removal or change of type of an argument, or a change in an + * argument's default value). + */ +export function findArgChanges( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): { + breakingChanges: Array; + dangerousChanges: Array; +}; + +export function findFieldsThatChangedTypeOnObjectOrInterfaceTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findFieldsThatChangedTypeOnInputObjectTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): { + breakingChanges: Array; + dangerousChanges: Array; +}; + +/** + * Given two schemas, returns an Array containing descriptions of any breaking + * changes in the newSchema related to removing types from a union type. + */ +export function findTypesRemovedFromUnions( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any dangerous + * changes in the newSchema related to adding types to a union type. + */ +export function findTypesAddedToUnions( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any breaking + * changes in the newSchema related to removing values from an enum type. + */ +export function findValuesRemovedFromEnums( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +/** + * Given two schemas, returns an Array containing descriptions of any dangerous + * changes in the newSchema related to adding values to an enum type. + */ +export function findValuesAddedToEnums( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findInterfacesRemovedFromObjectTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findInterfacesAddedToObjectTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findRemovedDirectives( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findRemovedDirectiveArgs( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findAddedNonNullDirectiveArgs( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; + +export function findRemovedLocationsForDirective( + oldDirective: GraphQLDirective, + newDirective: GraphQLDirective, +): Array; + +export function findRemovedDirectiveLocations( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema, +): Array; diff --git a/tstypes/utilities/findDeprecatedUsages.d.ts b/tstypes/utilities/findDeprecatedUsages.d.ts new file mode 100644 index 00000000000..8cd844e15f7 --- /dev/null +++ b/tstypes/utilities/findDeprecatedUsages.d.ts @@ -0,0 +1,13 @@ +import { GraphQLSchema } from '../type/schema'; +import { DocumentNode } from '../language/ast'; +import { GraphQLError } from '../error/GraphQLError'; + +/** + * A validation rule which reports deprecated usages. + * + * Returns a list of GraphQLError instances describing each deprecated use. + */ +export function findDeprecatedUsages( + schema: GraphQLSchema, + ast: DocumentNode, +): GraphQLError[]; diff --git a/tstypes/utilities/getOperationAST.d.ts b/tstypes/utilities/getOperationAST.d.ts new file mode 100644 index 00000000000..9f72b7eeca6 --- /dev/null +++ b/tstypes/utilities/getOperationAST.d.ts @@ -0,0 +1,12 @@ +import Maybe from '../tsutils/Maybe'; +import { DocumentNode, OperationDefinitionNode } from '../language/ast'; + +/** + * Returns an operation AST given a document AST and optionally an operation + * name. If a name is not provided, an operation is only returned if only one is + * provided in the document. + */ +export function getOperationAST( + documentAST: DocumentNode, + operationName: Maybe, +): Maybe; diff --git a/tstypes/utilities/getOperationRootType.d.ts b/tstypes/utilities/getOperationRootType.d.ts new file mode 100644 index 00000000000..f82eeecbc16 --- /dev/null +++ b/tstypes/utilities/getOperationRootType.d.ts @@ -0,0 +1,14 @@ +import { GraphQLSchema } from '../type/schema'; +import { + OperationDefinitionNode, + OperationTypeDefinitionNode, +} from '../language/ast'; +import { GraphQLObjectType } from '../type/definition'; + +/** + * Extracts the root type of the operation from the schema. + */ +export function getOperationRootType( + schema: GraphQLSchema, + operation: OperationDefinitionNode | OperationTypeDefinitionNode, +): GraphQLObjectType; diff --git a/tstypes/utilities/index.d.ts b/tstypes/utilities/index.d.ts new file mode 100644 index 00000000000..a459298c5b8 --- /dev/null +++ b/tstypes/utilities/index.d.ts @@ -0,0 +1,120 @@ +// The GraphQL query recommended for a full schema introspection. +export { + getIntrospectionQuery, + // @deprecated, use getIntrospectionQuery() - will be removed in v15 + introspectionQuery, +} from './introspectionQuery'; + +export { + IntrospectionOptions, + IntrospectionQuery, + IntrospectionSchema, + IntrospectionType, + IntrospectionInputType, + IntrospectionOutputType, + IntrospectionScalarType, + IntrospectionObjectType, + IntrospectionInterfaceType, + IntrospectionUnionType, + IntrospectionEnumType, + IntrospectionInputObjectType, + IntrospectionTypeRef, + IntrospectionInputTypeRef, + IntrospectionOutputTypeRef, + IntrospectionNamedTypeRef, + IntrospectionListTypeRef, + IntrospectionNonNullTypeRef, + IntrospectionField, + IntrospectionInputValue, + IntrospectionEnumValue, + IntrospectionDirective, +} from './introspectionQuery'; + +// Gets the target Operation from a Document +export { getOperationAST } from './getOperationAST'; + +// Gets the Type for the target Operation AST. +export { getOperationRootType } from './getOperationRootType'; + +// Convert a GraphQLSchema to an IntrospectionQuery +export { introspectionFromSchema } from './introspectionFromSchema'; + +// Build a GraphQLSchema from an introspection result. +export { buildClientSchema } from './buildClientSchema'; + +// Build a GraphQLSchema from GraphQL Schema language. +export { + buildASTSchema, + buildSchema, + // @deprecated: Get the description from a schema AST node and supports legacy + // syntax for specifying descriptions - will be removed in v16 + getDescription, + BuildSchemaOptions, +} from './buildASTSchema'; + +// Extends an existing GraphQLSchema from a parsed GraphQL Schema language AST. +export { extendSchema } from './extendSchema'; + +// Sort a GraphQLSchema. +export { lexicographicSortSchema } from './lexicographicSortSchema'; + +// Print a GraphQLSchema to GraphQL Schema language. +export { + printSchema, + printType, + printIntrospectionSchema, +} from './schemaPrinter'; + +// Create a GraphQLType from a GraphQL language AST. +export { typeFromAST } from './typeFromAST'; + +// Create a JavaScript value from a GraphQL language AST with a type. +export { valueFromAST } from './valueFromAST'; + +// Create a JavaScript value from a GraphQL language AST without a type. +export { valueFromASTUntyped } from './valueFromASTUntyped'; + +// Create a GraphQL language AST from a JavaScript value. +export { astFromValue } from './astFromValue'; + +// A helper to use within recursive-descent visitors which need to be aware of +// the GraphQL type system. +export { TypeInfo } from './TypeInfo'; + +// Coerces a JavaScript value to a GraphQL type, or produces errors. +export { coerceValue } from './coerceValue'; + +// @deprecated use coerceValue - will be removed in v15 +export { isValidJSValue } from './isValidJSValue'; + +// @deprecated use validation - will be removed in v15 +export { isValidLiteralValue } from './isValidLiteralValue'; + +// Concatenates multiple AST together. +export { concatAST } from './concatAST'; + +// Separates an AST into an AST per Operation. +export { separateOperations } from './separateOperations'; + +// Comparators for types +export { + isEqualType, + isTypeSubTypeOf, + doTypesOverlap, +} from './typeComparators'; + +// Asserts that a string is a valid GraphQL name +export { assertValidName, isValidNameError } from './assertValidName'; + +// Compares two GraphQLSchemas and detects breaking changes. +export { + BreakingChangeType, + DangerousChangeType, + findBreakingChanges, + findDangerousChanges, + BreakingChange, + DangerousChange, +} from './findBreakingChanges'; + +// Report all deprecated usage within a GraphQL document. +export { findDeprecatedUsages } from './findDeprecatedUsages'; diff --git a/tstypes/utilities/introspectionFromSchema.d.ts b/tstypes/utilities/introspectionFromSchema.d.ts new file mode 100644 index 00000000000..e0dcd63348c --- /dev/null +++ b/tstypes/utilities/introspectionFromSchema.d.ts @@ -0,0 +1,16 @@ +import { GraphQLSchema } from '../type/schema'; +import { IntrospectionQuery, IntrospectionOptions } from './introspectionQuery'; + +/** + * Build an IntrospectionQuery from a GraphQLSchema + * + * IntrospectionQuery is useful for utilities that care about type and field + * relationships, but do not need to traverse through those relationships. + * + * This is the inverse of buildClientSchema. The primary use case is outside + * of the server context, for instance when doing schema comparisons. + */ +export function introspectionFromSchema( + schema: GraphQLSchema, + options?: IntrospectionOptions, +): IntrospectionQuery; diff --git a/tstypes/utilities/introspectionQuery.d.ts b/tstypes/utilities/introspectionQuery.d.ts new file mode 100644 index 00000000000..714beacfedb --- /dev/null +++ b/tstypes/utilities/introspectionQuery.d.ts @@ -0,0 +1,177 @@ +import Maybe from '../tsutils/Maybe'; +import { DirectiveLocationEnum } from '../language/directiveLocation'; + +export interface IntrospectionOptions { + // Whether to include descriptions in the introspection result. + // Default: true + descriptions: boolean; +} + +export function getIntrospectionQuery(options?: IntrospectionOptions): string; + +/** + * Deprecated, call getIntrospectionQuery directly. + * + * This function will be removed in v15 + */ +export const introspectionQuery: string; + +export interface IntrospectionQuery { + readonly __schema: IntrospectionSchema; +} + +export interface IntrospectionSchema { + readonly queryType: IntrospectionNamedTypeRef; + readonly mutationType: Maybe< + IntrospectionNamedTypeRef + >; + readonly subscriptionType: Maybe< + IntrospectionNamedTypeRef + >; + readonly types: ReadonlyArray; + readonly directives: ReadonlyArray; +} + +export type IntrospectionType = + | IntrospectionScalarType + | IntrospectionObjectType + | IntrospectionInterfaceType + | IntrospectionUnionType + | IntrospectionEnumType + | IntrospectionInputObjectType; + +export type IntrospectionOutputType = + | IntrospectionScalarType + | IntrospectionObjectType + | IntrospectionInterfaceType + | IntrospectionUnionType + | IntrospectionEnumType; + +export type IntrospectionInputType = + | IntrospectionScalarType + | IntrospectionEnumType + | IntrospectionInputObjectType; + +export interface IntrospectionScalarType { + readonly kind: 'SCALAR'; + readonly name: string; + readonly description?: Maybe; +} + +export interface IntrospectionObjectType { + readonly kind: 'OBJECT'; + readonly name: string; + readonly description?: Maybe; + readonly fields: ReadonlyArray; + readonly interfaces: ReadonlyArray< + IntrospectionNamedTypeRef + >; +} + +export interface IntrospectionInterfaceType { + readonly kind: 'INTERFACE'; + readonly name: string; + readonly description?: Maybe; + readonly fields: ReadonlyArray; + readonly possibleTypes: ReadonlyArray< + IntrospectionNamedTypeRef + >; +} + +export interface IntrospectionUnionType { + readonly kind: 'UNION'; + readonly name: string; + readonly description?: Maybe; + readonly possibleTypes: ReadonlyArray< + IntrospectionNamedTypeRef + >; +} + +export interface IntrospectionEnumType { + readonly kind: 'ENUM'; + readonly name: string; + readonly description?: Maybe; + readonly enumValues: ReadonlyArray; +} + +export interface IntrospectionInputObjectType { + readonly kind: 'INPUT_OBJECT'; + readonly name: string; + readonly description?: Maybe; + readonly inputFields: ReadonlyArray; +} + +export interface IntrospectionListTypeRef< + T extends IntrospectionTypeRef = IntrospectionTypeRef +> { + readonly kind: 'LIST'; + readonly ofType: T; +} + +export interface IntrospectionNonNullTypeRef< + T extends IntrospectionTypeRef = IntrospectionTypeRef +> { + readonly kind: 'NON_NULL'; + readonly ofType: T; +} + +export type IntrospectionTypeRef = + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + | IntrospectionNonNullTypeRef< + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + >; + +export type IntrospectionOutputTypeRef = + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + | IntrospectionNonNullTypeRef< + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + >; + +export type IntrospectionInputTypeRef = + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + | IntrospectionNonNullTypeRef< + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + >; + +export interface IntrospectionNamedTypeRef< + T extends IntrospectionType = IntrospectionType +> { + readonly kind: T['kind']; + readonly name: string; +} + +export interface IntrospectionField { + readonly name: string; + readonly description?: Maybe; + readonly args: ReadonlyArray; + readonly type: IntrospectionOutputTypeRef; + readonly isDeprecated: boolean; + readonly deprecationReason?: Maybe; +} + +export interface IntrospectionInputValue { + readonly name: string; + readonly description?: Maybe; + readonly type: IntrospectionInputTypeRef; + readonly defaultValue?: Maybe; +} + +export interface IntrospectionEnumValue { + readonly name: string; + readonly description?: Maybe; + readonly isDeprecated: boolean; + readonly deprecationReason?: Maybe; +} + +export interface IntrospectionDirective { + readonly name: string; + readonly description?: Maybe; + readonly locations: ReadonlyArray; + readonly args: ReadonlyArray; +} diff --git a/tstypes/utilities/isValidJSValue.d.ts b/tstypes/utilities/isValidJSValue.d.ts new file mode 100644 index 00000000000..36d24efbac3 --- /dev/null +++ b/tstypes/utilities/isValidJSValue.d.ts @@ -0,0 +1,8 @@ +import { GraphQLInputType } from '../type/definition'; + +/** + * Deprecated. Use coerceValue() directly for richer information. + * + * This function will be removed in v15 + */ +export function isValidJSValue(value: any, type: GraphQLInputType): string[]; diff --git a/tstypes/utilities/isValidLiteralValue.d.ts b/tstypes/utilities/isValidLiteralValue.d.ts new file mode 100644 index 00000000000..c0c4eb4cfbc --- /dev/null +++ b/tstypes/utilities/isValidLiteralValue.d.ts @@ -0,0 +1,15 @@ +import { GraphQLError } from '../error/GraphQLError'; +import { ValueNode } from '../language/ast'; +import { GraphQLInputType } from '../type/definition'; + +/** + * Utility which determines if a value literal node is valid for an input type. + * + * Deprecated. Rely on validation for documents containing literal values. + * + * This function will be removed in v15 + */ +export function isValidLiteralValue( + type: GraphQLInputType, + valueNode: ValueNode, +): ReadonlyArray; diff --git a/tstypes/utilities/lexicographicSortSchema.d.ts b/tstypes/utilities/lexicographicSortSchema.d.ts new file mode 100644 index 00000000000..0cba04c0e8c --- /dev/null +++ b/tstypes/utilities/lexicographicSortSchema.d.ts @@ -0,0 +1,6 @@ +import { GraphQLSchema } from '../type/schema'; + +/** + * Sort GraphQLSchema. + */ +export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema; diff --git a/tstypes/utilities/schemaPrinter.d.ts b/tstypes/utilities/schemaPrinter.d.ts new file mode 100644 index 00000000000..fa723b7c32b --- /dev/null +++ b/tstypes/utilities/schemaPrinter.d.ts @@ -0,0 +1,30 @@ +import { GraphQLSchema } from '../type/schema'; +import { GraphQLType, GraphQLNamedType } from '../type/definition'; + +export interface Options { + /** + * Descriptions are defined as preceding string literals, however an older + * experimental version of the SDL supported preceding comments as + * descriptions. Set to true to enable this deprecated behavior. + * This option is provided to ease adoption and will be removed in v16. + * + * Default: false + */ + commentDescriptions?: boolean; +} + +/** + * Accepts options as a second argument: + * + * - commentDescriptions: + * Provide true to use preceding comments as the description. + * + */ +export function printSchema(schema: GraphQLSchema, options?: Options): string; + +export function printIntrospectionSchema( + schema: GraphQLSchema, + options?: Options, +): string; + +export function printType(type: GraphQLNamedType, options?: Options): string; diff --git a/tstypes/utilities/separateOperations.d.ts b/tstypes/utilities/separateOperations.d.ts new file mode 100644 index 00000000000..d3dcb6e9576 --- /dev/null +++ b/tstypes/utilities/separateOperations.d.ts @@ -0,0 +1,11 @@ +import { DocumentNode, OperationDefinitionNode } from '../language/ast'; + +/** + * separateOperations accepts a single AST document which may contain many + * operations and fragments and returns a collection of AST documents each of + * which contains a single operation as well the fragment definitions it + * refers to. + */ +export function separateOperations( + documentAST: DocumentNode, +): { [key: string]: DocumentNode }; diff --git a/tstypes/utilities/typeComparators.d.ts b/tstypes/utilities/typeComparators.d.ts new file mode 100644 index 00000000000..ca0cdaf6c25 --- /dev/null +++ b/tstypes/utilities/typeComparators.d.ts @@ -0,0 +1,36 @@ +import { + GraphQLType, + GraphQLCompositeType, + GraphQLAbstractType, +} from '../type/definition'; +import { GraphQLSchema } from '../type/schema'; + +/** + * Provided two types, return true if the types are equal (invariant). + */ +export function isEqualType(typeA: GraphQLType, typeB: GraphQLType): boolean; + +/** + * Provided a type and a super type, return true if the first type is either + * equal or a subset of the second super type (covariant). + */ +export function isTypeSubTypeOf( + schema: GraphQLSchema, + maybeSubType: GraphQLType, + superType: GraphQLType, +): boolean; + +/** + * Provided two composite types, determine if they "overlap". Two composite + * types overlap when the Sets of possible concrete types for each intersect. + * + * This is often used to determine if a fragment of a given type could possibly + * be visited in a context of another type. + * + * This function is commutative. + */ +export function doTypesOverlap( + schema: GraphQLSchema, + typeA: GraphQLCompositeType, + typeB: GraphQLCompositeType, +): boolean; diff --git a/tstypes/utilities/typeFromAST.d.ts b/tstypes/utilities/typeFromAST.d.ts new file mode 100644 index 00000000000..10e467dee99 --- /dev/null +++ b/tstypes/utilities/typeFromAST.d.ts @@ -0,0 +1,36 @@ +import { + TypeNode, + NamedTypeNode, + ListTypeNode, + NonNullTypeNode, +} from '../language/ast'; +import { + GraphQLType, + GraphQLNullableType, + GraphQLNamedType, + GraphQLList, + GraphQLNonNull, +} from '../type/definition'; +import { GraphQLSchema } from '../type/schema'; + +/** + * Given a Schema and an AST node describing a type, return a GraphQLType + * definition which applies to that type. For example, if provided the parsed + * AST node for `[User]`, a GraphQLList instance will be returned, containing + * the type called "User" found in the schema. If a type called "User" is not + * found in the schema, then undefined will be returned. + */ +export function typeFromAST( + schema: GraphQLSchema, + typeNode: NamedTypeNode, +): GraphQLNamedType | undefined; + +export function typeFromAST( + schema: GraphQLSchema, + typeNode: ListTypeNode, +): GraphQLList | undefined; + +export function typeFromAST( + schema: GraphQLSchema, + typeNode: NonNullTypeNode, +): GraphQLNonNull | undefined; diff --git a/tstypes/utilities/valueFromAST.d.ts b/tstypes/utilities/valueFromAST.d.ts new file mode 100644 index 00000000000..06a130aebfa --- /dev/null +++ b/tstypes/utilities/valueFromAST.d.ts @@ -0,0 +1,34 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLInputType } from '../type/definition'; +import { + ValueNode, + VariableNode, + ListValueNode, + ObjectValueNode, +} from '../language/ast'; + +/** + * Produces a JavaScript value given a GraphQL Value AST. + * + * A GraphQL type must be provided, which will be used to interpret different + * GraphQL Value literals. + * + * Returns `undefined` when the value could not be validly coerced according to + * the provided type. + * + * | GraphQL Value | JSON Value | + * | -------------------- | ------------- | + * | Input Object | Object | + * | List | Array | + * | Boolean | Boolean | + * | String | String | + * | Int / Float | Number | + * | Enum Value | Mixed | + * | NullValue | null | + * + */ +export function valueFromAST( + valueNode: Maybe, + type: GraphQLInputType, + variables?: Maybe<{ [key: string]: any }>, +): any; diff --git a/tstypes/utilities/valueFromASTUntyped.d.ts b/tstypes/utilities/valueFromASTUntyped.d.ts new file mode 100644 index 00000000000..ab7512e465b --- /dev/null +++ b/tstypes/utilities/valueFromASTUntyped.d.ts @@ -0,0 +1,23 @@ +import Maybe from '../tsutils/Maybe'; +import { ValueNode } from '../language/ast'; + +/** + * Produces a JavaScript value given a GraphQL Value AST. + * + * Unlike `valueFromAST()`, no type is provided. The resulting JavaScript value + * will reflect the provided GraphQL value AST. + * + * | GraphQL Value | JavaScript Value | + * | -------------------- | ---------------- | + * | Input Object | Object | + * | List | Array | + * | Boolean | Boolean | + * | String / Enum | String | + * | Int / Float | Number | + * | Null | null | + * + */ +export function valueFromASTUntyped( + valueNode: ValueNode, + variables?: Maybe<{ [key: string]: any }>, +): any; diff --git a/tstypes/validation/ValidationContext.d.ts b/tstypes/validation/ValidationContext.d.ts new file mode 100644 index 00000000000..1576bdc64e0 --- /dev/null +++ b/tstypes/validation/ValidationContext.d.ts @@ -0,0 +1,87 @@ +import Maybe from '../tsutils/Maybe'; +import { GraphQLError } from '../error'; +import { + DocumentNode, + OperationDefinitionNode, + VariableNode, + SelectionSetNode, + FragmentSpreadNode, + FragmentDefinitionNode, +} from '../language/ast'; +import { GraphQLSchema } from '../type/schema'; +import { + GraphQLInputType, + GraphQLOutputType, + GraphQLCompositeType, + GraphQLField, + GraphQLArgument, +} from '../type/definition'; +import { GraphQLDirective } from '../type/directives'; +import { TypeInfo } from '../utilities/TypeInfo'; +import { ASTVisitor } from '../language/visitor'; + +type NodeWithSelectionSet = OperationDefinitionNode | FragmentDefinitionNode; +type VariableUsage = { + readonly node: VariableNode; + readonly type: Maybe; + readonly defaultValue: Maybe; +}; + +/** + * An instance of this class is passed as the "this" context to all validators, + * allowing access to commonly useful contextual information from within a + * validation rule. + */ +export class ASTValidationContext { + constructor(ast: DocumentNode); + + reportError(error: GraphQLError): undefined; + + getErrors(): ReadonlyArray; + + getDocument(): DocumentNode; +} + +export class SDLValidationContext extends ASTValidationContext { + constructor(ast: DocumentNode, schema?: Maybe); + + getSchema(): Maybe; +} + +export type SDLValidationRule = (context: SDLValidationContext) => ASTVisitor; + +export class ValidationContext extends ASTValidationContext { + constructor(schema: GraphQLSchema, ast: DocumentNode, typeInfo: TypeInfo); + + getSchema(): GraphQLSchema; + + getFragment(name: string): Maybe; + + getFragmentSpreads(node: SelectionSetNode): ReadonlyArray; + + getRecursivelyReferencedFragments( + operation: OperationDefinitionNode, + ): ReadonlyArray; + + getVariableUsages(node: NodeWithSelectionSet): ReadonlyArray; + + getRecursiveVariableUsages( + operation: OperationDefinitionNode, + ): ReadonlyArray; + + getType(): Maybe; + + getParentType(): Maybe; + + getInputType(): Maybe; + + getParentInputType(): Maybe; + + getFieldDef(): Maybe>; + + getDirective(): Maybe; + + getArgument(): Maybe; +} + +export type ValidationRule = (context: ValidationContext) => ASTVisitor; diff --git a/tstypes/validation/index.d.ts b/tstypes/validation/index.d.ts new file mode 100644 index 00000000000..3d8f38e80d8 --- /dev/null +++ b/tstypes/validation/index.d.ts @@ -0,0 +1,126 @@ +export { validate } from './validate'; + +export { ValidationContext } from './ValidationContext'; + +export { specifiedRules } from './specifiedRules'; + +// Spec Section: "Field Selections on Objects, Interfaces, and Unions Types" +export { + FieldsOnCorrectType as FieldsOnCorrectTypeRule, +} from './rules/FieldsOnCorrectType'; + +// Spec Section: "Fragments on Composite Types" +export { + FragmentsOnCompositeTypes as FragmentsOnCompositeTypesRule, +} from './rules/FragmentsOnCompositeTypes'; + +// Spec Section: "Argument Names" +export { + KnownArgumentNames as KnownArgumentNamesRule, +} from './rules/KnownArgumentNames'; + +// Spec Section: "Directives Are Defined" +export { + KnownDirectives as KnownDirectivesRule, +} from './rules/KnownDirectives'; + +// Spec Section: "Fragment spread target defined" +export { + KnownFragmentNames as KnownFragmentNamesRule, +} from './rules/KnownFragmentNames'; + +// Spec Section: "Fragment Spread Type Existence" +export { KnownTypeNames as KnownTypeNamesRule } from './rules/KnownTypeNames'; + +// Spec Section: "Lone Anonymous Operation" +export { + LoneAnonymousOperation as LoneAnonymousOperationRule, +} from './rules/LoneAnonymousOperation'; + +// Spec Section: "Fragments must not form cycles" +export { + NoFragmentCycles as NoFragmentCyclesRule, +} from './rules/NoFragmentCycles'; + +// Spec Section: "All Variable Used Defined" +export { + NoUndefinedVariables as NoUndefinedVariablesRule, +} from './rules/NoUndefinedVariables'; + +// Spec Section: "Fragments must be used" +export { + NoUnusedFragments as NoUnusedFragmentsRule, +} from './rules/NoUnusedFragments'; + +// Spec Section: "All Variables Used" +export { + NoUnusedVariables as NoUnusedVariablesRule, +} from './rules/NoUnusedVariables'; + +// Spec Section: "Field Selection Merging" +export { + OverlappingFieldsCanBeMerged as OverlappingFieldsCanBeMergedRule, +} from './rules/OverlappingFieldsCanBeMerged'; + +// Spec Section: "Fragment spread is possible" +export { + PossibleFragmentSpreads as PossibleFragmentSpreadsRule, +} from './rules/PossibleFragmentSpreads'; + +// Spec Section: "Argument Optionality" +export { + ProvidedRequiredArguments as ProvidedRequiredArgumentsRule, +} from './rules/ProvidedRequiredArguments'; + +// Spec Section: "Leaf Field Selections" +export { ScalarLeafs as ScalarLeafsRule } from './rules/ScalarLeafs'; + +// Spec Section: "Subscriptions with Single Root Field" +export { + SingleFieldSubscriptions as SingleFieldSubscriptionsRule, +} from './rules/SingleFieldSubscriptions'; + +// Spec Section: "Argument Uniqueness" +export { + UniqueArgumentNames as UniqueArgumentNamesRule, +} from './rules/UniqueArgumentNames'; + +// Spec Section: "Directives Are Unique Per Location" +export { + UniqueDirectivesPerLocation as UniqueDirectivesPerLocationRule, +} from './rules/UniqueDirectivesPerLocation'; + +// Spec Section: "Fragment Name Uniqueness" +export { + UniqueFragmentNames as UniqueFragmentNamesRule, +} from './rules/UniqueFragmentNames'; + +// Spec Section: "Input Object Field Uniqueness" +export { + UniqueInputFieldNames as UniqueInputFieldNamesRule, +} from './rules/UniqueInputFieldNames'; + +// Spec Section: "Operation Name Uniqueness" +export { + UniqueOperationNames as UniqueOperationNamesRule, +} from './rules/UniqueOperationNames'; + +// Spec Section: "Variable Uniqueness" +export { + UniqueVariableNames as UniqueVariableNamesRule, +} from './rules/UniqueVariableNames'; + +// Spec Section: "Values Type Correctness" +export { + ValuesOfCorrectType as ValuesOfCorrectTypeRule, +} from './rules/ValuesOfCorrectType'; + +// Spec Section: "Variables are Input Types" +export { + VariablesAreInputTypes as VariablesAreInputTypesRule, +} from './rules/VariablesAreInputTypes'; + +// Spec Section: "All Variable Usages Are Allowed" +export { + VariablesInAllowedPosition as VariablesInAllowedPositionRule, +} from './rules/VariablesInAllowedPosition'; diff --git a/tstypes/validation/rules/ExecutableDefinitions.d.ts b/tstypes/validation/rules/ExecutableDefinitions.d.ts new file mode 100644 index 00000000000..055bca6e63a --- /dev/null +++ b/tstypes/validation/rules/ExecutableDefinitions.d.ts @@ -0,0 +1,14 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function nonExecutableDefinitionMessage(defName: string): string; + +/** + * Executable definitions + * + * A GraphQL document is only valid for execution if all definitions are either + * operation or fragment definitions. + */ +export function ExecutableDefinitions( + context: ASTValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/FieldsOnCorrectType.d.ts b/tstypes/validation/rules/FieldsOnCorrectType.d.ts new file mode 100644 index 00000000000..38ba3ed846e --- /dev/null +++ b/tstypes/validation/rules/FieldsOnCorrectType.d.ts @@ -0,0 +1,10 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +/** + * Fields on correct type + * + * A GraphQL document is only valid if all fields selected are defined by the + * parent type, or are an allowed meta field such as __typename. + */ +export function FieldsOnCorrectType(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/FragmentsOnCompositeTypes.d.ts b/tstypes/validation/rules/FragmentsOnCompositeTypes.d.ts new file mode 100644 index 00000000000..f2da30fd00a --- /dev/null +++ b/tstypes/validation/rules/FragmentsOnCompositeTypes.d.ts @@ -0,0 +1,20 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function inlineFragmentOnNonCompositeErrorMessage(type: string): string; + +export function fragmentOnNonCompositeErrorMessage( + fragName: string, + type: string, +): string; + +/** + * Fragments on composite type + * + * Fragments use a type condition to determine if they apply, since fragments + * can only be spread into a composite type (object, interface, or union), the + * type condition must also be a composite type. + */ +export function FragmentsOnCompositeTypes( + context: ValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/KnownArgumentNames.d.ts b/tstypes/validation/rules/KnownArgumentNames.d.ts new file mode 100644 index 00000000000..208f919302a --- /dev/null +++ b/tstypes/validation/rules/KnownArgumentNames.d.ts @@ -0,0 +1,28 @@ +import { ValidationContext, SDLValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unknownArgMessage( + argName: string, + fieldName: string, + typeName: string, + suggestedArgs: Array, +): string; + +export function unknownDirectiveArgMessage( + argName: string, + directiveName: string, + suggestedArgs: Array, +): string; + +/** + * Known argument names + * + * A GraphQL field is only valid if all supplied arguments are defined by + * that field. + */ +export function KnownArgumentNames(context: ValidationContext): ASTVisitor; + +// @internal +export function KnownArgumentNamesOnDirectives( + context: ValidationContext | SDLValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/KnownDirectives.d.ts b/tstypes/validation/rules/KnownDirectives.d.ts new file mode 100644 index 00000000000..8585a80737a --- /dev/null +++ b/tstypes/validation/rules/KnownDirectives.d.ts @@ -0,0 +1,19 @@ +import { ValidationContext, SDLValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unknownDirectiveMessage(directiveName: string): string; + +export function misplacedDirectiveMessage( + directiveName: string, + location: string, +): string; + +/** + * Known directives + * + * A GraphQL document is only valid if all `@directives` are known by the + * schema and legally positioned. + */ +export function KnownDirectives( + context: ValidationContext | SDLValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/KnownFragmentNames.d.ts b/tstypes/validation/rules/KnownFragmentNames.d.ts new file mode 100644 index 00000000000..14168e23481 --- /dev/null +++ b/tstypes/validation/rules/KnownFragmentNames.d.ts @@ -0,0 +1,12 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unknownFragmentMessage(fragName: string): string; + +/** + * Known fragment names + * + * A GraphQL document is only valid if all `...Fragment` fragment spreads refer + * to fragments defined in the same document. + */ +export function KnownFragmentNames(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/KnownTypeNames.d.ts b/tstypes/validation/rules/KnownTypeNames.d.ts new file mode 100644 index 00000000000..d720269f9b0 --- /dev/null +++ b/tstypes/validation/rules/KnownTypeNames.d.ts @@ -0,0 +1,15 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unknownTypeMessage( + typeName: string, + suggestedTypes: Array, +): string; + +/** + * Known type names + * + * A GraphQL document is only valid if referenced types (specifically + * variable definitions and fragment conditions) are defined by the type schema. + */ +export function KnownTypeNames(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/LoneAnonymousOperation.d.ts b/tstypes/validation/rules/LoneAnonymousOperation.d.ts new file mode 100644 index 00000000000..345966ad7de --- /dev/null +++ b/tstypes/validation/rules/LoneAnonymousOperation.d.ts @@ -0,0 +1,14 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function anonOperationNotAloneMessage(): string; + +/** + * Lone anonymous operation + * + * A GraphQL document is only valid if when it contains an anonymous operation + * (the query short-hand) that it contains only that one operation definition. + */ +export function LoneAnonymousOperation( + context: ASTValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/LoneSchemaDefinition.d.ts b/tstypes/validation/rules/LoneSchemaDefinition.d.ts new file mode 100644 index 00000000000..c2084bb5eb5 --- /dev/null +++ b/tstypes/validation/rules/LoneSchemaDefinition.d.ts @@ -0,0 +1,13 @@ +import { SDLValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function schemaDefinitionNotAloneMessage(): string; + +export function canNotDefineSchemaWithinExtensionMessage(): string; + +/** + * Lone Schema definition + * + * A GraphQL document is only valid if it contains only one schema definition. + */ +export function LoneSchemaDefinition(context: SDLValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/NoFragmentCycles.d.ts b/tstypes/validation/rules/NoFragmentCycles.d.ts new file mode 100644 index 00000000000..98e90517220 --- /dev/null +++ b/tstypes/validation/rules/NoFragmentCycles.d.ts @@ -0,0 +1,9 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function cycleErrorMessage( + fragName: string, + spreadNames: Array, +): string; + +export function NoFragmentCycles(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/NoUndefinedVariables.d.ts b/tstypes/validation/rules/NoUndefinedVariables.d.ts new file mode 100644 index 00000000000..a8bd4d9d954 --- /dev/null +++ b/tstypes/validation/rules/NoUndefinedVariables.d.ts @@ -0,0 +1,16 @@ +import Maybe from '../../tsutils/Maybe'; +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function undefinedVarMessage( + varName: string, + opName: Maybe, +): string; + +/** + * No undefined variables + * + * A GraphQL operation is only valid if all variables encountered, both directly + * and via fragment spreads, are defined by that operation. + */ +export function NoUndefinedVariables(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/NoUnusedFragments.d.ts b/tstypes/validation/rules/NoUnusedFragments.d.ts new file mode 100644 index 00000000000..be44a0cb838 --- /dev/null +++ b/tstypes/validation/rules/NoUnusedFragments.d.ts @@ -0,0 +1,12 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unusedFragMessage(fragName: string): string; + +/** + * No unused fragments + * + * A GraphQL document is only valid if all fragment definitions are spread + * within operations, or spread within other fragments spread within operations. + */ +export function NoUnusedFragments(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/NoUnusedVariables.d.ts b/tstypes/validation/rules/NoUnusedVariables.d.ts new file mode 100644 index 00000000000..4d2c9be1c85 --- /dev/null +++ b/tstypes/validation/rules/NoUnusedVariables.d.ts @@ -0,0 +1,16 @@ +import Maybe from '../../tsutils/Maybe'; +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function unusedVariableMessage( + varName: string, + opName: Maybe, +): string; + +/** + * No unused variables + * + * A GraphQL operation is only valid if all variables defined by an operation + * are used, either directly or within a spread fragment. + */ +export function NoUnusedVariables(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/OverlappingFieldsCanBeMerged.d.ts b/tstypes/validation/rules/OverlappingFieldsCanBeMerged.d.ts new file mode 100644 index 00000000000..1288ed1da7a --- /dev/null +++ b/tstypes/validation/rules/OverlappingFieldsCanBeMerged.d.ts @@ -0,0 +1,24 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function fieldsConflictMessage( + responseName: string, + reason: ConflictReasonMessage, +): string; + +/** + * Overlapping fields can be merged + * + * A selection set is only valid if all fields (including spreading any + * fragments) either correspond to distinct response names or can be merged + * without ambiguity. + */ +export function OverlappingFieldsCanBeMerged( + context: ValidationContext, +): ASTVisitor; + +// Field name and reason. +type ConflictReason = [string, string]; + +// Reason is a string, or a nested list of conflicts. +type ConflictReasonMessage = string | Array; diff --git a/tstypes/validation/rules/PossibleFragmentSpreads.d.ts b/tstypes/validation/rules/PossibleFragmentSpreads.d.ts new file mode 100644 index 00000000000..1623fc41d8f --- /dev/null +++ b/tstypes/validation/rules/PossibleFragmentSpreads.d.ts @@ -0,0 +1,22 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function typeIncompatibleSpreadMessage( + fragName: string, + parentType: string, + fragType: string, +): string; + +export function typeIncompatibleAnonSpreadMessage( + parentType: string, + fragType: string, +): string; + +/** + * Possible fragment spread + * + * A fragment spread is only valid if the type condition could ever possibly + * be true: if there is a non-empty intersection of the possible parent types, + * and possible types which pass the type condition. + */ +export function PossibleFragmentSpreads(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/ProvidedRequiredArguments.d.ts b/tstypes/validation/rules/ProvidedRequiredArguments.d.ts new file mode 100644 index 00000000000..a7382f2af74 --- /dev/null +++ b/tstypes/validation/rules/ProvidedRequiredArguments.d.ts @@ -0,0 +1,29 @@ +import { ValidationContext, SDLValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function missingFieldArgMessage( + fieldName: string, + argName: string, + type: string, +): string; + +export function missingDirectiveArgMessage( + directiveName: string, + argName: string, + type: string, +): string; + +/** + * Provided required arguments + * + * A field or directive is only valid if all required (non-null without a + * default value) field arguments have been provided. + */ +export function ProvidedRequiredArguments( + context: ValidationContext, +): ASTVisitor; + +// @internal +export function ProvidedRequiredArgumentsOnDirectives( + context: ValidationContext | SDLValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/ScalarLeafs.d.ts b/tstypes/validation/rules/ScalarLeafs.d.ts new file mode 100644 index 00000000000..c16d923811b --- /dev/null +++ b/tstypes/validation/rules/ScalarLeafs.d.ts @@ -0,0 +1,20 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function noSubselectionAllowedMessage( + fieldName: string, + type: string, +): string; + +export function requiredSubselectionMessage( + fieldName: string, + type: string, +): string; + +/** + * Scalar leafs + * + * A GraphQL document is valid only if all leaf fields (fields without + * sub selections) are of scalar or enum types. + */ +export function ScalarLeafs(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/SingleFieldSubscriptions.d.ts b/tstypes/validation/rules/SingleFieldSubscriptions.d.ts new file mode 100644 index 00000000000..8e3d56c3b14 --- /dev/null +++ b/tstypes/validation/rules/SingleFieldSubscriptions.d.ts @@ -0,0 +1,14 @@ +import Maybe from '../../tsutils/Maybe'; +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function singleFieldOnlyMessage(name: Maybe): string; + +/** + * Subscriptions must only include one field. + * + * A GraphQL subscription is valid only if it contains a single root field. + */ +export function SingleFieldSubscriptions( + context: ASTValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueArgumentNames.d.ts b/tstypes/validation/rules/UniqueArgumentNames.d.ts new file mode 100644 index 00000000000..f0b4d4adc2f --- /dev/null +++ b/tstypes/validation/rules/UniqueArgumentNames.d.ts @@ -0,0 +1,12 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateArgMessage(argName: string): string; + +/** + * Unique argument names + * + * A GraphQL field or directive is only valid if all supplied arguments are + * uniquely named. + */ +export function UniqueArgumentNames(context: ASTValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueDirectivesPerLocation.d.ts b/tstypes/validation/rules/UniqueDirectivesPerLocation.d.ts new file mode 100644 index 00000000000..879eea7eeb4 --- /dev/null +++ b/tstypes/validation/rules/UniqueDirectivesPerLocation.d.ts @@ -0,0 +1,14 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateDirectiveMessage(directiveName: string): string; + +/** + * Unique directive names per location + * + * A GraphQL document is only valid if all directives at a given location + * are uniquely named. + */ +export function UniqueDirectivesPerLocation( + context: ASTValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueFragmentNames.d.ts b/tstypes/validation/rules/UniqueFragmentNames.d.ts new file mode 100644 index 00000000000..e849d9fe325 --- /dev/null +++ b/tstypes/validation/rules/UniqueFragmentNames.d.ts @@ -0,0 +1,11 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateFragmentNameMessage(fragName: string): string; + +/** + * Unique fragment names + * + * A GraphQL document is only valid if all defined fragments have unique names. + */ +export function UniqueFragmentNames(context: ASTValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueInputFieldNames.d.ts b/tstypes/validation/rules/UniqueInputFieldNames.d.ts new file mode 100644 index 00000000000..d2682fec0b5 --- /dev/null +++ b/tstypes/validation/rules/UniqueInputFieldNames.d.ts @@ -0,0 +1,14 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateInputFieldMessage(fieldName: string): string; + +/** + * Unique input field names + * + * A GraphQL input object value is only valid if all supplied fields are + * uniquely named. + */ +export function UniqueInputFieldNames( + context: ASTValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueOperationNames.d.ts b/tstypes/validation/rules/UniqueOperationNames.d.ts new file mode 100644 index 00000000000..bd31be1ee2f --- /dev/null +++ b/tstypes/validation/rules/UniqueOperationNames.d.ts @@ -0,0 +1,11 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateOperationNameMessage(operationName: string): string; + +/** + * Unique operation names + * + * A GraphQL document is only valid if all defined operations have unique names. + */ +export function UniqueOperationNames(context: ASTValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/UniqueVariableNames.d.ts b/tstypes/validation/rules/UniqueVariableNames.d.ts new file mode 100644 index 00000000000..ac81c95f9ef --- /dev/null +++ b/tstypes/validation/rules/UniqueVariableNames.d.ts @@ -0,0 +1,11 @@ +import { ASTValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function duplicateVariableMessage(variableName: string): string; + +/** + * Unique variable names + * + * A GraphQL operation is only valid if all its variables are uniquely named. + */ +export function UniqueVariableNames(context: ASTValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/ValuesOfCorrectType.d.ts b/tstypes/validation/rules/ValuesOfCorrectType.d.ts new file mode 100644 index 00000000000..3ef5d6d4ed4 --- /dev/null +++ b/tstypes/validation/rules/ValuesOfCorrectType.d.ts @@ -0,0 +1,28 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function badValueMessage( + typeName: string, + valueName: string, + message?: string, +): string; + +export function requiredFieldMessage( + typeName: string, + fieldName: string, + fieldTypeName: string, +): string; + +export function unknownFieldMessage( + typeName: string, + fieldName: string, + message?: string, +): string; + +/** + * Value literals of correct type + * + * A GraphQL document is only valid if all value literals are of the type + * expected at their position. + */ +export function ValuesOfCorrectType(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/VariablesAreInputTypes.d.ts b/tstypes/validation/rules/VariablesAreInputTypes.d.ts new file mode 100644 index 00000000000..f5103aea209 --- /dev/null +++ b/tstypes/validation/rules/VariablesAreInputTypes.d.ts @@ -0,0 +1,15 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function nonInputTypeOnVarMessage( + variableName: string, + typeName: string, +): string; + +/** + * Variables are input types + * + * A GraphQL operation is only valid if all the variables it defines are of + * input types (scalar, enum, or input object). + */ +export function VariablesAreInputTypes(context: ValidationContext): ASTVisitor; diff --git a/tstypes/validation/rules/VariablesInAllowedPosition.d.ts b/tstypes/validation/rules/VariablesInAllowedPosition.d.ts new file mode 100644 index 00000000000..84a5dade51e --- /dev/null +++ b/tstypes/validation/rules/VariablesInAllowedPosition.d.ts @@ -0,0 +1,15 @@ +import { ValidationContext } from '../ValidationContext'; +import { ASTVisitor } from '../../language/visitor'; + +export function badVarPosMessage( + varName: string, + varType: string, + expectedType: string, +): string; + +/** + * Variables passed to field arguments conform to type + */ +export function VariablesInAllowedPosition( + context: ValidationContext, +): ASTVisitor; diff --git a/tstypes/validation/specifiedRules.d.ts b/tstypes/validation/specifiedRules.d.ts new file mode 100644 index 00000000000..98e9e5eb2ba --- /dev/null +++ b/tstypes/validation/specifiedRules.d.ts @@ -0,0 +1,92 @@ +import { ValidationRule, SDLValidationRule } from './ValidationContext'; + +// Spec Section: "Executable Definitions" +import { ExecutableDefinitions } from './rules/ExecutableDefinitions'; + +// Spec Section: "Operation Name Uniqueness" +import { UniqueOperationNames } from './rules/UniqueOperationNames'; + +// Spec Section: "Lone Anonymous Operation" +import { LoneAnonymousOperation } from './rules/LoneAnonymousOperation'; + +// Spec Section: "Subscriptions with Single Root Field" +import { SingleFieldSubscriptions } from './rules/SingleFieldSubscriptions'; + +// Spec Section: "Fragment Spread Type Existence" +import { KnownTypeNames } from './rules/KnownTypeNames'; + +// Spec Section: "Fragments on Composite Types" +import { FragmentsOnCompositeTypes } from './rules/FragmentsOnCompositeTypes'; + +// Spec Section: "Variables are Input Types" +import { VariablesAreInputTypes } from './rules/VariablesAreInputTypes'; + +// Spec Section: "Leaf Field Selections" +import { ScalarLeafs } from './rules/ScalarLeafs'; + +// Spec Section: "Field Selections on Objects, Interfaces, and Unions Types" +import { FieldsOnCorrectType } from './rules/FieldsOnCorrectType'; + +// Spec Section: "Fragment Name Uniqueness" +import { UniqueFragmentNames } from './rules/UniqueFragmentNames'; + +// Spec Section: "Fragment spread target defined" +import { KnownFragmentNames } from './rules/KnownFragmentNames'; + +// Spec Section: "Fragments must be used" +import { NoUnusedFragments } from './rules/NoUnusedFragments'; + +// Spec Section: "Fragment spread is possible" +import { PossibleFragmentSpreads } from './rules/PossibleFragmentSpreads'; + +// Spec Section: "Fragments must not form cycles" +import { NoFragmentCycles } from './rules/NoFragmentCycles'; + +// Spec Section: "Variable Uniqueness" +import { UniqueVariableNames } from './rules/UniqueVariableNames'; + +// Spec Section: "All Variable Used Defined" +import { NoUndefinedVariables } from './rules/NoUndefinedVariables'; + +// Spec Section: "All Variables Used" +import { NoUnusedVariables } from './rules/NoUnusedVariables'; + +// Spec Section: "Directives Are Defined" +import { KnownDirectives } from './rules/KnownDirectives'; + +// Spec Section: "Directives Are Unique Per Location" +import { UniqueDirectivesPerLocation } from './rules/UniqueDirectivesPerLocation'; + +// Spec Section: "Argument Names" +import { KnownArgumentNames } from './rules/KnownArgumentNames'; + +// Spec Section: "Argument Uniqueness" +import { UniqueArgumentNames } from './rules/UniqueArgumentNames'; + +// Spec Section: "Value Type Correctness" +import { ValuesOfCorrectType } from './rules/ValuesOfCorrectType'; + +// Spec Section: "Argument Optionality" +import { ProvidedRequiredArguments } from './rules/ProvidedRequiredArguments'; + +// Spec Section: "All Variable Usages Are Allowed" +import { VariablesInAllowedPosition } from './rules/VariablesInAllowedPosition'; + +// Spec Section: "Field Selection Merging" +import { OverlappingFieldsCanBeMerged } from './rules/OverlappingFieldsCanBeMerged'; + +// Spec Section: "Input Object Field Uniqueness" +import { UniqueInputFieldNames } from './rules/UniqueInputFieldNames'; + +/** + * This set includes all validation rules defined by the GraphQL spec. + * + * The order of the rules in this list has been adjusted to lead to the + * most clear output when encountering multiple validation errors. + */ +export const specifiedRules: ReadonlyArray; + +import { LoneSchemaDefinition } from './rules/LoneSchemaDefinition'; + +// @internal +export const specifiedSDLRules: ReadonlyArray; diff --git a/tstypes/validation/validate.d.ts b/tstypes/validation/validate.d.ts new file mode 100644 index 00000000000..9fe20452a9a --- /dev/null +++ b/tstypes/validation/validate.d.ts @@ -0,0 +1,54 @@ +import { GraphQLError } from '../error'; +import { DocumentNode } from '../language/ast'; +import { GraphQLSchema } from '../type/schema'; +import { TypeInfo } from '../utilities/TypeInfo'; +import { ValidationRule, SDLValidationRule } from './ValidationContext'; + +/** + * Implements the "Validation" section of the spec. + * + * Validation runs synchronously, returning an array of encountered errors, or + * an empty array if no errors were encountered and the document is valid. + * + * A list of specific validation rules may be provided. If not provided, the + * default list of rules defined by the GraphQL specification will be used. + * + * Each validation rules is a function which returns a visitor + * (see the language/visitor API). Visitor methods are expected to return + * GraphQLErrors, or Arrays of GraphQLErrors when invalid. + * + * Optionally a custom TypeInfo instance may be provided. If not provided, one + * will be created from the provided schema. + */ +export function validate( + schema: GraphQLSchema, + documentAST: DocumentNode, + rules?: ReadonlyArray, + typeInfo?: TypeInfo, +): ReadonlyArray; + +// @internal +export function validateSDL( + documentAST: DocumentNode, + schemaToExtend?: GraphQLSchema | null, + rules?: ReadonlyArray, +): GraphQLError[]; + +/** + * Utility function which asserts a SDL document is valid by throwing an error + * if it is invalid. + * + * @internal + */ +export function assertValidSDL(documentAST: DocumentNode): undefined; + +/** + * Utility function which asserts a SDL document is valid by throwing an error + * if it is invalid. + * + * @internal + */ +export function assertValidSDLExtension( + documentAST: DocumentNode, + schema: GraphQLSchema, +): undefined;