diff --git a/.c8rc.json b/.c8rc.json index 3a1c03886f..07134f4f24 100644 --- a/.c8rc.json +++ b/.c8rc.json @@ -7,6 +7,7 @@ "src/jsutils/Maybe.ts", "src/jsutils/ObjMap.ts", "src/jsutils/PromiseOrValue.ts", + "src/language/KindTypeMap.ts", "src/utilities/typedQueryDocumentNode.ts", "src/**/__tests__/**/*.ts" ], diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64c2a0a6cd..07a2c21d48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: run: npm run lint - name: Check Types - run: npm run check + run: npm run check:ts - name: Lint Prettier run: npm run prettier:check @@ -244,7 +244,7 @@ jobs: name: denoDist path: ./denoDist - type-check-deno-dist: + check-deno-dist: name: Type check denoDist on Deno v${{ matrix.deno_version_to_setup }} needs: build-deno-dist runs-on: ubuntu-latest @@ -268,5 +268,12 @@ jobs: with: deno-version: ${{ matrix.deno_version_to_setup }} - - name: Check denoDist package - run: deno check ./denoDist/index.ts + - name: Run denoDist package publish dry-run checks + # `deno publish --dry-run` performs a number of checks including: + # (a) type-checking package modules/public API, + # (b) validating exports and module-graph resolution, + # (c) validating the publish file set (gitignore + publish.exclude/include), + # (d) validating package metadata/config, and + # (e) enforcing JSR slow-types checks. + working-directory: ./denoDist + run: deno publish --dry-run diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 057de53c3e..5b16e388e4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -134,14 +134,9 @@ jobs: runs-on: ubuntu-latest environment: release permissions: - contents: read # for actions/checkout + contents: read # for actions/download-artifact id-token: write # for JSR trusted publishing via OIDC steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - persist-credentials: false - - name: Download denoDist package uses: actions/download-artifact@v4 with: diff --git a/package.json b/package.json index b554ad6a63..0c868305ec 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,9 @@ "benchmark": "node --import ./resources/register-ts-node.js resources/benchmark.ts", "test": "npm run lint && npm run check && npm run testonly:cover && npm run prettier:check && npm run check:spelling && npm run check:integrations", "lint": "eslint --cache --max-warnings 0 .", - "check": "tsc --pretty", + "check": "npm run check:ts && npm run check:deno", + "check:ts": "tsc --pretty", + "check:deno": "npm run build:deno && deno publish --dry-run --allow-dirty --config denoDist/jsr.json", "testonly": "mocha --full-trace src/**/__tests__/**/*-test.ts", "testonly:cover": "c8 npm run testonly", "testonly:watch": "npm run testonly -- --watch", diff --git a/resources/build-deno.ts b/resources/build-deno.ts index b7179bf7ca..4d73f24b6b 100644 --- a/resources/build-deno.ts +++ b/resources/build-deno.ts @@ -90,6 +90,9 @@ interface JSRConfig { name: string; version: string; exports: { [entrypoint: string]: string }; + publish: { + exclude: ReadonlyArray; + }; } async function writeJSRConfig( @@ -122,6 +125,10 @@ async function writeJSRConfig( name: '@graphql/graphql-js', version, exports: jsrExports, + publish: { + // The package root is `denoDist/`, so unignore relative to that root. + exclude: ['!.'], + }, }; const prettified = await prettify(jsrConfigPath, JSON.stringify(jsrConfig)); diff --git a/resources/change-extension-in-import-paths.ts b/resources/change-extension-in-import-paths.ts index 9394411489..351d9d50a4 100644 --- a/resources/change-extension-in-import-paths.ts +++ b/resources/change-extension-in-import-paths.ts @@ -21,14 +21,16 @@ import ts from 'typescript'; * ``` * */ -export function changeExtensionInImportPaths(config: { extension: string }) { +export function changeExtensionInImportPaths(config: { + extension: string; +}): ts.TransformerFactory { const { extension } = config; - return (context: ts.TransformationContext) => { + return (context: ts.TransformationContext): ts.Transformer => { const { factory } = context; return visitSourceFile; - function visitSourceFile(sourceFile: ts.SourceFile) { + function visitSourceFile(sourceFile: ts.SourceFile): ts.SourceFile { return ts.visitNode(sourceFile, visitNode, ts.isSourceFile); } diff --git a/resources/gen-version.ts b/resources/gen-version.ts index b4b75ea92c..e7e4e783b2 100644 --- a/resources/gen-version.ts +++ b/resources/gen-version.ts @@ -20,7 +20,12 @@ export const version = '${version}' as string; /** * An object containing the components of the GraphQL.js version string */ -export const versionInfo = Object.freeze({ +export const versionInfo: Readonly<{ + major: number; + minor: number; + patch: number; + preReleaseTag: string | null; +}> = Object.freeze({ major: ${major} as number, minor: ${minor} as number, patch: ${patch} as number, diff --git a/resources/inline-invariant.ts b/resources/inline-invariant.ts index 9b73f1a3eb..5d89b20668 100644 --- a/resources/inline-invariant.ts +++ b/resources/inline-invariant.ts @@ -11,12 +11,14 @@ import ts from 'typescript'; * * if (!()) invariant(false, ...) */ -export function inlineInvariant(context: ts.TransformationContext) { +export function inlineInvariant( + context: ts.TransformationContext, +): ts.Transformer { const { factory } = context; return visitSourceFile; - function visitSourceFile(sourceFile: ts.SourceFile) { + function visitSourceFile(sourceFile: ts.SourceFile): ts.SourceFile { return ts.visitNode(sourceFile, visitNode, ts.isSourceFile); } diff --git a/src/__testUtils__/expectJSON.ts b/src/__testUtils__/expectJSON.ts index 6de15ccacf..1820561ca0 100644 --- a/src/__testUtils__/expectJSON.ts +++ b/src/__testUtils__/expectJSON.ts @@ -23,22 +23,33 @@ function toJSONDeep(value: unknown): unknown { return mapValue(value, toJSONDeep); } -export function expectJSON(actual: unknown) { +export function expectJSON(actual: unknown): { + toDeepEqual: (expected: unknown) => ReturnType; + toDeepNestedProperty: ( + path: string, + expected: unknown, + ) => ReturnType; +} { const actualJSON = toJSONDeep(actual); return { - toDeepEqual(expected: unknown) { + toDeepEqual(expected: unknown): ReturnType { const expectedJSON = toJSONDeep(expected); - expect(actualJSON).to.deep.equal(expectedJSON); + return expect(actualJSON).to.deep.equal(expectedJSON); }, - toDeepNestedProperty(path: string, expected: unknown) { + toDeepNestedProperty( + path: string, + expected: unknown, + ): ReturnType { const expectedJSON = toJSONDeep(expected); - expect(actualJSON).to.deep.nested.property(path, expectedJSON); + return expect(actualJSON).to.deep.nested.property(path, expectedJSON); }, }; } -export function expectToThrowJSON(fn: () => unknown) { +export function expectToThrowJSON( + fn: () => unknown, +): ReturnType { function mapException(): unknown { try { return fn(); diff --git a/src/__testUtils__/expectPromise.ts b/src/__testUtils__/expectPromise.ts index 7c18f4a39b..8371af723c 100644 --- a/src/__testUtils__/expectPromise.ts +++ b/src/__testUtils__/expectPromise.ts @@ -3,17 +3,22 @@ import { assert, expect } from 'chai'; import { inspect } from '../jsutils/inspect.js'; import { isPromise } from '../jsutils/isPromise.js'; -export function expectPromise(maybePromise: unknown) { +interface PromiseExpectation { + toResolve: () => Promise; + toRejectWith: (message: string) => Promise; +} + +export function expectPromise(maybePromise: unknown): PromiseExpectation { assert( isPromise(maybePromise), `Expected a promise, received '${inspect(maybePromise)}'`, ); return { - toResolve() { + toResolve(): Promise { return maybePromise; }, - async toRejectWith(message: string) { + async toRejectWith(message: string): Promise { let caughtError: unknown; let resolved; let rejected = false; diff --git a/src/__testUtils__/viralSchema.ts b/src/__testUtils__/viralSchema.ts index 62613dc710..463d988b95 100644 --- a/src/__testUtils__/viralSchema.ts +++ b/src/__testUtils__/viralSchema.ts @@ -39,6 +39,6 @@ const Query = new GraphQLObjectType({ }, }); -export const viralSchema = new GraphQLSchema({ +export const viralSchema: GraphQLSchema = new GraphQLSchema({ query: Query, }); diff --git a/src/execution/Executor.ts b/src/execution/Executor.ts index 546662e0e7..be8feebd36 100644 --- a/src/execution/Executor.ts +++ b/src/execution/Executor.ts @@ -119,7 +119,11 @@ export interface ValidatedExecutionArgs { * type. Memoizing ensures the subfields are not repeatedly calculated, which * saves overhead when resolving lists of values. */ -export const collectSubfields = memoize3( +export const collectSubfields: ( + validatedExecutionArgs: ValidatedExecutionArgs, + returnType: GraphQLObjectType, + fieldDetailsList: FieldDetailsList, +) => ReturnType = memoize3( ( validatedExecutionArgs: ValidatedExecutionArgs, returnType: GraphQLObjectType, @@ -138,7 +142,7 @@ export const collectSubfields = memoize3( }, ); -export const getStreamUsage = memoize2( +export const getStreamUsage: typeof _getStreamUsage = memoize2( ( validatedExecutionArgs: ValidatedExecutionArgs, fieldDetailsList: FieldDetailsList, @@ -160,7 +164,7 @@ class CollectedErrors { return this._errors; } - add(error: GraphQLError, path: Path | undefined) { + add(error: GraphQLError, path: Path | undefined): void { // Do not modify errors list if the execution position for this error or // any of its ancestors has already been nulled via error propagation. // This check should be unnecessary for implementations able to implement diff --git a/src/index.ts b/src/index.ts index af9373a739..3baacf2a79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -230,8 +230,11 @@ export type { // Parse and operate on GraphQL language source files. // @see https://github.com/typescript-eslint/typescript-eslint/issues/10313 - +// Deno misclassifies this merged value+type re-export and requires `export type`. +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore TS1205 export { Kind } from './language/kinds.js'; + export { Token, Source, diff --git a/src/jsutils/AccumulatorMap.ts b/src/jsutils/AccumulatorMap.ts index 198f22bc7f..3687926620 100644 --- a/src/jsutils/AccumulatorMap.ts +++ b/src/jsutils/AccumulatorMap.ts @@ -3,7 +3,7 @@ */ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters export class AccumulatorMap extends Map> { - override get [Symbol.toStringTag]() { + override get [Symbol.toStringTag](): string { return 'AccumulatorMap'; } diff --git a/src/language/KindTypeMap.ts b/src/language/KindTypeMap.ts new file mode 100644 index 0000000000..8260b7779e --- /dev/null +++ b/src/language/KindTypeMap.ts @@ -0,0 +1,7 @@ +/* eslint-disable import/no-namespace */ +import type * as Kind_ from './kinds_.js'; + +// Keep the kind literal map available as a type-only import for `ast.ts`. +// This avoids depending on the `Kind` runtime namespace in type positions, +// which Deno's publish type-output validation rejects for this package shape. +export type KindTypeMap = typeof Kind_; diff --git a/src/language/ast.ts b/src/language/ast.ts index 9997950ee8..c2a0c3d718 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -1,4 +1,4 @@ -import type { Kind } from './kinds.js'; +import type { KindTypeMap } from './KindTypeMap.js'; import type { Source } from './source.js'; import type { TokenKind } from './tokenKind.js'; @@ -40,7 +40,7 @@ export class Location { this.source = source; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'Location'; } @@ -115,7 +115,7 @@ export class Token { this.next = null; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'Token'; } @@ -320,7 +320,7 @@ export function isNode(maybeNode: any): maybeNode is ASTNode { /** Name */ export interface NameNode { - readonly kind: typeof Kind.NAME; + readonly kind: KindTypeMap['NAME']; readonly loc?: Location | undefined; readonly value: string; } @@ -328,7 +328,7 @@ export interface NameNode { /** Document */ export interface DocumentNode { - readonly kind: typeof Kind.DOCUMENT; + readonly kind: KindTypeMap['DOCUMENT']; readonly loc?: Location | undefined; readonly definitions: ReadonlyArray; readonly tokenCount?: number | undefined; @@ -344,7 +344,7 @@ export type ExecutableDefinitionNode = | FragmentDefinitionNode; export interface OperationDefinitionNode { - readonly kind: typeof Kind.OPERATION_DEFINITION; + readonly kind: KindTypeMap['OPERATION_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly operation: OperationTypeNode; @@ -366,7 +366,7 @@ export type OperationTypeNode = (typeof OperationTypeNode)[keyof typeof OperationTypeNode]; export interface VariableDefinitionNode { - readonly kind: typeof Kind.VARIABLE_DEFINITION; + readonly kind: KindTypeMap['VARIABLE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly variable: VariableNode; @@ -376,13 +376,13 @@ export interface VariableDefinitionNode { } export interface VariableNode { - readonly kind: typeof Kind.VARIABLE; + readonly kind: KindTypeMap['VARIABLE']; readonly loc?: Location | undefined; readonly name: NameNode; } export interface SelectionSetNode { - kind: typeof Kind.SELECTION_SET; + kind: KindTypeMap['SELECTION_SET']; loc?: Location | undefined; selections: ReadonlyArray; } @@ -390,7 +390,7 @@ export interface SelectionSetNode { export type SelectionNode = FieldNode | FragmentSpreadNode | InlineFragmentNode; export interface FieldNode { - readonly kind: typeof Kind.FIELD; + readonly kind: KindTypeMap['FIELD']; readonly loc?: Location | undefined; readonly alias?: NameNode | undefined; readonly name: NameNode; @@ -400,21 +400,21 @@ export interface FieldNode { } export interface ArgumentNode { - readonly kind: typeof Kind.ARGUMENT; + readonly kind: KindTypeMap['ARGUMENT']; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ValueNode; } export interface ConstArgumentNode { - readonly kind: typeof Kind.ARGUMENT; + readonly kind: KindTypeMap['ARGUMENT']; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ConstValueNode; } export interface FragmentArgumentNode { - readonly kind: typeof Kind.FRAGMENT_ARGUMENT; + readonly kind: KindTypeMap['FRAGMENT_ARGUMENT']; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ValueNode; @@ -423,7 +423,7 @@ export interface FragmentArgumentNode { /** Fragments */ export interface FragmentSpreadNode { - readonly kind: typeof Kind.FRAGMENT_SPREAD; + readonly kind: KindTypeMap['FRAGMENT_SPREAD']; readonly loc?: Location | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; @@ -431,7 +431,7 @@ export interface FragmentSpreadNode { } export interface InlineFragmentNode { - readonly kind: typeof Kind.INLINE_FRAGMENT; + readonly kind: KindTypeMap['INLINE_FRAGMENT']; readonly loc?: Location | undefined; readonly typeCondition?: NamedTypeNode | undefined; readonly directives?: ReadonlyArray | undefined; @@ -439,7 +439,7 @@ export interface InlineFragmentNode { } export interface FragmentDefinitionNode { - readonly kind: typeof Kind.FRAGMENT_DEFINITION; + readonly kind: KindTypeMap['FRAGMENT_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -475,74 +475,74 @@ export type ConstValueNode = | ConstObjectValueNode; export interface IntValueNode { - readonly kind: typeof Kind.INT; + readonly kind: KindTypeMap['INT']; readonly loc?: Location | undefined; readonly value: string; } export interface FloatValueNode { - readonly kind: typeof Kind.FLOAT; + readonly kind: KindTypeMap['FLOAT']; readonly loc?: Location | undefined; readonly value: string; } export interface StringValueNode { - readonly kind: typeof Kind.STRING; + readonly kind: KindTypeMap['STRING']; readonly loc?: Location | undefined; readonly value: string; readonly block?: boolean | undefined; } export interface BooleanValueNode { - readonly kind: typeof Kind.BOOLEAN; + readonly kind: KindTypeMap['BOOLEAN']; readonly loc?: Location | undefined; readonly value: boolean; } export interface NullValueNode { - readonly kind: typeof Kind.NULL; + readonly kind: KindTypeMap['NULL']; readonly loc?: Location | undefined; } export interface EnumValueNode { - readonly kind: typeof Kind.ENUM; + readonly kind: KindTypeMap['ENUM']; readonly loc?: Location | undefined; readonly value: string; } export interface ListValueNode { - readonly kind: typeof Kind.LIST; + readonly kind: KindTypeMap['LIST']; readonly loc?: Location | undefined; readonly values: ReadonlyArray; } export interface ConstListValueNode { - readonly kind: typeof Kind.LIST; + readonly kind: KindTypeMap['LIST']; readonly loc?: Location | undefined; readonly values: ReadonlyArray; } export interface ObjectValueNode { - readonly kind: typeof Kind.OBJECT; + readonly kind: KindTypeMap['OBJECT']; readonly loc?: Location | undefined; readonly fields: ReadonlyArray; } export interface ConstObjectValueNode { - readonly kind: typeof Kind.OBJECT; + readonly kind: KindTypeMap['OBJECT']; readonly loc?: Location | undefined; readonly fields: ReadonlyArray; } export interface ObjectFieldNode { - readonly kind: typeof Kind.OBJECT_FIELD; + readonly kind: KindTypeMap['OBJECT_FIELD']; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ValueNode; } export interface ConstObjectFieldNode { - readonly kind: typeof Kind.OBJECT_FIELD; + readonly kind: KindTypeMap['OBJECT_FIELD']; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ConstValueNode; @@ -551,14 +551,14 @@ export interface ConstObjectFieldNode { /** Directives */ export interface DirectiveNode { - readonly kind: typeof Kind.DIRECTIVE; + readonly kind: KindTypeMap['DIRECTIVE']; readonly loc?: Location | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; } export interface ConstDirectiveNode { - readonly kind: typeof Kind.DIRECTIVE; + readonly kind: KindTypeMap['DIRECTIVE']; readonly loc?: Location | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; @@ -569,19 +569,19 @@ export interface ConstDirectiveNode { export type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode; export interface NamedTypeNode { - readonly kind: typeof Kind.NAMED_TYPE; + readonly kind: KindTypeMap['NAMED_TYPE']; readonly loc?: Location | undefined; readonly name: NameNode; } export interface ListTypeNode { - readonly kind: typeof Kind.LIST_TYPE; + readonly kind: KindTypeMap['LIST_TYPE']; readonly loc?: Location | undefined; readonly type: TypeNode; } export interface NonNullTypeNode { - readonly kind: typeof Kind.NON_NULL_TYPE; + readonly kind: KindTypeMap['NON_NULL_TYPE']; readonly loc?: Location | undefined; readonly type: NamedTypeNode | ListTypeNode; } @@ -594,7 +594,7 @@ export type TypeSystemDefinitionNode = | DirectiveDefinitionNode; export interface SchemaDefinitionNode { - readonly kind: typeof Kind.SCHEMA_DEFINITION; + readonly kind: KindTypeMap['SCHEMA_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly directives?: ReadonlyArray | undefined; @@ -602,7 +602,7 @@ export interface SchemaDefinitionNode { } export interface OperationTypeDefinitionNode { - readonly kind: typeof Kind.OPERATION_TYPE_DEFINITION; + readonly kind: KindTypeMap['OPERATION_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly operation: OperationTypeNode; readonly type: NamedTypeNode; @@ -619,7 +619,7 @@ export type TypeDefinitionNode = | InputObjectTypeDefinitionNode; export interface ScalarTypeDefinitionNode { - readonly kind: typeof Kind.SCALAR_TYPE_DEFINITION; + readonly kind: KindTypeMap['SCALAR_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -627,7 +627,7 @@ export interface ScalarTypeDefinitionNode { } export interface ObjectTypeDefinitionNode { - readonly kind: typeof Kind.OBJECT_TYPE_DEFINITION; + readonly kind: KindTypeMap['OBJECT_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -637,7 +637,7 @@ export interface ObjectTypeDefinitionNode { } export interface FieldDefinitionNode { - readonly kind: typeof Kind.FIELD_DEFINITION; + readonly kind: KindTypeMap['FIELD_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -647,7 +647,7 @@ export interface FieldDefinitionNode { } export interface InputValueDefinitionNode { - readonly kind: typeof Kind.INPUT_VALUE_DEFINITION; + readonly kind: KindTypeMap['INPUT_VALUE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -657,7 +657,7 @@ export interface InputValueDefinitionNode { } export interface InterfaceTypeDefinitionNode { - readonly kind: typeof Kind.INTERFACE_TYPE_DEFINITION; + readonly kind: KindTypeMap['INTERFACE_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -667,7 +667,7 @@ export interface InterfaceTypeDefinitionNode { } export interface UnionTypeDefinitionNode { - readonly kind: typeof Kind.UNION_TYPE_DEFINITION; + readonly kind: KindTypeMap['UNION_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -676,7 +676,7 @@ export interface UnionTypeDefinitionNode { } export interface EnumTypeDefinitionNode { - readonly kind: typeof Kind.ENUM_TYPE_DEFINITION; + readonly kind: KindTypeMap['ENUM_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -685,7 +685,7 @@ export interface EnumTypeDefinitionNode { } export interface EnumValueDefinitionNode { - readonly kind: typeof Kind.ENUM_VALUE_DEFINITION; + readonly kind: KindTypeMap['ENUM_VALUE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -693,7 +693,7 @@ export interface EnumValueDefinitionNode { } export interface InputObjectTypeDefinitionNode { - readonly kind: typeof Kind.INPUT_OBJECT_TYPE_DEFINITION; + readonly kind: KindTypeMap['INPUT_OBJECT_TYPE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -704,7 +704,7 @@ export interface InputObjectTypeDefinitionNode { /** Directive Definitions */ export interface DirectiveDefinitionNode { - readonly kind: typeof Kind.DIRECTIVE_DEFINITION; + readonly kind: KindTypeMap['DIRECTIVE_DEFINITION']; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -718,7 +718,7 @@ export interface DirectiveDefinitionNode { export type TypeSystemExtensionNode = SchemaExtensionNode | TypeExtensionNode; export interface SchemaExtensionNode { - readonly kind: typeof Kind.SCHEMA_EXTENSION; + readonly kind: KindTypeMap['SCHEMA_EXTENSION']; readonly loc?: Location | undefined; readonly directives?: ReadonlyArray | undefined; readonly operationTypes?: @@ -737,14 +737,14 @@ export type TypeExtensionNode = | InputObjectTypeExtensionNode; export interface ScalarTypeExtensionNode { - readonly kind: typeof Kind.SCALAR_TYPE_EXTENSION; + readonly kind: KindTypeMap['SCALAR_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; } export interface ObjectTypeExtensionNode { - readonly kind: typeof Kind.OBJECT_TYPE_EXTENSION; + readonly kind: KindTypeMap['OBJECT_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly interfaces?: ReadonlyArray | undefined; @@ -753,7 +753,7 @@ export interface ObjectTypeExtensionNode { } export interface InterfaceTypeExtensionNode { - readonly kind: typeof Kind.INTERFACE_TYPE_EXTENSION; + readonly kind: KindTypeMap['INTERFACE_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly interfaces?: ReadonlyArray | undefined; @@ -762,7 +762,7 @@ export interface InterfaceTypeExtensionNode { } export interface UnionTypeExtensionNode { - readonly kind: typeof Kind.UNION_TYPE_EXTENSION; + readonly kind: KindTypeMap['UNION_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; @@ -770,7 +770,7 @@ export interface UnionTypeExtensionNode { } export interface EnumTypeExtensionNode { - readonly kind: typeof Kind.ENUM_TYPE_EXTENSION; + readonly kind: KindTypeMap['ENUM_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; @@ -778,7 +778,7 @@ export interface EnumTypeExtensionNode { } export interface InputObjectTypeExtensionNode { - readonly kind: typeof Kind.INPUT_OBJECT_TYPE_EXTENSION; + readonly kind: KindTypeMap['INPUT_OBJECT_TYPE_EXTENSION']; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; @@ -795,20 +795,20 @@ export type SchemaCoordinateNode = | DirectiveArgumentCoordinateNode; export interface TypeCoordinateNode { - readonly kind: typeof Kind.TYPE_COORDINATE; + readonly kind: KindTypeMap['TYPE_COORDINATE']; readonly loc?: Location; readonly name: NameNode; } export interface MemberCoordinateNode { - readonly kind: typeof Kind.MEMBER_COORDINATE; + readonly kind: KindTypeMap['MEMBER_COORDINATE']; readonly loc?: Location; readonly name: NameNode; readonly memberName: NameNode; } export interface ArgumentCoordinateNode { - readonly kind: typeof Kind.ARGUMENT_COORDINATE; + readonly kind: KindTypeMap['ARGUMENT_COORDINATE']; readonly loc?: Location; readonly name: NameNode; readonly fieldName: NameNode; @@ -816,13 +816,13 @@ export interface ArgumentCoordinateNode { } export interface DirectiveCoordinateNode { - readonly kind: typeof Kind.DIRECTIVE_COORDINATE; + readonly kind: KindTypeMap['DIRECTIVE_COORDINATE']; readonly loc?: Location; readonly name: NameNode; } export interface DirectiveArgumentCoordinateNode { - readonly kind: typeof Kind.DIRECTIVE_ARGUMENT_COORDINATE; + readonly kind: KindTypeMap['DIRECTIVE_ARGUMENT_COORDINATE']; readonly loc?: Location; readonly name: NameNode; readonly argumentName: NameNode; diff --git a/src/language/index.ts b/src/language/index.ts index a36bf938ff..ccc9ea92c4 100644 --- a/src/language/index.ts +++ b/src/language/index.ts @@ -6,7 +6,9 @@ export type { SourceLocation } from './location.js'; export { printLocation, printSourceLocation } from './printLocation.js'; // @see https://github.com/typescript-eslint/typescript-eslint/issues/10313 - +// Deno misclassifies this merged value+type re-export and requires `export type`. +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore TS1205 export { Kind } from './kinds.js'; export { TokenKind } from './tokenKind.js'; diff --git a/src/language/lexer.ts b/src/language/lexer.ts index e614be1aa3..4da1ba6b2a 100644 --- a/src/language/lexer.ts +++ b/src/language/lexer.ts @@ -63,7 +63,7 @@ export class Lexer implements LexerInterface { this.lineStart = 0; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'Lexer'; } diff --git a/src/language/schemaCoordinateLexer.ts b/src/language/schemaCoordinateLexer.ts index 6daf0238ad..60206df566 100644 --- a/src/language/schemaCoordinateLexer.ts +++ b/src/language/schemaCoordinateLexer.ts @@ -48,7 +48,7 @@ export class SchemaCoordinateLexer implements LexerInterface { this.token = startOfFileToken; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'SchemaCoordinateLexer'; } diff --git a/src/language/source.ts b/src/language/source.ts index 06d78b2c3f..a058bd8c78 100644 --- a/src/language/source.ts +++ b/src/language/source.ts @@ -41,7 +41,7 @@ export class Source { ); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'Source'; } } diff --git a/src/type/definition.ts b/src/type/definition.ts index 8fa65538eb..30926a7fb7 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -400,7 +400,7 @@ export class GraphQLList< this.ofType = ofType; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLList'; } @@ -445,7 +445,7 @@ export class GraphQLNonNull< this.ofType = ofType; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLNonNull'; } @@ -740,7 +740,7 @@ export class GraphQLScalarType< } } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLScalarType'; } @@ -904,7 +904,7 @@ export class GraphQLObjectType< TContext = any, TAbstract = any, > implements GraphQLSchemaElement { - readonly __kind = objectSymbol; + readonly __kind: typeof objectSymbol = objectSymbol; name: string; description: Maybe; isTypeOf: Maybe>; @@ -933,7 +933,7 @@ export class GraphQLObjectType< this._interfaces = defineInterfaces.bind(undefined, config.interfaces); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLObjectType'; } @@ -1188,7 +1188,7 @@ export class GraphQLField< this.astNode = config.astNode; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLField'; } @@ -1247,7 +1247,7 @@ export class GraphQLArgument implements GraphQLSchemaElement { this.astNode = config.astNode; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLArgument'; } @@ -1353,7 +1353,7 @@ export class GraphQLInterfaceType< this._interfaces = defineInterfaces.bind(undefined, config.interfaces); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLInterfaceType'; } @@ -1482,7 +1482,7 @@ export class GraphQLUnionType< this._types = defineTypes.bind(undefined, config.types); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLUnionType'; } @@ -1608,7 +1608,7 @@ export class GraphQLEnumType /* */ implements GraphQLSchemaElement { this._nameLookup = null; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLEnumType'; } @@ -1833,7 +1833,7 @@ export class GraphQLEnumValue implements GraphQLSchemaElement { this.astNode = config.astNode; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLEnumValue'; } @@ -1913,7 +1913,7 @@ export class GraphQLInputObjectType implements GraphQLSchemaElement { this._fields = defineInputFieldMap.bind(undefined, this, config.fields); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLInputObjectType'; } @@ -2041,7 +2041,7 @@ export class GraphQLInputField implements GraphQLSchemaElement { this.astNode = config.astNode; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLInputField'; } diff --git a/src/type/directives.ts b/src/type/directives.ts index 412581d5f9..939bd55fd3 100644 --- a/src/type/directives.ts +++ b/src/type/directives.ts @@ -89,7 +89,7 @@ export class GraphQLDirective implements GraphQLSchemaElement { ); } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLDirective'; } @@ -177,7 +177,7 @@ export const GraphQLSkipDirective: GraphQLDirective = new GraphQLDirective({ /** * Used to conditionally defer fragments. */ -export const GraphQLDeferDirective = new GraphQLDirective({ +export const GraphQLDeferDirective: GraphQLDirective = new GraphQLDirective({ name: 'defer', description: 'Directs the executor to defer this fragment when the `if` argument is true or undefined.', @@ -201,7 +201,7 @@ export const GraphQLDeferDirective = new GraphQLDirective({ /** * Used to conditionally stream list fields. */ -export const GraphQLStreamDirective = new GraphQLDirective({ +export const GraphQLStreamDirective: GraphQLDirective = new GraphQLDirective({ name: 'stream', description: 'Directs the executor to stream plural fields when the `if` argument is true or undefined.', @@ -282,15 +282,16 @@ export const GraphQLOneOfDirective: GraphQLDirective = new GraphQLDirective({ /** * Disables error propagation (experimental). */ -export const GraphQLDisableErrorPropagationDirective = new GraphQLDirective({ - name: 'experimental_disableErrorPropagation', - description: 'Disables error propagation.', - locations: [ - DirectiveLocation.QUERY, - DirectiveLocation.MUTATION, - DirectiveLocation.SUBSCRIPTION, - ], -}); +export const GraphQLDisableErrorPropagationDirective: GraphQLDirective = + new GraphQLDirective({ + name: 'experimental_disableErrorPropagation', + description: 'Disables error propagation.', + locations: [ + DirectiveLocation.QUERY, + DirectiveLocation.MUTATION, + DirectiveLocation.SUBSCRIPTION, + ], + }); /** * The full list of specified directives. diff --git a/src/type/introspection.ts b/src/type/introspection.ts index fceb49b9f9..07ab23da57 100644 --- a/src/type/introspection.ts +++ b/src/type/introspection.ts @@ -516,24 +516,27 @@ export const __TypeKind: GraphQLEnumType = new GraphQLEnumType({ }, }); -export const SchemaMetaFieldDef = new GraphQLField(undefined, '__schema', { - type: new GraphQLNonNull(__Schema), - description: 'Access the current type schema of this server.', - resolve: (_source, _args, _context, { schema }) => schema, -}); +export const SchemaMetaFieldDef: GraphQLField = + new GraphQLField(undefined, '__schema', { + type: new GraphQLNonNull(__Schema), + description: 'Access the current type schema of this server.', + resolve: (_source, _args, _context, { schema }) => schema, + }); -export const TypeMetaFieldDef = new GraphQLField(undefined, '__type', { - type: __Type, - description: 'Request the type information of a single type.', - args: { name: { type: new GraphQLNonNull(GraphQLString) } }, - resolve: (_source, { name }, _context, { schema }) => schema.getType(name), -}); +export const TypeMetaFieldDef: GraphQLField = + new GraphQLField(undefined, '__type', { + type: __Type, + description: 'Request the type information of a single type.', + args: { name: { type: new GraphQLNonNull(GraphQLString) } }, + resolve: (_source, { name }, _context, { schema }) => schema.getType(name), + }); -export const TypeNameMetaFieldDef = new GraphQLField(undefined, '__typename', { - type: new GraphQLNonNull(GraphQLString), - description: 'The name of the current Object type at runtime.', - resolve: (_source, _args, _context, { parentType }) => parentType.name, -}); +export const TypeNameMetaFieldDef: GraphQLField = + new GraphQLField(undefined, '__typename', { + type: new GraphQLNonNull(GraphQLString), + description: 'The name of the current Object type at runtime.', + resolve: (_source, _args, _context, { parentType }) => parentType.name, + }); export const introspectionTypes: ReadonlyArray = Object.freeze([ diff --git a/src/type/scalars.ts b/src/type/scalars.ts index ddf2c3294c..b6bd6c6ab2 100644 --- a/src/type/scalars.ts +++ b/src/type/scalars.ts @@ -23,286 +23,293 @@ export const GRAPHQL_MAX_INT = 2147483647; * */ export const GRAPHQL_MIN_INT = -2147483648; -export const GraphQLInt = new GraphQLScalarType({ - name: 'Int', - description: - 'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.', +export const GraphQLInt: GraphQLScalarType = + new GraphQLScalarType({ + name: 'Int', + description: + 'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.', - coerceOutputValue(outputValue) { - const coercedValue = coerceOutputValueObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); - if (typeof coercedValue === 'number') { - return coerceIntFromNumber(coercedValue); - } - if (typeof coercedValue === 'boolean') { - return coercedValue ? 1 : 0; - } - if (typeof coercedValue === 'string') { - return coerceIntFromString(coercedValue); - } - if (typeof coercedValue === 'bigint') { - return coerceIntFromBigInt(coercedValue); - } - throw new GraphQLError( - `Int cannot represent non-integer value: ${inspect(coercedValue)}`, - ); - }, - - coerceInputValue(inputValue) { - if (typeof inputValue === 'number') { - return coerceIntFromNumber(inputValue); - } - if (typeof inputValue === 'bigint') { - return coerceIntFromBigInt(inputValue); - } - throw new GraphQLError( - `Int cannot represent non-integer value: ${inspect(inputValue)}`, - ); - }, - - coerceInputLiteral(valueNode) { - if (valueNode.kind !== Kind.INT) { + if (typeof coercedValue === 'number') { + return coerceIntFromNumber(coercedValue); + } + if (typeof coercedValue === 'boolean') { + return coercedValue ? 1 : 0; + } + if (typeof coercedValue === 'string') { + return coerceIntFromString(coercedValue); + } + if (typeof coercedValue === 'bigint') { + return coerceIntFromBigInt(coercedValue); + } throw new GraphQLError( - `Int cannot represent non-integer value: ${print(valueNode)}`, - { nodes: valueNode }, + `Int cannot represent non-integer value: ${inspect(coercedValue)}`, ); - } - const num = parseInt(valueNode.value, 10); - if (num > GRAPHQL_MAX_INT || num < GRAPHQL_MIN_INT) { + }, + + coerceInputValue(inputValue) { + if (typeof inputValue === 'number') { + return coerceIntFromNumber(inputValue); + } + if (typeof inputValue === 'bigint') { + return coerceIntFromBigInt(inputValue); + } throw new GraphQLError( - `Int cannot represent non 32-bit signed integer value: ${valueNode.value}`, - { nodes: valueNode }, + `Int cannot represent non-integer value: ${inspect(inputValue)}`, ); - } - return num; - }, - valueToLiteral(value) { - if ( - ((typeof value === 'number' && Number.isInteger(value)) || - typeof value === 'bigint') && - value <= GRAPHQL_MAX_INT && - value >= GRAPHQL_MIN_INT - ) { - return { kind: Kind.INT, value: String(value) }; - } - }, -}); - -export const GraphQLFloat = new GraphQLScalarType({ - name: 'Float', - description: - 'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).', - - coerceOutputValue(outputValue) { - const coercedValue = coerceOutputValueObject(outputValue); + }, + + coerceInputLiteral(valueNode) { + if (valueNode.kind !== Kind.INT) { + throw new GraphQLError( + `Int cannot represent non-integer value: ${print(valueNode)}`, + { nodes: valueNode }, + ); + } + const num = parseInt(valueNode.value, 10); + if (num > GRAPHQL_MAX_INT || num < GRAPHQL_MIN_INT) { + throw new GraphQLError( + `Int cannot represent non 32-bit signed integer value: ${valueNode.value}`, + { nodes: valueNode }, + ); + } + return num; + }, + valueToLiteral(value) { + if ( + ((typeof value === 'number' && Number.isInteger(value)) || + typeof value === 'bigint') && + value <= GRAPHQL_MAX_INT && + value >= GRAPHQL_MIN_INT + ) { + return { kind: Kind.INT, value: String(value) }; + } + }, + }); - if (typeof coercedValue === 'number') { - return coerceFloatFromNumber(coercedValue); - } - if (typeof coercedValue === 'boolean') { - return coercedValue ? 1 : 0; - } - if (typeof coercedValue === 'string') { - return coerceFloatFromString(coercedValue); - } - if (typeof coercedValue === 'bigint') { - return coerceFloatFromBigInt(coercedValue); - } - throw new GraphQLError( - `Float cannot represent non numeric value: ${inspect(coercedValue)}`, - ); - }, +export const GraphQLFloat: GraphQLScalarType = + new GraphQLScalarType({ + name: 'Float', + description: + 'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).', - coerceInputValue(inputValue) { - if (typeof inputValue === 'number') { - return coerceFloatFromNumber(inputValue); - } - if (typeof inputValue === 'bigint') { - return coerceFloatFromBigInt(inputValue); - } - throw new GraphQLError( - `Float cannot represent non numeric value: ${inspect(inputValue)}`, - ); - }, + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); - coerceInputLiteral(valueNode) { - if (valueNode.kind !== Kind.FLOAT && valueNode.kind !== Kind.INT) { + if (typeof coercedValue === 'number') { + return coerceFloatFromNumber(coercedValue); + } + if (typeof coercedValue === 'boolean') { + return coercedValue ? 1 : 0; + } + if (typeof coercedValue === 'string') { + return coerceFloatFromString(coercedValue); + } + if (typeof coercedValue === 'bigint') { + return coerceFloatFromBigInt(coercedValue); + } throw new GraphQLError( - `Float cannot represent non numeric value: ${print(valueNode)}`, - { nodes: valueNode }, + `Float cannot represent non numeric value: ${inspect(coercedValue)}`, ); - } - return parseFloat(valueNode.value); - }, - valueToLiteral(value) { - const literal = defaultScalarValueToLiteral(value); - if (literal.kind === Kind.FLOAT || literal.kind === Kind.INT) { - return literal; - } - }, -}); - -export const GraphQLString = new GraphQLScalarType({ - name: 'String', - description: - 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', - - coerceOutputValue(outputValue) { - const coercedValue = coerceOutputValueObject(outputValue); - - // Coerces string, boolean and number values to a string, but do not - // attempt to coerce object, function, symbol, or other types as strings. - if (typeof coercedValue === 'string') { - return coercedValue; - } - if (typeof coercedValue === 'boolean') { - return coercedValue ? 'true' : 'false'; - } - if (typeof coercedValue === 'number') { - return coerceStringFromNumber(coercedValue); - } - if (typeof coercedValue === 'bigint') { - return String(coercedValue); - } - throw new GraphQLError( - `String cannot represent value: ${inspect(outputValue)}`, - ); - }, + }, - coerceInputValue(inputValue) { - if (typeof inputValue !== 'string') { + coerceInputValue(inputValue) { + if (typeof inputValue === 'number') { + return coerceFloatFromNumber(inputValue); + } + if (typeof inputValue === 'bigint') { + return coerceFloatFromBigInt(inputValue); + } throw new GraphQLError( - `String cannot represent a non string value: ${inspect(inputValue)}`, + `Float cannot represent non numeric value: ${inspect(inputValue)}`, ); - } - return inputValue; - }, - - coerceInputLiteral(valueNode) { - if (valueNode.kind !== Kind.STRING) { + }, + + coerceInputLiteral(valueNode) { + if (valueNode.kind !== Kind.FLOAT && valueNode.kind !== Kind.INT) { + throw new GraphQLError( + `Float cannot represent non numeric value: ${print(valueNode)}`, + { nodes: valueNode }, + ); + } + return parseFloat(valueNode.value); + }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.FLOAT || literal.kind === Kind.INT) { + return literal; + } + }, + }); + +export const GraphQLString: GraphQLScalarType = + new GraphQLScalarType({ + name: 'String', + description: + 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', + + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); + + // Coerces string, boolean and number values to a string, but do not + // attempt to coerce object, function, symbol, or other types as strings. + if (typeof coercedValue === 'string') { + return coercedValue; + } + if (typeof coercedValue === 'boolean') { + return coercedValue ? 'true' : 'false'; + } + if (typeof coercedValue === 'number') { + return coerceStringFromNumber(coercedValue); + } + if (typeof coercedValue === 'bigint') { + return String(coercedValue); + } throw new GraphQLError( - `String cannot represent a non string value: ${print(valueNode)}`, - { nodes: valueNode }, + `String cannot represent value: ${inspect(outputValue)}`, ); - } - return valueNode.value; - }, - valueToLiteral(value) { - const literal = defaultScalarValueToLiteral(value); - if (literal.kind === Kind.STRING) { - return literal; - } - }, -}); - -export const GraphQLBoolean = new GraphQLScalarType({ - name: 'Boolean', - description: 'The `Boolean` scalar type represents `true` or `false`.', + }, - coerceOutputValue(outputValue) { - const coercedValue = coerceOutputValueObject(outputValue); + coerceInputValue(inputValue) { + if (typeof inputValue !== 'string') { + throw new GraphQLError( + `String cannot represent a non string value: ${inspect(inputValue)}`, + ); + } + return inputValue; + }, + + coerceInputLiteral(valueNode) { + if (valueNode.kind !== Kind.STRING) { + throw new GraphQLError( + `String cannot represent a non string value: ${print(valueNode)}`, + { nodes: valueNode }, + ); + } + return valueNode.value; + }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.STRING) { + return literal; + } + }, + }); - if (typeof coercedValue === 'boolean') { - return coercedValue; - } - if (typeof coercedValue === 'number') { - return coerceBooleanFromNumber(coercedValue); - } - if (typeof coercedValue === 'bigint') { - return coercedValue !== 0n; - } - throw new GraphQLError( - `Boolean cannot represent a non boolean value: ${inspect(coercedValue)}`, - ); - }, +export const GraphQLBoolean: GraphQLScalarType = + new GraphQLScalarType({ + name: 'Boolean', + description: 'The `Boolean` scalar type represents `true` or `false`.', - coerceInputValue(inputValue) { - if (typeof inputValue !== 'boolean') { - throw new GraphQLError( - `Boolean cannot represent a non boolean value: ${inspect(inputValue)}`, - ); - } - return inputValue; - }, + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); - coerceInputLiteral(valueNode) { - if (valueNode.kind !== Kind.BOOLEAN) { + if (typeof coercedValue === 'boolean') { + return coercedValue; + } + if (typeof coercedValue === 'number') { + return coerceBooleanFromNumber(coercedValue); + } + if (typeof coercedValue === 'bigint') { + return coercedValue !== 0n; + } throw new GraphQLError( - `Boolean cannot represent a non boolean value: ${print(valueNode)}`, - { nodes: valueNode }, + `Boolean cannot represent a non boolean value: ${inspect(coercedValue)}`, ); - } - return valueNode.value; - }, - valueToLiteral(value) { - const literal = defaultScalarValueToLiteral(value); - if (literal.kind === Kind.BOOLEAN) { - return literal; - } - }, -}); + }, -export const GraphQLID = new GraphQLScalarType({ - name: 'ID', - description: - 'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.', + coerceInputValue(inputValue) { + if (typeof inputValue !== 'boolean') { + throw new GraphQLError( + `Boolean cannot represent a non boolean value: ${inspect(inputValue)}`, + ); + } + return inputValue; + }, + + coerceInputLiteral(valueNode) { + if (valueNode.kind !== Kind.BOOLEAN) { + throw new GraphQLError( + `Boolean cannot represent a non boolean value: ${print(valueNode)}`, + { nodes: valueNode }, + ); + } + return valueNode.value; + }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.BOOLEAN) { + return literal; + } + }, + }); - coerceOutputValue(outputValue) { - const coercedValue = coerceOutputValueObject(outputValue); +export const GraphQLID: GraphQLScalarType = + new GraphQLScalarType({ + name: 'ID', + description: + 'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.', - if (typeof coercedValue === 'string') { - return coercedValue; - } - if (typeof coercedValue === 'number') { - return coerceIDFromNumber(coercedValue); - } - if (typeof coercedValue === 'bigint') { - return String(coercedValue); - } - throw new GraphQLError( - `ID cannot represent value: ${inspect(outputValue)}`, - ); - }, + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); - coerceInputValue(inputValue) { - if (typeof inputValue === 'string') { - return inputValue; - } - if (typeof inputValue === 'number') { - return coerceIDFromNumber(inputValue); - } - if (typeof inputValue === 'bigint') { - return String(inputValue); - } - throw new GraphQLError(`ID cannot represent value: ${inspect(inputValue)}`); - }, + if (typeof coercedValue === 'string') { + return coercedValue; + } + if (typeof coercedValue === 'number') { + return coerceIDFromNumber(coercedValue); + } + if (typeof coercedValue === 'bigint') { + return String(coercedValue); + } + throw new GraphQLError( + `ID cannot represent value: ${inspect(outputValue)}`, + ); + }, - coerceInputLiteral(valueNode) { - if (valueNode.kind !== Kind.STRING && valueNode.kind !== Kind.INT) { + coerceInputValue(inputValue) { + if (typeof inputValue === 'string') { + return inputValue; + } + if (typeof inputValue === 'number') { + return coerceIDFromNumber(inputValue); + } + if (typeof inputValue === 'bigint') { + return String(inputValue); + } throw new GraphQLError( - 'ID cannot represent a non-string and non-integer value: ' + - print(valueNode), - { nodes: valueNode }, + `ID cannot represent value: ${inspect(inputValue)}`, ); - } - return valueNode.value; - }, - valueToLiteral(value) { - // ID types can use number values and Int literals. - if (typeof value === 'string') { - // Will parse as an IntValue. - return /^-?(?:0|[1-9][0-9]*)$/.test(value) - ? { kind: Kind.INT, value } - : { kind: Kind.STRING, value, block: false }; - } - if (typeof value === 'number') { - return { kind: Kind.INT, value: coerceIDFromNumber(value) }; - } - if (typeof value === 'bigint') { - return { kind: Kind.INT, value: String(value) }; - } - }, -}); + }, + + coerceInputLiteral(valueNode) { + if (valueNode.kind !== Kind.STRING && valueNode.kind !== Kind.INT) { + throw new GraphQLError( + 'ID cannot represent a non-string and non-integer value: ' + + print(valueNode), + { nodes: valueNode }, + ); + } + return valueNode.value; + }, + valueToLiteral(value) { + // ID types can use number values and Int literals. + if (typeof value === 'string') { + // Will parse as an IntValue. + return /^-?(?:0|[1-9][0-9]*)$/.test(value) + ? { kind: Kind.INT, value } + : { kind: Kind.STRING, value, block: false }; + } + if (typeof value === 'number') { + return { kind: Kind.INT, value: coerceIDFromNumber(value) }; + } + if (typeof value === 'bigint') { + return { kind: Kind.INT, value: String(value) }; + } + }, + }); export const specifiedScalarTypes: ReadonlyArray = Object.freeze([ diff --git a/src/type/schema.ts b/src/type/schema.ts index e8600eb980..5b20f052eb 100644 --- a/src/type/schema.ts +++ b/src/type/schema.ts @@ -135,7 +135,7 @@ const schemaSymbol: unique symbol = Symbol('Schema'); * ``` */ export class GraphQLSchema { - readonly __kind = schemaSymbol; + readonly __kind: typeof schemaSymbol = schemaSymbol; description: Maybe; extensions: Readonly; astNode: Maybe; @@ -258,7 +258,7 @@ export class GraphQLSchema { } } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'GraphQLSchema'; } diff --git a/src/utilities/TypeInfo.ts b/src/utilities/TypeInfo.ts index 22255faf64..e2c9683835 100644 --- a/src/utilities/TypeInfo.ts +++ b/src/utilities/TypeInfo.ts @@ -100,7 +100,7 @@ export class TypeInfo { } } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'TypeInfo'; } @@ -154,7 +154,7 @@ export class TypeInfo { return this._enumValue; } - enter(node: ASTNode) { + enter(node: ASTNode): void { const schema = this._schema; // Note: many of the types below are explicitly typed as "unknown" to drop // any assumptions of a valid schema to ensure runtime types are properly @@ -292,7 +292,7 @@ export class TypeInfo { } } - leave(node: ASTNode) { + leave(node: ASTNode): void { switch (node.kind) { case Kind.DOCUMENT: this._fragmentSignaturesByName = /* c8 ignore start */ () => diff --git a/src/validation/ValidationContext.ts b/src/validation/ValidationContext.ts index a37220a33f..83f5823c5b 100644 --- a/src/validation/ValidationContext.ts +++ b/src/validation/ValidationContext.ts @@ -62,7 +62,7 @@ export class ASTValidationContext { this._onError = onError; } - get [Symbol.toStringTag]() { + get [Symbol.toStringTag](): string { return 'ASTValidationContext'; } @@ -154,11 +154,11 @@ export class SDLValidationContext extends ASTValidationContext { this._schema = schema; } - get hideSuggestions() { + get hideSuggestions(): boolean { return false; } - override get [Symbol.toStringTag]() { + override get [Symbol.toStringTag](): string { return 'SDLValidationContext'; } @@ -198,11 +198,11 @@ export class ValidationContext extends ASTValidationContext { this._hideSuggestions = hideSuggestions ?? false; } - override get [Symbol.toStringTag]() { + override get [Symbol.toStringTag](): string { return 'ValidationContext'; } - get hideSuggestions() { + get hideSuggestions(): boolean { return this._hideSuggestions; } diff --git a/src/validation/specifiedRules.ts b/src/validation/specifiedRules.ts index fa2d746de4..225b87e3fc 100644 --- a/src/validation/specifiedRules.ts +++ b/src/validation/specifiedRules.ts @@ -83,7 +83,9 @@ import type { SDLValidationRule, ValidationRule } from './ValidationContext.js'; * Technically these aren't part of the spec but they are strongly encouraged * validation rules. */ -export const recommendedRules = Object.freeze([MaxIntrospectionDepthRule]); +export const recommendedRules: ReadonlyArray = Object.freeze([ + MaxIntrospectionDepthRule, +]); /** * This set includes all validation rules defined by the GraphQL spec. diff --git a/src/version.ts b/src/version.ts index 8757ea4f97..5ccce4d43b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -9,7 +9,12 @@ export const version = '17.0.0-alpha.13' as string; /** * An object containing the components of the GraphQL.js version string */ -export const versionInfo = Object.freeze({ +export const versionInfo: Readonly<{ + major: number; + minor: number; + patch: number; + preReleaseTag: string | null; +}> = Object.freeze({ major: 17 as number, minor: 0 as number, patch: 0 as number, diff --git a/tsconfig.json b/tsconfig.json index 02b1deddd8..2749111b7f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,8 +12,10 @@ "inlineSources": true, "module": "node16", "moduleResolution": "node16", + "declaration": true, "noEmit": true, "isolatedModules": true, + "isolatedDeclarations": true, "verbatimModuleSyntax": true, "forceConsistentCasingInFileNames": true, // Type Checking