diff --git a/.eslintrc.yml b/.eslintrc.yml index 66567952f8..cc4f7a14cc 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -632,12 +632,25 @@ overrides: '@typescript-eslint/type-annotation-spacing': off - files: '**/__*__/**' rules: + '@typescript-eslint/consistent-type-assertions': + [error, { assertionStyle: as, objectLiteralTypeAssertions: allow }] + '@typescript-eslint/no-non-null-assertion': off + '@typescript-eslint/restrict-plus-operands': off + '@typescript-eslint/no-floating-promises': off + '@typescript-eslint/no-invalid-this': off + '@typescript-eslint/no-throw-literal': off + '@typescript-eslint/require-await': off + '@typescript-eslint/await-thenable': off + 'prefer-promise-reject-errors': 0 + 'no-new-wrappers': 0 + 'no-throw-literal': 0 node/no-unpublished-import: off node/no-unpublished-require: off import/no-restricted-paths: off import/no-extraneous-dependencies: [error, { devDependencies: true }] import/no-nodejs-modules: off no-restricted-syntax: off + flowtype/type-import-style: off - files: 'resources/**' parserOptions: sourceType: script diff --git a/.flowconfig b/.flowconfig index 9b6cc9e48d..8c13004ee3 100644 --- a/.flowconfig +++ b/.flowconfig @@ -36,7 +36,6 @@ module.use_strict=true babel_loose_array_spread=true esproposal.optional_chaining=enable suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$DisableFlowOnNegativeTest [version] ^0.126.0 diff --git a/.mocharc.yml b/.mocharc.yml index 5e75d26389..6a9f5ba6e2 100644 --- a/.mocharc.yml +++ b/.mocharc.yml @@ -2,3 +2,4 @@ throw-deprecation: true check-leaks: true require: - '@babel/register' + - ts-node/register diff --git a/cspell.json b/cspell.json index 3d89a84bf3..e16524df6c 100644 --- a/cspell.json +++ b/cspell.json @@ -18,6 +18,9 @@ "Alderaan", "Tatooine", "astromech", + "structs", + "geocode", + "behaviour", // TODO: remove bellow words "Graphi", // GraphiQL diff --git a/package-lock.json b/package-lock.json index 09f2c06e69..8142ddc003 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2360,6 +2360,12 @@ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true }, + "@types/chai": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.11.tgz", + "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", + "dev": true + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -2378,10 +2384,16 @@ "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", "dev": true }, + "@types/mocha": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", + "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "dev": true + }, "@types/node": { - "version": "12.12.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.43.tgz", - "integrity": "sha512-KUyZdkGCnVPuXfsKmDUu2XLui65LZIJ2s0M57noy5e+ixUT2oK33ep7zlvgzI8LElcWqbf8AR+o/3GqAPac2zA==", + "version": "14.0.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.9.tgz", + "integrity": "sha512-0sCTiXKXELOBxvZLN4krQ0FPOAA7ij+6WwvD0k/PHd9/KAkr4dXel5J9fh6F4x1FwAQILqAWkmpeuS6mjf1iKA==", "dev": true }, "@types/parsimmon": { @@ -2573,6 +2585,12 @@ "readable-stream": "^2.0.6" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -3743,6 +3761,12 @@ "tar-stream": "1.6.2" }, "dependencies": { + "@types/node": { + "version": "12.12.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.43.tgz", + "integrity": "sha512-KUyZdkGCnVPuXfsKmDUu2XLui65LZIJ2s0M57noy5e+ixUT2oK33ep7zlvgzI8LElcWqbf8AR+o/3GqAPac2zA==", + "dev": true + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -5612,6 +5636,12 @@ "semver": "^5.6.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -7267,6 +7297,27 @@ "punycode": "^2.1.1" } }, + "ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -7898,6 +7949,12 @@ } } } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/package.json b/package.json index 05ab923fb1..1e7658059c 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,8 @@ "scripts": { "test": "npm run prettier:check && npm run lint && npm run check && npm run testonly && npm run check:ts && npm run check:spelling", "test:ci": "npm run prettier:check && npm run lint -- --no-cache && npm run check && npm run testonly:cover && npm run check:ts && npm run check:spelling && npm run build", - "fuzzonly": "mocha --full-trace src/**/__tests__/**/*-fuzz.js", - "testonly": "mocha --full-trace src/**/__tests__/**/*-test.js", + "fuzzonly": "mocha --full-trace src/**/__tests__/**/*-fuzz.ts", + "testonly": "mocha --full-trace src/**/__tests__/**/*-test.ts", "testonly:cover": "nyc npm run testonly", "lint": "eslint --cache --ext .js,.ts src resources", "benchmark": "node --noconcurrent_sweeping --expose-gc --predictable ./resources/benchmark.js", @@ -46,6 +46,9 @@ "dependencies": {}, "devDependencies": { "@babel/core": "7.10.2", + "@types/node": "14.0.9", + "@types/mocha": "7.0.2", + "@types/chai": "4.2.11", "@babel/plugin-transform-flow-strip-types": "7.10.1", "@babel/preset-env": "7.10.2", "@babel/register": "7.10.1", @@ -65,6 +68,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "prettier": "2.0.5", + "ts-node": "8.10.2", "typescript": "3.9.3" } } diff --git a/src/__fixtures__/index.d.ts b/src/__fixtures__/index.d.ts new file mode 100644 index 0000000000..0e281da754 --- /dev/null +++ b/src/__fixtures__/index.d.ts @@ -0,0 +1,4 @@ +export declare const bigSchemaSDL: string; +export declare const bigSchemaIntrospectionResult: Record; +export declare const kitchenSinkSDL: string; +export declare const kitchenSinkQuery: string; diff --git a/src/__fixtures__/index.js b/src/__fixtures__/index.js index 460bee30f0..f906dbc3d3 100644 --- a/src/__fixtures__/index.js +++ b/src/__fixtures__/index.js @@ -1,18 +1,21 @@ +/* eslint-disable import/no-commonjs */ // @flow strict -import { join } from 'path'; -import { readFileSync } from 'fs'; +// FIXME: This file should remain as JS file, and has a supporting `d.ts` file, +// because it's in use by other areas of that repo (like benchmark tests). +// I should be converted to `.ts` after migrating the entire build system to TS. -function readLocalFile(filename: string): string { +const { join } = require('path'); +const { readFileSync } = require('fs'); + +function readLocalFile(filename) { return readFileSync(join(__dirname, filename), 'utf8'); } -export const bigSchemaSDL: string = readLocalFile('github-schema.graphql'); -export const bigSchemaIntrospectionResult: any = JSON.parse( +export const bigSchemaSDL = readLocalFile('github-schema.graphql'); +export const bigSchemaIntrospectionResult = JSON.parse( readLocalFile('github-schema.json'), ); -export const kitchenSinkSDL: string = readLocalFile( - 'schema-kitchen-sink.graphql', -); -export const kitchenSinkQuery: string = readLocalFile('kitchen-sink.graphql'); +export const kitchenSinkSDL = readLocalFile('schema-kitchen-sink.graphql'); +export const kitchenSinkQuery = readLocalFile('kitchen-sink.graphql'); diff --git a/src/__testUtils__/__tests__/dedent-test.js b/src/__testUtils__/__tests__/dedent-test.ts similarity index 99% rename from src/__testUtils__/__tests__/dedent-test.js rename to src/__testUtils__/__tests__/dedent-test.ts index 192af3c8de..9ee2440bce 100644 --- a/src/__testUtils__/__tests__/dedent-test.js +++ b/src/__testUtils__/__tests__/dedent-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/__testUtils__/__tests__/genFuzzStrings-test.js b/src/__testUtils__/__tests__/genFuzzStrings-test.ts similarity index 94% rename from src/__testUtils__/__tests__/genFuzzStrings-test.js rename to src/__testUtils__/__tests__/genFuzzStrings-test.ts index 0e9ec2b189..92ea5c592d 100644 --- a/src/__testUtils__/__tests__/genFuzzStrings-test.js +++ b/src/__testUtils__/__tests__/genFuzzStrings-test.ts @@ -1,11 +1,12 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; import genFuzzStrings from '../genFuzzStrings'; -function expectFuzzStrings(options) { +function expectFuzzStrings(options: { + allowedChars: Array; + maxLength: number; +}) { return expect(Array.from(genFuzzStrings(options))); } diff --git a/src/__testUtils__/__tests__/inspectStr-test.js b/src/__testUtils__/__tests__/inspectStr-test.ts similarity index 97% rename from src/__testUtils__/__tests__/inspectStr-test.js rename to src/__testUtils__/__tests__/inspectStr-test.ts index ba7e9f3688..b31e59b159 100644 --- a/src/__testUtils__/__tests__/inspectStr-test.js +++ b/src/__testUtils__/__tests__/inspectStr-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/__testUtils__/dedent.js b/src/__testUtils__/dedent.ts similarity index 91% rename from src/__testUtils__/dedent.js rename to src/__testUtils__/dedent.ts index 80aef9be46..5aab8b206a 100644 --- a/src/__testUtils__/dedent.js +++ b/src/__testUtils__/dedent.ts @@ -1,5 +1,3 @@ -// @flow strict - /** * An ES6 string tag that fixes indentation. Also removes leading newlines * and trailing spaces and tabs, but keeps trailing newlines. @@ -13,8 +11,8 @@ * str === "{\n test\n}\n"; */ export default function dedent( - strings: $ReadOnlyArray, - ...values: $ReadOnlyArray + strings: string | ReadonlyArray, + ...values: ReadonlyArray ): string { let str = ''; diff --git a/src/__testUtils__/genFuzzStrings.js b/src/__testUtils__/genFuzzStrings.ts similarity index 82% rename from src/__testUtils__/genFuzzStrings.js rename to src/__testUtils__/genFuzzStrings.ts index b8258a75fe..b9e4a0af7e 100644 --- a/src/__testUtils__/genFuzzStrings.js +++ b/src/__testUtils__/genFuzzStrings.ts @@ -1,12 +1,10 @@ -// @flow strict - /** * Generator that produces all possible combinations of allowed characters. */ -export default function* genFuzzStrings(options: {| - allowedChars: Array, - maxLength: number, -|}): Generator { +export default function* genFuzzStrings(options: { + allowedChars: Array; + maxLength: number; +}): Generator { const { allowedChars, maxLength } = options; const numAllowedChars = allowedChars.length; diff --git a/src/__testUtils__/inspectStr.js b/src/__testUtils__/inspectStr.ts similarity index 70% rename from src/__testUtils__/inspectStr.js rename to src/__testUtils__/inspectStr.ts index 1c2061888f..c9047d094a 100644 --- a/src/__testUtils__/inspectStr.js +++ b/src/__testUtils__/inspectStr.ts @@ -1,9 +1,9 @@ -// @flow strict +import { Maybe } from '../jsutils/Maybe'; /** * Special inspect function to produce readable string literal for error messages in tests */ -export default function inspectStr(str: ?string): string { +export default function inspectStr(str: Maybe): string { if (str == null) { return 'null'; } diff --git a/src/__tests__/starWarsData.js b/src/__tests__/starWarsData.ts similarity index 72% rename from src/__tests__/starWarsData.js rename to src/__tests__/starWarsData.ts index 5144f3735e..f37ef26aa2 100644 --- a/src/__tests__/starWarsData.js +++ b/src/__tests__/starWarsData.ts @@ -1,4 +1,25 @@ -// @flow strict +import { Maybe } from '../jsutils/Maybe'; + +/** + * These are TS types which correspond to the schema. + * They represent the shape of the data visited during field resolution. + */ +export type Character = { + id: string; + name: string; + friends: Array; + appearsIn: Array; +}; + +export type Human = Character & { + type: 'Human'; + homePlanet?: string; +}; + +export type Droid = Character & { + type: 'Droid'; + primaryFunction: string; +}; /** * This defines a basic set of data for our Star Wars Schema. @@ -8,7 +29,7 @@ * JSON objects in a more complex demo. */ -const luke = { +const luke: Human = { type: 'Human', id: '1000', name: 'Luke Skywalker', @@ -17,7 +38,7 @@ const luke = { homePlanet: 'Tatooine', }; -const vader = { +const vader: Human = { type: 'Human', id: '1001', name: 'Darth Vader', @@ -26,7 +47,7 @@ const vader = { homePlanet: 'Tatooine', }; -const han = { +const han: Human = { type: 'Human', id: '1002', name: 'Han Solo', @@ -34,7 +55,7 @@ const han = { appearsIn: [4, 5, 6], }; -const leia = { +const leia: Human = { type: 'Human', id: '1003', name: 'Leia Organa', @@ -43,7 +64,7 @@ const leia = { homePlanet: 'Alderaan', }; -const tarkin = { +const tarkin: Human = { type: 'Human', id: '1004', name: 'Wilhuff Tarkin', @@ -51,7 +72,7 @@ const tarkin = { appearsIn: [4], }; -const humanData = { +const humanData: Record> = { '1000': luke, '1001': vader, '1002': han, @@ -59,7 +80,7 @@ const humanData = { '1004': tarkin, }; -const threepio = { +const threepio: Droid = { type: 'Droid', id: '2000', name: 'C-3PO', @@ -68,7 +89,7 @@ const threepio = { primaryFunction: 'Protocol', }; -const artoo = { +const artoo: Droid = { type: 'Droid', id: '2001', name: 'R2-D2', @@ -77,45 +98,15 @@ const artoo = { primaryFunction: 'Astromech', }; -const droidData = { +const droidData: Record> = { '2000': threepio, '2001': artoo, }; -/** - * These are Flow types which correspond to the schema. - * They represent the shape of the data visited during field resolution. - */ -export type Character = { - id: string, - name: string, - friends: Array, - appearsIn: Array, - ... -}; - -export type Human = {| - type: 'Human', - id: string, - name: string, - friends: Array, - appearsIn: Array, - homePlanet: string, -|}; - -export type Droid = {| - type: 'Droid', - id: string, - name: string, - friends: Array, - appearsIn: Array, - primaryFunction: string, -|}; - /** * Helper function to get a character by ID. */ -function getCharacter(id) { +function getCharacter(id: string): Promise> { // Returning a promise just to illustrate that GraphQL.js supports it. return Promise.resolve(humanData[id] ?? droidData[id]); } @@ -123,7 +114,9 @@ function getCharacter(id) { /** * Allows us to query for a character's friends. */ -export function getFriends(character: Character): Array> { +export function getFriends( + character: Character, +): Array>> { // Notice that GraphQL accepts Arrays of Promises. return character.friends.map((id) => getCharacter(id)); } @@ -143,13 +136,13 @@ export function getHero(episode: number): Character { /** * Allows us to query for the human with the given id. */ -export function getHuman(id: string): Human { +export function getHuman(id: string): Maybe { return humanData[id]; } /** * Allows us to query for the droid with the given id. */ -export function getDroid(id: string): Droid { +export function getDroid(id: string): Maybe { return droidData[id]; } diff --git a/src/__tests__/starWarsIntrospection-test.js b/src/__tests__/starWarsIntrospection-test.ts similarity index 99% rename from src/__tests__/starWarsIntrospection-test.js rename to src/__tests__/starWarsIntrospection-test.ts index 8db0c324c6..d637787c4a 100644 --- a/src/__tests__/starWarsIntrospection-test.js +++ b/src/__tests__/starWarsIntrospection-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -7,7 +5,7 @@ import { graphqlSync } from '../graphql'; import { StarWarsSchema } from './starWarsSchema'; -function queryStarWars(source) { +function queryStarWars(source: string) { const result = graphqlSync({ schema: StarWarsSchema, source }); expect(Object.keys(result)).to.deep.equal(['data']); return result.data; diff --git a/src/__tests__/starWarsQuery-test.js b/src/__tests__/starWarsQuery-test.ts similarity index 99% rename from src/__tests__/starWarsQuery-test.js rename to src/__tests__/starWarsQuery-test.ts index fd14017293..8b8ef8a56e 100644 --- a/src/__tests__/starWarsQuery-test.js +++ b/src/__tests__/starWarsQuery-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/__tests__/starWarsSchema.js b/src/__tests__/starWarsSchema.ts similarity index 98% rename from src/__tests__/starWarsSchema.js rename to src/__tests__/starWarsSchema.ts index 6d3c778ba7..16ee5c3444 100644 --- a/src/__tests__/starWarsSchema.js +++ b/src/__tests__/starWarsSchema.ts @@ -1,5 +1,3 @@ -// @flow strict - import invariant from '../jsutils/invariant'; import { GraphQLSchema } from '../type/schema'; @@ -100,7 +98,7 @@ const episodeEnum = new GraphQLEnumType({ * secretBackstory: String * } */ -const characterInterface = new GraphQLInterfaceType({ +const characterInterface: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Character', description: 'A character in the Star Wars Trilogy', fields: () => ({ @@ -294,7 +292,7 @@ const queryType = new GraphQLObjectType({ * Finally, we construct our schema (whose starting query type is the query * type we defined above) and export it. */ -export const StarWarsSchema: GraphQLSchema = new GraphQLSchema({ +export const StarWarsSchema = new GraphQLSchema({ query: queryType, types: [humanType, droidType], }); diff --git a/src/__tests__/starWarsValidation-test.js b/src/__tests__/starWarsValidation-test.ts similarity index 98% rename from src/__tests__/starWarsValidation-test.js rename to src/__tests__/starWarsValidation-test.ts index e746b60688..65e6c7f666 100644 --- a/src/__tests__/starWarsValidation-test.js +++ b/src/__tests__/starWarsValidation-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -13,7 +11,7 @@ import { StarWarsSchema } from './starWarsSchema'; /** * Helper function to test a query and the expected response. */ -function validationErrors(query) { +function validationErrors(query: string) { const source = new Source(query, 'StarWars.graphql'); const ast = parse(source); return validate(StarWarsSchema, ast); diff --git a/src/__tests__/version-test.js b/src/__tests__/version-test.ts similarity index 93% rename from src/__tests__/version-test.js rename to src/__tests__/version-test.ts index 928c5d8094..24d5554188 100644 --- a/src/__tests__/version-test.js +++ b/src/__tests__/version-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -31,6 +29,7 @@ describe('Version', () => { expect(preReleaseTag).to.be.a('string'); } + // FIXME: prefer using template literals instead of plus operand expect( `${major}.${minor}.${patch}` + // istanbul ignore next (Can't be verified on all versions) diff --git a/src/error/GraphQLError.d.ts b/src/error/GraphQLError.d.ts index 4e741f9796..99001fd26f 100644 --- a/src/error/GraphQLError.d.ts +++ b/src/error/GraphQLError.d.ts @@ -13,7 +13,7 @@ import { SourceLocation } from '../language/location'; export class GraphQLError extends Error { constructor( message: string, - nodes?: ReadonlyArray | ASTNode, + nodes?: Maybe | ASTNode>, source?: Maybe, positions?: Maybe>, path?: Maybe>, diff --git a/src/error/__tests__/GraphQLError-test.js b/src/error/__tests__/GraphQLError-test.ts similarity index 94% rename from src/error/__tests__/GraphQLError-test.js rename to src/error/__tests__/GraphQLError-test.ts index a4130b96c6..399986df7a 100644 --- a/src/error/__tests__/GraphQLError-test.js +++ b/src/error/__tests__/GraphQLError-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -12,6 +10,10 @@ import { parse } from '../../language/parser'; import { Source } from '../../language/source'; import { GraphQLError, printError } from '../GraphQLError'; +import type { + OperationDefinitionNode, + ObjectTypeDefinitionNode, +} from '../../language/ast'; const source = new Source(dedent` { @@ -21,7 +23,8 @@ const source = new Source(dedent` const ast = parse(source); const operationNode = ast.definitions[0]; invariant(operationNode.kind === Kind.OPERATION_DEFINITION); -const fieldNode = operationNode.selectionSet.selections[0]; +const fieldNode = (operationNode as OperationDefinitionNode).selectionSet + .selections[0]; invariant(fieldNode); describe('GraphQLError', () => { @@ -163,7 +166,7 @@ describe('printError', () => { ); const opA = docA.definitions[0]; invariant(opA.kind === Kind.OBJECT_TYPE_DEFINITION && opA.fields); - const fieldA = opA.fields[0]; + const fieldA = (opA as ObjectTypeDefinitionNode).fields![0]; const docB = parse( new Source( @@ -177,7 +180,7 @@ describe('printError', () => { ); const opB = docB.definitions[0]; invariant(opB.kind === Kind.OBJECT_TYPE_DEFINITION && opB.fields); - const fieldB = opB.fields[0]; + const fieldB = (opB as ObjectTypeDefinitionNode).fields![0]; const error = new GraphQLError('Example error with two nodes', [ fieldA.type, diff --git a/src/error/__tests__/formatError-test.js b/src/error/__tests__/formatError-test.ts similarity index 89% rename from src/error/__tests__/formatError-test.js rename to src/error/__tests__/formatError-test.ts index f1638804b0..4ab736b57f 100644 --- a/src/error/__tests__/formatError-test.js +++ b/src/error/__tests__/formatError-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -8,7 +6,7 @@ import { GraphQLError } from '../GraphQLError'; describe('formatError: default error formatter', () => { it('uses default message', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - due to missing error message const e = new GraphQLError(); expect(formatError(e)).to.deep.equal({ @@ -47,12 +45,12 @@ describe('formatError: default error formatter', () => { }); it('rejects null and undefined errors', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - due to undefined param expect(() => formatError(undefined)).to.throw( 'Received null or undefined error.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - due to null param expect(() => formatError(null)).to.throw( 'Received null or undefined error.', ); diff --git a/src/error/__tests__/locatedError-test.js b/src/error/__tests__/locatedError-test.ts similarity index 76% rename from src/error/__tests__/locatedError-test.js rename to src/error/__tests__/locatedError-test.ts index d30cb6ed72..a8cf8318d6 100644 --- a/src/error/__tests__/locatedError-test.js +++ b/src/error/__tests__/locatedError-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -20,19 +18,19 @@ describe('locatedError', () => { it('passes GraphQLError-ish through', () => { const e = new Error('I have a different prototype chain'); - (e: any).locations = []; - (e: any).path = []; - (e: any).nodes = []; - (e: any).source = null; - (e: any).positions = []; - (e: any).name = 'GraphQLError'; + (e as any).locations = []; + (e as any).path = []; + (e as any).nodes = []; + (e as any).source = null; + (e as any).positions = []; + (e as any).name = 'GraphQLError'; expect(locatedError(e, [], [])).to.deep.equal(e); }); it('does not pass through elasticsearch-like errors', () => { const e = new Error('I am from elasticsearch'); - (e: any).path = '/something/feed/_search'; + (e as any).path = '/something/feed/_search'; expect(locatedError(e, [], [])).to.not.deep.equal(e); }); diff --git a/src/execution/__tests__/abstract-promise-test.js b/src/execution/__tests__/abstract-promise-test.ts similarity index 98% rename from src/execution/__tests__/abstract-promise-test.js rename to src/execution/__tests__/abstract-promise-test.ts index 0c79b54ff2..b1ad3770de 100644 --- a/src/execution/__tests__/abstract-promise-test.js +++ b/src/execution/__tests__/abstract-promise-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -20,7 +18,7 @@ class Dog { name: string; woofs: boolean; - constructor(name, woofs) { + constructor(name: string, woofs: boolean) { this.name = name; this.woofs = woofs; } @@ -30,7 +28,7 @@ class Cat { name: string; meows: boolean; - constructor(name, meows) { + constructor(name: string, meows: boolean) { this.name = name; this.meows = meows; } @@ -39,7 +37,7 @@ class Cat { class Human { name: string; - constructor(name) { + constructor(name: string) { this.name = name; } } @@ -267,7 +265,7 @@ describe('Execute: Handles execution of abstract types with promises', () => { }); it('resolveType on Interface yields useful error', async () => { - const PetType = new GraphQLInterfaceType({ + const PetType: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Pet', resolveType(obj) { if (obj instanceof Dog) { diff --git a/src/execution/__tests__/abstract-test.js b/src/execution/__tests__/abstract-test.ts similarity index 98% rename from src/execution/__tests__/abstract-test.js rename to src/execution/__tests__/abstract-test.ts index 3e42ead8b5..b10b764ab6 100644 --- a/src/execution/__tests__/abstract-test.js +++ b/src/execution/__tests__/abstract-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -20,7 +18,7 @@ class Dog { name: string; woofs: boolean; - constructor(name, woofs) { + constructor(name: string, woofs: boolean) { this.name = name; this.woofs = woofs; } @@ -30,7 +28,7 @@ class Cat { name: string; meows: boolean; - constructor(name, meows) { + constructor(name: string, meows: boolean) { this.name = name; this.meows = meows; } @@ -39,7 +37,7 @@ class Cat { class Human { name: string; - constructor(name) { + constructor(name: string) { this.name = name; } } @@ -190,7 +188,7 @@ describe('Execute: Handles execution of abstract types', () => { }); it('resolveType on Interface yields useful error', () => { - const PetType = new GraphQLInterfaceType({ + const PetType: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Pet', resolveType(obj) { if (obj instanceof Dog) { @@ -405,7 +403,7 @@ describe('Execute: Handles execution of abstract types', () => { const fooInterface = new GraphQLInterfaceType({ name: 'FooInterface', fields: { bar: { type: GraphQLString } }, - // $DisableFlowOnNegativeTest + // @ts-expect-error - incorrect function implementation resolveType() { return []; }, diff --git a/src/execution/__tests__/directives-test.js b/src/execution/__tests__/directives-test.ts similarity index 99% rename from src/execution/__tests__/directives-test.js rename to src/execution/__tests__/directives-test.ts index 810cd51b68..da769cac4f 100644 --- a/src/execution/__tests__/directives-test.js +++ b/src/execution/__tests__/directives-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -30,7 +28,7 @@ const rootValue = { }, }; -function executeTestQuery(query) { +function executeTestQuery(query: string) { const document = parse(query); return execute({ schema, document, rootValue }); } diff --git a/src/execution/__tests__/executor-test.js b/src/execution/__tests__/executor-test.ts similarity index 96% rename from src/execution/__tests__/executor-test.js rename to src/execution/__tests__/executor-test.ts index ef5d02076e..b5b4d238a0 100644 --- a/src/execution/__tests__/executor-test.js +++ b/src/execution/__tests__/executor-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -17,9 +15,12 @@ import { GraphQLScalarType, GraphQLInterfaceType, GraphQLObjectType, + GraphQLResolveInfo, + GraphQLAbstractType, } from '../../type/definition'; import { execute } from '../execute'; +import type { OperationDefinitionNode } from '../../language/ast'; describe('Execute: Handles basic execution tasks', () => { it('throws if no document is provided', () => { @@ -32,14 +33,14 @@ describe('Execute: Handles basic execution tasks', () => { }), }); - // $DisableFlowOnNegativeTest + // @ts-expect-error - no document provided expect(() => execute({ schema })).to.throw('Must provide document.'); }); it('throws if no schema is provided', () => { const document = parse('{ field }'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - no schema provided expect(() => execute({ document })).to.throw( 'Expected undefined to be a GraphQL schema.', ); @@ -64,7 +65,7 @@ describe('Execute: Handles basic execution tasks', () => { `); const variableValues = '{ "a": 1 }'; - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid variables object expect(() => execute({ schema, document, variableValues })).to.throw( 'Variables must be provided as an Object where each property is a variable value. Perhaps look to see if an unparsed JSON string was provided.', ); @@ -103,7 +104,7 @@ describe('Execute: Handles basic execution tasks', () => { e: () => 'Egg', f: 'Fish', // Called only by DataType::pic static resolver - pic: (size) => 'Pic of size: ' + size, + pic: (size: number) => `Pic of size: ${size}`, deep: () => deepData, promise: promiseData, }; @@ -123,7 +124,7 @@ describe('Execute: Handles basic execution tasks', () => { }); } - const DataType = new GraphQLObjectType({ + const DataType: GraphQLObjectType = new GraphQLObjectType({ name: 'DataType', fields: () => ({ a: { type: GraphQLString }, @@ -214,7 +215,7 @@ describe('Execute: Handles basic execution tasks', () => { }); it('merges parallel fragments', () => { - const Type = new GraphQLObjectType({ + const Type: GraphQLObjectType = new GraphQLObjectType({ name: 'Type', fields: () => ({ a: { type: GraphQLString, resolve: () => 'Apple' }, @@ -276,6 +277,7 @@ describe('Execute: Handles basic execution tasks', () => { const rootValue = { root: 'val' }; const variableValues = { var: 'abc' }; + // FIXME: https://github.com/graphql/graphql-js/issues/2610 execute({ schema, document, rootValue, variableValues }); expect(resolvedInfo).to.have.all.keys( @@ -303,7 +305,8 @@ describe('Execute: Handles basic execution tasks', () => { operation, }); - const field = operation.selectionSet.selections[0]; + const field = (operation as OperationDefinitionNode).selectionSet + .selections[0]; expect(resolvedInfo).to.deep.include({ fieldNodes: [field], path: { prev: undefined, key: 'result' }, @@ -330,6 +333,7 @@ describe('Execute: Handles basic execution tasks', () => { const document = parse('query Example { a }'); const rootValue = { contextThing: 'thing' }; + // FIXME: https://github.com/graphql/graphql-js/issues/2610 execute({ schema, document, rootValue }); expect(resolvedRootValue).to.equal(rootValue); }); @@ -360,6 +364,7 @@ describe('Execute: Handles basic execution tasks', () => { } `); + // FIXME: https://github.com/graphql/graphql-js/issues/2610 execute({ schema, document }); expect(resolvedArgs).to.deep.equal({ numArg: 123, stringArg: 'foo' }); }); @@ -413,7 +418,6 @@ describe('Execute: Handles basic execution tasks', () => { throw new Error('Error getting syncError'); }, syncRawError() { - // eslint-disable-next-line no-throw-literal throw 'Error getting syncRawError'; }, syncReturnError() { @@ -436,11 +440,9 @@ describe('Execute: Handles basic execution tasks', () => { ); }, asyncRawReject() { - // eslint-disable-next-line prefer-promise-reject-errors return Promise.reject('Error getting asyncRawReject'); }, asyncEmptyReject() { - // eslint-disable-next-line prefer-promise-reject-errors return Promise.reject(); }, asyncError() { @@ -450,7 +452,6 @@ describe('Execute: Handles basic execution tasks', () => { }, asyncRawError() { return new Promise(() => { - // eslint-disable-next-line no-throw-literal throw 'Error getting asyncRawError'; }); }, @@ -459,7 +460,7 @@ describe('Execute: Handles basic execution tasks', () => { }, asyncReturnErrorWithExtensions() { const error = new Error('Error getting asyncReturnErrorWithExtensions'); - (error: any).extensions = { foo: 'bar' }; + (error as any).extensions = { foo: 'bar' }; return Promise.resolve(error); }, @@ -593,7 +594,7 @@ describe('Execute: Handles basic execution tasks', () => { }); it('Full response path is included for non-nullable fields', () => { - const A = new GraphQLObjectType({ + const A: GraphQLObjectType = new GraphQLObjectType({ name: 'A', fields: () => ({ nullableA: { @@ -1006,7 +1007,7 @@ describe('Execute: Handles basic execution tasks', () => { class Special { value: string; - constructor(value) { + constructor(value: string) { this.value = value; } } @@ -1014,7 +1015,7 @@ describe('Execute: Handles basic execution tasks', () => { class NotSpecial { value: string; - constructor(value) { + constructor(value: string) { this.value = value; } } @@ -1131,7 +1132,12 @@ describe('Execute: Handles basic execution tasks', () => { }); const document = parse('{ foo }'); - function fieldResolver(_source, _args, _context, info) { + function fieldResolver( + _source: any, + _args: any, + _context: any, + info: GraphQLResolveInfo, + ) { // For the purposes of test, just return the name of the field! return info.fieldName; } @@ -1169,7 +1175,12 @@ describe('Execute: Handles basic execution tasks', () => { }); let possibleTypes; - function typeResolver(_source, _context, info, abstractType) { + function typeResolver( + _source: any, + _context: any, + info: any, + abstractType: GraphQLAbstractType, + ) { // Resolver should be able to figure out all possible types on its own possibleTypes = info.schema.getPossibleTypes(abstractType); diff --git a/src/execution/__tests__/lists-test.js b/src/execution/__tests__/lists-test.ts similarity index 98% rename from src/execution/__tests__/lists-test.js rename to src/execution/__tests__/lists-test.ts index c665c9f9ec..d0da537d40 100644 --- a/src/execution/__tests__/lists-test.js +++ b/src/execution/__tests__/lists-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -11,6 +9,7 @@ import { GraphQLList, GraphQLNonNull, GraphQLObjectType, + GraphQLOutputType, } from '../../type/definition'; import { execute } from '../execute'; @@ -27,11 +26,11 @@ const rejected = Promise.reject.bind(Promise); * contains a rejection, testData should be a function that returns that * rejection so as not to trigger the "unhandled rejection" error watcher. */ -function check(testType, testData, expected) { +function check(testType: GraphQLOutputType, testData: any, expected: any) { return async () => { const data = { test: testData }; - const dataType = new GraphQLObjectType({ + const dataType: GraphQLObjectType = new GraphQLObjectType({ name: 'DataType', fields: () => ({ test: { type: testType }, @@ -71,7 +70,7 @@ describe('Execute: Accepts any iterable as list value', () => { }), ); - function getArgs(...args) { + function getArgs(...args: Array) { return args; } diff --git a/src/execution/__tests__/mutations-test.js b/src/execution/__tests__/mutations-test.ts similarity index 99% rename from src/execution/__tests__/mutations-test.js rename to src/execution/__tests__/mutations-test.ts index 63b2411394..87d108ae8b 100644 --- a/src/execution/__tests__/mutations-test.js +++ b/src/execution/__tests__/mutations-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/execution/__tests__/nonnull-test.js b/src/execution/__tests__/nonnull-test.ts similarity index 99% rename from src/execution/__tests__/nonnull-test.js rename to src/execution/__tests__/nonnull-test.ts index 3312a1b275..bd4a7f97a0 100644 --- a/src/execution/__tests__/nonnull-test.js +++ b/src/execution/__tests__/nonnull-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -105,12 +103,12 @@ const schema = buildSchema(` } `); -function executeQuery(query, rootValue) { +function executeQuery(query: string, rootValue: Record) { return execute({ schema, document: parse(query), rootValue }); } // avoids also doing any nests -function patch(data) { +function patch(data: any) { return JSON.parse( JSON.stringify(data) .replace(/\bsync\b/g, 'promise') @@ -118,7 +116,10 @@ function patch(data) { ); } -async function executeSyncAndAsync(query, rootValue) { +async function executeSyncAndAsync( + query: string, + rootValue: Record, +) { const syncResult = await executeQuery(query, rootValue); const asyncResult = await executeQuery(patch(query), rootValue); diff --git a/src/execution/__tests__/resolve-test.js b/src/execution/__tests__/resolve-test.ts similarity index 89% rename from src/execution/__tests__/resolve-test.js rename to src/execution/__tests__/resolve-test.ts index cd1f13b8fb..2e1591cc0e 100644 --- a/src/execution/__tests__/resolve-test.js +++ b/src/execution/__tests__/resolve-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; import { GraphQLSchema } from '../../type/schema'; -import { GraphQLObjectType } from '../../type/definition'; +import { GraphQLObjectType, GraphQLFieldConfig } from '../../type/definition'; import { GraphQLInt, GraphQLString } from '../../type/scalars'; import { graphqlSync } from '../../graphql'; describe('Execute: resolve function', () => { - function testSchema(testField) { + function testSchema(testField: GraphQLFieldConfig) { return new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', @@ -59,11 +57,11 @@ describe('Execute: resolve function', () => { class Adder { _num: number; - constructor(num) { + constructor(num: number) { this._num = num; } - test({ addend1 }, context) { + test({ addend1 }: { addend1: number }, context: { addend2: number }) { return this._num + addend1 + context.addend2; } } @@ -94,7 +92,7 @@ describe('Execute: resolve function', () => { resolve: (source, args) => JSON.stringify([source, args]), }); - function execute(source, rootValue, contextValue) { + function execute(source: string, rootValue?: any, contextValue?: any) { return graphqlSync({ schema, source, rootValue, contextValue }); } diff --git a/src/execution/__tests__/schema-test.js b/src/execution/__tests__/schema-test.ts similarity index 94% rename from src/execution/__tests__/schema-test.js rename to src/execution/__tests__/schema-test.ts index 7c8115ce9c..b3c52f03e9 100644 --- a/src/execution/__tests__/schema-test.js +++ b/src/execution/__tests__/schema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -31,7 +29,7 @@ describe('Execute: Handles execution with a complex schema', () => { }, }); - const BlogAuthor = new GraphQLObjectType({ + const BlogAuthor: GraphQLObjectType = new GraphQLObjectType({ name: 'Author', fields: () => ({ id: { type: GraphQLString }, @@ -87,24 +85,24 @@ describe('Execute: Handles execution with a complex schema', () => { query: BlogQuery, }); - function article(id) { + function article(id: number) { return { id, isPublished: true, author: { id: 123, name: 'John Smith', - pic: (width, height) => getPic(123, width, height), + pic: (width: number, height: number) => getPic(123, width, height), recentArticle: () => article(1), }, - title: 'My Article ' + id, + title: `My Article ${id}`, body: 'This is a post', hidden: 'This data is not exposed in the schema', keywords: ['foo', 'bar', 1, true, null], }; } - function getPic(uid, width, height) { + function getPic(uid: number, width: number, height: number) { return { url: `cdn://${uid}`, width: `${width}`, diff --git a/src/execution/__tests__/sync-test.js b/src/execution/__tests__/sync-test.ts similarity index 99% rename from src/execution/__tests__/sync-test.js rename to src/execution/__tests__/sync-test.ts index 4c12f1fb24..32ca934d4c 100644 --- a/src/execution/__tests__/sync-test.js +++ b/src/execution/__tests__/sync-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/execution/__tests__/union-interface-test.js b/src/execution/__tests__/union-interface-test.ts similarity index 94% rename from src/execution/__tests__/union-interface-test.js rename to src/execution/__tests__/union-interface-test.ts index 602385edaf..d044553d13 100644 --- a/src/execution/__tests__/union-interface-test.js +++ b/src/execution/__tests__/union-interface-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -21,11 +19,11 @@ import { execute } from '../execute'; class Dog { name: string; barks: boolean; - mother: ?Dog; - father: ?Dog; + mother: Dog | null; + father: Dog | null; progeny: Array; - constructor(name, barks) { + constructor(name: string, barks: boolean) { this.name = name; this.barks = barks; this.mother = null; @@ -37,11 +35,11 @@ class Dog { class Cat { name: string; meows: boolean; - mother: ?Cat; - father: ?Cat; + mother: Cat | null; + father: Cat | null; progeny: Array; - constructor(name, meows) { + constructor(name: string, meows: boolean) { this.name = name; this.meows = meows; this.mother = null; @@ -52,10 +50,14 @@ class Cat { class Person { name: string; - pets: ?Array; - friends: ?Array; - - constructor(name, pets, friends) { + pets?: Array; + friends?: Array; + + constructor( + name: string, + pets?: Array, + friends?: Array, + ) { this.name = name; this.pets = pets; this.friends = friends; @@ -69,14 +71,14 @@ const NamedType = new GraphQLInterfaceType({ }, }); -const LifeType = new GraphQLInterfaceType({ +const LifeType: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Life', fields: () => ({ progeny: { type: GraphQLList(LifeType) }, }), }); -const MammalType = new GraphQLInterfaceType({ +const MammalType: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Mammal', interfaces: [LifeType], fields: () => ({ @@ -86,7 +88,7 @@ const MammalType = new GraphQLInterfaceType({ }), }); -const DogType = new GraphQLObjectType({ +const DogType: GraphQLObjectType = new GraphQLObjectType({ name: 'Dog', interfaces: [MammalType, LifeType, NamedType], fields: () => ({ @@ -99,7 +101,7 @@ const DogType = new GraphQLObjectType({ isTypeOf: (value) => value instanceof Dog, }); -const CatType = new GraphQLObjectType({ +const CatType: GraphQLObjectType = new GraphQLObjectType({ name: 'Cat', interfaces: [MammalType, LifeType, NamedType], fields: () => ({ @@ -129,7 +131,7 @@ const PetType = new GraphQLUnionType({ }, }); -const PersonType = new GraphQLObjectType({ +const PersonType: GraphQLObjectType = new GraphQLObjectType({ name: 'Person', interfaces: [NamedType, MammalType, LifeType], fields: () => ({ @@ -507,7 +509,7 @@ describe('Execute: Union and intersection types', () => { let encounteredSchema; let encounteredRootValue; - const NamedType2 = new GraphQLInterfaceType({ + const NamedType2: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Named', fields: { name: { type: GraphQLString }, diff --git a/src/execution/__tests__/variables-test.js b/src/execution/__tests__/variables-test.ts similarity index 96% rename from src/execution/__tests__/variables-test.js rename to src/execution/__tests__/variables-test.ts index f0ce6253a5..1d09581056 100644 --- a/src/execution/__tests__/variables-test.js +++ b/src/execution/__tests__/variables-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -18,10 +16,17 @@ import { GraphQLObjectType, GraphQLInputObjectType, GraphQLEnumType, + GraphQLFieldConfig, + GraphQLArgumentConfig, } from '../../type/definition'; import { execute } from '../execute'; import { getVariableValues } from '../values'; +import type { + StringValueNode, + VariableDefinitionNode, + OperationDefinitionNode, +} from '../../language/ast'; const TestComplexScalar = new GraphQLScalarType({ name: 'ComplexScalar', @@ -30,9 +35,10 @@ const TestComplexScalar = new GraphQLScalarType({ return 'DeserializedValue'; }, parseLiteral(ast) { - invariant(ast.value === 'SerializedValue'); + invariant((ast as StringValueNode).value === 'SerializedValue'); return 'DeserializedValue'; }, + serialize: () => 'SerializedValue', }); const TestInputObject = new GraphQLInputObjectType({ @@ -65,11 +71,13 @@ const TestEnum = new GraphQLEnumType({ }, }); -function fieldWithInputArg(inputArg) { +function fieldWithInputArg( + inputArg: GraphQLArgumentConfig, +): GraphQLFieldConfig { return { type: GraphQLString, args: { input: inputArg }, - resolve(_, args) { + resolve(_: any, args) { if ('input' in args) { return inspect(args.input); } @@ -116,7 +124,7 @@ const TestType = new GraphQLObjectType({ const schema = new GraphQLSchema({ query: TestType }); -function executeQuery(query, variableValues) { +function executeQuery(query: string, variableValues?: Record) { const document = parse(query); return execute({ schema, document, variableValues }); } @@ -1005,12 +1013,13 @@ describe('Execute: Handles inputs', () => { const operation = doc.definitions[0]; invariant(operation.kind === Kind.OPERATION_DEFINITION); - const { variableDefinitions } = operation; + const variableDefinitions = + (operation as OperationDefinitionNode).variableDefinitions ?? null; invariant(variableDefinitions != null); const inputValue = { input: [0, 1, 2] }; - function invalidValueError(value, index) { + function invalidValueError(value: number, index: number) { return { message: `Variable "$input" got invalid value ${value} at "input[${index}]"; String cannot represent a non string value: ${value}`, locations: [{ line: 2, column: 14 }], @@ -1018,7 +1027,11 @@ describe('Execute: Handles inputs', () => { } it('return all errors by default', () => { - const result = getVariableValues(schema, variableDefinitions, inputValue); + const result = getVariableValues( + schema, + variableDefinitions as Array, + inputValue, + ); expect(result).to.deep.equal({ errors: [ @@ -1032,7 +1045,7 @@ describe('Execute: Handles inputs', () => { it('when maxErrors is equal to number of errors', () => { const result = getVariableValues( schema, - variableDefinitions, + variableDefinitions as Array, inputValue, { maxErrors: 3 }, ); @@ -1049,7 +1062,7 @@ describe('Execute: Handles inputs', () => { it('when maxErrors is less than number of errors', () => { const result = getVariableValues( schema, - variableDefinitions, + variableDefinitions as Array, inputValue, { maxErrors: 2 }, ); diff --git a/src/jsutils/ObjMap.d.ts b/src/jsutils/ObjMap.d.ts new file mode 100644 index 0000000000..bc7a6362cf --- /dev/null +++ b/src/jsutils/ObjMap.d.ts @@ -0,0 +1,15 @@ +export interface ObjMap { + [key: string]: T; + __proto__: never; +} + +export type ObjMapLike = ObjMap | { [key: string]: T }; + +export interface ReadOnlyObjMap { + readonly [key: string]: T; + __proto__: never; +} + +export type ReadOnlyObjMapLike = + | ReadOnlyObjMap + | { readonly [key: string]: T }; diff --git a/src/jsutils/__tests__/didYouMean-test.js b/src/jsutils/__tests__/didYouMean-test.ts similarity index 98% rename from src/jsutils/__tests__/didYouMean-test.js rename to src/jsutils/__tests__/didYouMean-test.ts index ff79ad757a..70a4ac5237 100644 --- a/src/jsutils/__tests__/didYouMean-test.js +++ b/src/jsutils/__tests__/didYouMean-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/jsutils/__tests__/identityFunc-test.js b/src/jsutils/__tests__/identityFunc-test.ts similarity index 96% rename from src/jsutils/__tests__/identityFunc-test.js rename to src/jsutils/__tests__/identityFunc-test.ts index 438f02b2c9..8c7eff39bc 100644 --- a/src/jsutils/__tests__/identityFunc-test.js +++ b/src/jsutils/__tests__/identityFunc-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/jsutils/__tests__/inspect-test.js b/src/jsutils/__tests__/inspect-test.ts similarity index 94% rename from src/jsutils/__tests__/inspect-test.js rename to src/jsutils/__tests__/inspect-test.ts index 887c92fce1..8615992826 100644 --- a/src/jsutils/__tests__/inspect-test.js +++ b/src/jsutils/__tests__/inspect-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -142,7 +140,7 @@ describe('inspect', () => { }); it('detect circular objects', () => { - const obj = {}; + const obj: { [key: string]: any } = {}; obj.self = obj; obj.deepSelf = { self: obj }; @@ -150,13 +148,13 @@ describe('inspect', () => { '{ self: [Circular], deepSelf: { self: [Circular] } }', ); - const array = []; + const array: Array = []; array[0] = array; array[1] = [array]; expect(inspect(array)).to.equal('[[Circular], [[Circular]]]'); - const mixed = { array: [] }; + const mixed: { array: Array } = { array: [] }; mixed.array[0] = mixed; expect(inspect(mixed)).to.equal('{ array: [[Circular]] }'); @@ -183,11 +181,12 @@ describe('inspect', () => { expect(inspect([[new Foo()]])).to.equal('[[[Foo]]]'); - (Foo.prototype: any)[Symbol.toStringTag] = 'Bar'; + (Foo.prototype as any)[Symbol.toStringTag] = 'Bar'; expect(inspect([[new Foo()]])).to.equal('[[[Bar]]]'); + // @ts-expect-error - invalid creation due to `any` type const objectWithoutClassName = new (function () { - // eslint-disable-next-line no-invalid-this + // @ts-expect-error- invalid usage of `this` this.foo = 1; })(); expect(inspect([[objectWithoutClassName]])).to.equal('[[[Object]]]'); diff --git a/src/jsutils/__tests__/instanceOf-test.js b/src/jsutils/__tests__/instanceOf-test.ts similarity index 97% rename from src/jsutils/__tests__/instanceOf-test.js rename to src/jsutils/__tests__/instanceOf-test.ts index b91f03f9ce..17a8d4e46d 100644 --- a/src/jsutils/__tests__/instanceOf-test.js +++ b/src/jsutils/__tests__/instanceOf-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/jsutils/__tests__/invariant-test.js b/src/jsutils/__tests__/invariant-test.ts similarity index 95% rename from src/jsutils/__tests__/invariant-test.js rename to src/jsutils/__tests__/invariant-test.ts index 762143076a..97c293596e 100644 --- a/src/jsutils/__tests__/invariant-test.js +++ b/src/jsutils/__tests__/invariant-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/jsutils/__tests__/isCollection-test.js b/src/jsutils/__tests__/isCollection-test.ts similarity index 92% rename from src/jsutils/__tests__/isCollection-test.js rename to src/jsutils/__tests__/isCollection-test.ts index d42f38af11..347c632241 100644 --- a/src/jsutils/__tests__/isCollection-test.js +++ b/src/jsutils/__tests__/isCollection-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -11,7 +9,7 @@ describe('isCollection', () => { expect(isCollection([])).to.equal(true); expect(isCollection(new Int8Array(1))).to.equal(true); - // eslint-disable-next-line no-new-wrappers + // FIXME: No need to use `new` for creating a String expect(isCollection(new String('ABC'))).to.equal(true); function getArguments() { @@ -48,12 +46,10 @@ describe('isCollection', () => { expect(isCollection(1)).to.equal(false); expect(isCollection(0)).to.equal(false); expect(isCollection(NaN)).to.equal(false); - // eslint-disable-next-line no-new-wrappers expect(isCollection(new Number(123))).to.equal(false); expect(isCollection(true)).to.equal(false); expect(isCollection(false)).to.equal(false); - // eslint-disable-next-line no-new-wrappers expect(isCollection(new Boolean(true))).to.equal(false); expect(isCollection({})).to.equal(false); diff --git a/src/jsutils/__tests__/isObjectLike-test.js b/src/jsutils/__tests__/isObjectLike-test.ts similarity index 97% rename from src/jsutils/__tests__/isObjectLike-test.js rename to src/jsutils/__tests__/isObjectLike-test.ts index 5827023f14..724d3ab10c 100644 --- a/src/jsutils/__tests__/isObjectLike-test.js +++ b/src/jsutils/__tests__/isObjectLike-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/jsutils/__tests__/suggestionList-test.js b/src/jsutils/__tests__/suggestionList-test.ts similarity index 96% rename from src/jsutils/__tests__/suggestionList-test.js rename to src/jsutils/__tests__/suggestionList-test.ts index e9316f6393..b94dc7547f 100644 --- a/src/jsutils/__tests__/suggestionList-test.js +++ b/src/jsutils/__tests__/suggestionList-test.ts @@ -1,11 +1,9 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; import suggestionList from '../suggestionList'; -function expectSuggestions(input, options) { +function expectSuggestions(input: string, options: ReadonlyArray) { return expect(suggestionList(input, options)); } diff --git a/src/jsutils/__tests__/toObjMap-test.js b/src/jsutils/__tests__/toObjMap-test.ts similarity index 90% rename from src/jsutils/__tests__/toObjMap-test.js rename to src/jsutils/__tests__/toObjMap-test.ts index 51b6f81128..097d28f06f 100644 --- a/src/jsutils/__tests__/toObjMap-test.js +++ b/src/jsutils/__tests__/toObjMap-test.ts @@ -1,13 +1,10 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; import toObjMap from '../toObjMap'; -import { type ObjMapLike } from '../ObjMap'; +import { ObjMapLike } from '../ObjMap'; -// Workaround to make both ESLint and Flow happy -const __proto__: string = '__proto__'; +const __proto__ = '__proto__'; describe('toObjMap', () => { it('convert empty object to ObjMap', () => { diff --git a/src/jsutils/didYouMean.d.ts b/src/jsutils/didYouMean.d.ts new file mode 100644 index 0000000000..ceac122303 --- /dev/null +++ b/src/jsutils/didYouMean.d.ts @@ -0,0 +1,4 @@ +export default function didYouMean( + firstArg: string | ReadonlyArray, + secondArg?: ReadonlyArray, +): string; diff --git a/src/jsutils/identityFunc.d.ts b/src/jsutils/identityFunc.d.ts new file mode 100644 index 0000000000..af766f2dbb --- /dev/null +++ b/src/jsutils/identityFunc.d.ts @@ -0,0 +1,4 @@ +/** + * Returns the first argument it receives. + */ +export default function identityFunc(x?: T): T; diff --git a/src/jsutils/inspect.d.ts b/src/jsutils/inspect.d.ts new file mode 100644 index 0000000000..e4bb5ada4f --- /dev/null +++ b/src/jsutils/inspect.d.ts @@ -0,0 +1 @@ +export default function inspect(value: any): string; diff --git a/src/jsutils/instanceOf.d.ts b/src/jsutils/instanceOf.d.ts new file mode 100644 index 0000000000..e1312be347 --- /dev/null +++ b/src/jsutils/instanceOf.d.ts @@ -0,0 +1 @@ +export default function instanceOf(value: any, constructor: any): boolean; diff --git a/src/jsutils/invariant.d.ts b/src/jsutils/invariant.d.ts new file mode 100644 index 0000000000..441b413953 --- /dev/null +++ b/src/jsutils/invariant.d.ts @@ -0,0 +1 @@ +export default function invariant(condition: any, message?: string): void; diff --git a/src/jsutils/isCollection.d.ts b/src/jsutils/isCollection.d.ts new file mode 100644 index 0000000000..506326c2fc --- /dev/null +++ b/src/jsutils/isCollection.d.ts @@ -0,0 +1 @@ +export default function isCollection(obj: any): boolean; diff --git a/src/jsutils/isObjectLike.d.ts b/src/jsutils/isObjectLike.d.ts new file mode 100644 index 0000000000..05e69785b3 --- /dev/null +++ b/src/jsutils/isObjectLike.d.ts @@ -0,0 +1 @@ +export default function isObjectLike(value: any): boolean; diff --git a/src/jsutils/nodejsCustomInspectSymbol.d.ts b/src/jsutils/nodejsCustomInspectSymbol.d.ts new file mode 100644 index 0000000000..6c22ea3b3d --- /dev/null +++ b/src/jsutils/nodejsCustomInspectSymbol.d.ts @@ -0,0 +1,3 @@ +declare const nodejsCustomInspectSymbol: symbol | undefined; + +export default nodejsCustomInspectSymbol; diff --git a/src/jsutils/suggestionList.d.ts b/src/jsutils/suggestionList.d.ts new file mode 100644 index 0000000000..560c1c5355 --- /dev/null +++ b/src/jsutils/suggestionList.d.ts @@ -0,0 +1,4 @@ +export default function suggestionList( + input: string, + options: ReadonlyArray, +): Array; diff --git a/src/jsutils/toObjMap.d.ts b/src/jsutils/toObjMap.d.ts new file mode 100644 index 0000000000..b17aecfaf5 --- /dev/null +++ b/src/jsutils/toObjMap.d.ts @@ -0,0 +1,13 @@ +import { + ObjMap, + ObjMapLike, + ReadOnlyObjMap, + ReadOnlyObjMapLike, +} from './ObjMap'; + +// eslint-disable-next-line import/export +export default function toObjMap(obj: ObjMapLike): ObjMap; +// eslint-disable-next-line import/export +export default function toObjMap( + obj: ReadOnlyObjMapLike, +): ReadOnlyObjMap; diff --git a/src/language/__tests__/.blockString-test.js.swp b/src/language/__tests__/.blockString-test.js.swp deleted file mode 100644 index bbad20578d..0000000000 Binary files a/src/language/__tests__/.blockString-test.js.swp and /dev/null differ diff --git a/src/language/__tests__/blockString-fuzz.js b/src/language/__tests__/blockString-fuzz.ts similarity index 92% rename from src/language/__tests__/blockString-fuzz.js rename to src/language/__tests__/blockString-fuzz.ts index 7f11302e6d..ddd18d92a8 100644 --- a/src/language/__tests__/blockString-fuzz.js +++ b/src/language/__tests__/blockString-fuzz.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import dedent from '../../__testUtils__/dedent'; @@ -12,12 +10,12 @@ import { Lexer } from '../lexer'; import { Source } from '../source'; import { printBlockString } from '../blockString'; -function lexValue(str) { +function lexValue(str: string): string { const lexer = new Lexer(new Source(str)); const value = lexer.advance().value; invariant(lexer.advance().kind === '', 'Expected EOF'); - return value; + return value as string; } describe('printBlockString', () => { @@ -28,9 +26,10 @@ describe('printBlockString', () => { allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'], maxLength: 7, })) { + // FIXME: Prefer string literal over plus operand const testStr = '"""' + fuzzStr + '"""'; - let testValue; + let testValue: string; try { testValue = lexValue(testStr); } catch (e) { diff --git a/src/language/__tests__/blockString-test.js b/src/language/__tests__/blockString-test.ts similarity index 99% rename from src/language/__tests__/blockString-test.js rename to src/language/__tests__/blockString-test.ts index efd7abbd45..28a2fb391e 100644 --- a/src/language/__tests__/blockString-test.js +++ b/src/language/__tests__/blockString-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,7 +7,7 @@ import { printBlockString, } from '../blockString'; -function joinLines(...args) { +function joinLines(...args: Array) { return args.join('\n'); } diff --git a/src/language/__tests__/lexer-test.js b/src/language/__tests__/lexer-test.ts similarity index 98% rename from src/language/__tests__/lexer-test.js rename to src/language/__tests__/lexer-test.ts index 14fa0bba4b..2435e4ae38 100644 --- a/src/language/__tests__/lexer-test.js +++ b/src/language/__tests__/lexer-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { inspect as nodeInspect } from 'util'; import { expect } from 'chai'; @@ -13,20 +11,21 @@ import { GraphQLError } from '../../error/GraphQLError'; import { Source } from '../source'; import { TokenKind } from '../tokenKind'; +import { Token } from '../ast'; import { Lexer, isPunctuatorTokenKind } from '../lexer'; -function lexOne(str) { +function lexOne(str: string) { const lexer = new Lexer(new Source(str)); return lexer.advance(); } -function lexSecond(str) { +function lexSecond(str: string) { const lexer = new Lexer(new Source(str)); lexer.advance(); return lexer.advance(); } -function expectSyntaxError(text) { +function expectSyntaxError(text: string) { return expect(() => lexSecond(text)).to.throw(); } @@ -887,7 +886,7 @@ describe('Lexer', () => { expect(endToken.next).to.equal(null); const tokens = []; - for (let tok = startToken; tok; tok = tok.next) { + for (let tok: Token | null = startToken; tok; tok = tok.next) { if (tokens.length) { // Tokens are double-linked, prev should point to last seen token. expect(tok.prev).to.equal(tokens[tokens.length - 1]); @@ -907,7 +906,7 @@ describe('Lexer', () => { }); describe('isPunctuatorTokenKind', () => { - function isPunctuatorToken(text) { + function isPunctuatorToken(text: string) { return isPunctuatorTokenKind(lexOne(text).kind); } diff --git a/src/language/__tests__/parser-test.js b/src/language/__tests__/parser-test.ts similarity index 99% rename from src/language/__tests__/parser-test.js rename to src/language/__tests__/parser-test.ts index cf199e479c..0884d9ad28 100644 --- a/src/language/__tests__/parser-test.js +++ b/src/language/__tests__/parser-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { inspect as nodeInspect } from 'util'; import { expect } from 'chai'; @@ -18,18 +16,18 @@ import { kitchenSinkQuery } from '../../__fixtures__/index'; import toJSONDeep from './toJSONDeep'; -function expectSyntaxError(text) { +function expectSyntaxError(text: string) { return expect(() => parse(text)).to.throw(); } describe('Parser', () => { it('asserts that a source to parse was provided', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - no source expect(() => parse()).to.throw('Must provide Source. Received: undefined.'); }); it('asserts that an invalid source to parse was provided', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid source expect(() => parse({})).to.throw('Must provide Source. Received: {}.'); }); diff --git a/src/language/__tests__/predicates-test.js b/src/language/__tests__/predicates-test.ts similarity index 95% rename from src/language/__tests__/predicates-test.js rename to src/language/__tests__/predicates-test.ts index 0f01049f85..e718a68659 100644 --- a/src/language/__tests__/predicates-test.js +++ b/src/language/__tests__/predicates-test.ts @@ -1,10 +1,8 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; import { Kind } from '../kinds'; -import { type ASTNode } from '../ast'; +import { ASTNode } from '../ast'; import { isDefinitionNode, isExecutableDefinitionNode, @@ -18,10 +16,10 @@ import { } from '../predicates'; const allASTNodes: Array = Object.values(Kind).map( - (kind) => ({ kind }: any), + (kind) => (({ kind } as any) as ASTNode), ); -function filterNodes(predicate: (ASTNode) => boolean): Array { +function filterNodes(predicate: (arg: ASTNode) => boolean): Array { return allASTNodes.filter(predicate).map(({ kind }) => kind); } diff --git a/src/language/__tests__/printLocation-test.js b/src/language/__tests__/printLocation-test.ts similarity index 99% rename from src/language/__tests__/printLocation-test.js rename to src/language/__tests__/printLocation-test.ts index 146c9e4541..2fbcdcca4e 100644 --- a/src/language/__tests__/printLocation-test.js +++ b/src/language/__tests__/printLocation-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/language/__tests__/printer-test.js b/src/language/__tests__/printer-test.ts similarity index 95% rename from src/language/__tests__/printer-test.js rename to src/language/__tests__/printer-test.ts index d64a5bfa3a..fcb0a8f925 100644 --- a/src/language/__tests__/printer-test.js +++ b/src/language/__tests__/printer-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,6 +7,7 @@ import { parse } from '../parser'; import { print } from '../printer'; import { kitchenSinkQuery } from '../../__fixtures__/index'; +import { FieldNode } from '../ast'; describe('Printer: Query document', () => { it('does not alter ast', () => { @@ -19,13 +18,16 @@ describe('Printer: Query document', () => { }); it('prints minimal ast', () => { - const ast = { kind: 'Field', name: { kind: 'Name', value: 'foo' } }; + const ast: FieldNode = { + kind: 'Field', + name: { kind: 'Name', value: 'foo' }, + }; expect(print(ast)).to.equal('foo'); }); it('produces helpful error messages', () => { const badAST = { random: 'Data' }; - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid AST structure expect(() => print(badAST)).to.throw( 'Invalid AST Node: { random: "Data" }.', ); @@ -114,7 +116,6 @@ describe('Printer: Query document', () => { const printed = print(parse(kitchenSinkQuery)); expect(printed).to.equal( - // $FlowFixMe dedent(String.raw` query queryName($foo: ComplexType, $site: Site = MOBILE) @onQuery { whoever123is: node(id: [123, 456]) { diff --git a/src/language/__tests__/schema-parser-test.js b/src/language/__tests__/schema-parser-test.ts similarity index 96% rename from src/language/__tests__/schema-parser-test.js rename to src/language/__tests__/schema-parser-test.ts index ec29875d39..06328207bb 100644 --- a/src/language/__tests__/schema-parser-test.js +++ b/src/language/__tests__/schema-parser-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,33 +7,55 @@ import { kitchenSinkSDL } from '../../__fixtures__/index'; import { parse } from '../parser'; +import { + NamedTypeNode, + NameNode, + Location, + FieldDefinitionNode, + TypeNode, + InputValueDefinitionNode, + EnumValueDefinitionNode, +} from '../ast'; + import toJSONDeep from './toJSONDeep'; -function expectSyntaxError(text) { +function expectSyntaxError(text: string) { return expect(() => parse(text)).to.throw(); } -function typeNode(name, loc) { +function typeNode( + name: string, + loc: { start: number; end: number }, +): NamedTypeNode { return { kind: 'NamedType', name: nameNode(name, loc), - loc, + loc: loc as Location, }; } -function nameNode(name, loc) { +function nameNode(name: string, loc: { start: number; end: number }): NameNode { return { kind: 'Name', value: name, - loc, + loc: loc as Location, }; } -function fieldNode(name, type, loc) { +function fieldNode( + name: NameNode, + type: TypeNode, + loc: { start: number; end: number }, +): FieldDefinitionNode { return fieldNodeWithArgs(name, type, [], loc); } -function fieldNodeWithArgs(name, type, args, loc) { +function fieldNodeWithArgs( + name: NameNode, + type: TypeNode, + args: Array, + loc: { start: number; end: number }, +): FieldDefinitionNode { return { kind: 'FieldDefinition', description: undefined, @@ -43,21 +63,29 @@ function fieldNodeWithArgs(name, type, args, loc) { arguments: args, type, directives: [], - loc, + loc: loc as Location, }; } -function enumValueNode(name, loc) { +function enumValueNode( + name: string, + loc: { start: number; end: number }, +): EnumValueDefinitionNode { return { kind: 'EnumValueDefinition', name: nameNode(name, loc), description: undefined, directives: [], - loc, + loc: loc as Location, }; } -function inputValueNode(name, type, defaultValue, loc) { +function inputValueNode( + name: NameNode, + type: TypeNode, + defaultValue: any, + loc: { start: number; end: number }, +): InputValueDefinitionNode { return { kind: 'InputValueDefinition', name, @@ -65,7 +93,7 @@ function inputValueNode(name, type, defaultValue, loc) { type, defaultValue, directives: [], - loc, + loc: loc as Location, }; } @@ -455,7 +483,7 @@ describe('Schema Parser', () => { { kind: 'NonNullType', type: typeNode('String', { start: 22, end: 28 }), - loc: { start: 22, end: 29 }, + loc: { start: 22, end: 29 } as Location, }, { start: 15, end: 29 }, ), @@ -811,7 +839,7 @@ describe('Schema Parser', () => { { kind: 'ListType', type: typeNode('String', { start: 30, end: 36 }), - loc: { start: 29, end: 37 }, + loc: { start: 29, end: 37 } as Location, }, undefined, { start: 21, end: 37 }, diff --git a/src/language/__tests__/schema-printer-test.js b/src/language/__tests__/schema-printer-test.ts similarity index 97% rename from src/language/__tests__/schema-printer-test.js rename to src/language/__tests__/schema-printer-test.ts index 79695a5d77..54cdc09021 100644 --- a/src/language/__tests__/schema-printer-test.js +++ b/src/language/__tests__/schema-printer-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,10 +7,11 @@ import { parse } from '../parser'; import { print } from '../printer'; import { kitchenSinkSDL } from '../../__fixtures__/index'; +import { ScalarTypeDefinitionNode } from '../ast'; describe('Printer: SDL document', () => { it('prints minimal ast', () => { - const ast = { + const ast: ScalarTypeDefinitionNode = { kind: 'ScalarTypeDefinition', name: { kind: 'Name', value: 'foo' }, }; @@ -21,7 +20,7 @@ describe('Printer: SDL document', () => { it('produces helpful error messages', () => { const badAST = { random: 'Data' }; - // $DisableFlowOnNegativeTest + // @ts-expect-error - bad AST expect(() => print(badAST)).to.throw( 'Invalid AST Node: { random: "Data" }.', ); diff --git a/src/language/__tests__/source-test.js b/src/language/__tests__/source-test.ts similarity index 92% rename from src/language/__tests__/source-test.js rename to src/language/__tests__/source-test.ts index 64b1a89d03..1e7d24601c 100644 --- a/src/language/__tests__/source-test.js +++ b/src/language/__tests__/source-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -13,7 +11,7 @@ describe('Source', () => { }); it('rejects invalid locationOffset', () => { - function createSource(locationOffset) { + function createSource(locationOffset: { line: number; column: number }) { return new Source('', '', locationOffset); } diff --git a/src/language/__tests__/toJSONDeep.js b/src/language/__tests__/toJSONDeep.ts similarity index 83% rename from src/language/__tests__/toJSONDeep.js rename to src/language/__tests__/toJSONDeep.ts index 5405b99ce1..7a59a9a01b 100644 --- a/src/language/__tests__/toJSONDeep.js +++ b/src/language/__tests__/toJSONDeep.ts @@ -1,18 +1,15 @@ -// @flow strict - import isObjectLike from '../../jsutils/isObjectLike'; /** * Deeply transforms an arbitrary value to a JSON-safe value by calling toJSON * on any nested value which defines it. */ -export default function toJSONDeep(value: mixed): mixed { +export default function toJSONDeep(value: any): any { if (!isObjectLike(value)) { return value; } if (typeof value.toJSON === 'function') { - // $FlowFixMe(>=0.90.0) return value.toJSON(); } diff --git a/src/language/__tests__/visitor-test.js b/src/language/__tests__/visitor-test.ts similarity index 95% rename from src/language/__tests__/visitor-test.js rename to src/language/__tests__/visitor-test.ts index b847c8b5d2..8873ef3a9d 100644 --- a/src/language/__tests__/visitor-test.js +++ b/src/language/__tests__/visitor-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -10,8 +8,13 @@ import { parse } from '../parser'; import { visit, visitInParallel, BREAK, QueryDocumentKeys } from '../visitor'; import { kitchenSinkQuery } from '../../__fixtures__/index'; +import { ASTNode, SelectionSetNode } from '../ast'; -function checkVisitorFnArgs(ast, args, isEdited) { +function checkVisitorFnArgs( + ast: ASTNode, + args: IArguments, + isEdited?: boolean, +) { const [node, key, parent, path, ancestors] = args; expect(node).to.be.an.instanceof(Object); @@ -43,7 +46,7 @@ function checkVisitorFnArgs(ast, args, isEdited) { for (let i = 0; i < ancestors.length; ++i) { expect(ancestors[i]).to.equal(currentNode); - currentNode = currentNode[path[i]]; + currentNode = (currentNode as any)[path[i]]; expect(currentNode).to.not.equal(undefined); } @@ -52,13 +55,13 @@ function checkVisitorFnArgs(ast, args, isEdited) { } } -function getValue(node) { +function getValue(node: any): string | undefined { return node.value != null ? node.value : undefined; } describe('Visitor', () => { it('validates path argument', () => { - const visited = []; + const visited: Array<[string, Array]> = []; const ast = parse('{ a }', { noLocation: true }); @@ -89,7 +92,9 @@ describe('Visitor', () => { it('validates ancestors argument', () => { const ast = parse('{ a }', { noLocation: true }); - const visitedNodes = []; + const visitedNodes: Array< + ASTNode | ReadonlyArray | undefined + > = []; visit(ast, { enter(node, key, parent, _path, ancestors) { @@ -117,7 +122,7 @@ describe('Visitor', () => { it('allows visiting only specified nodes', () => { const ast = parse('{ a }', { noLocation: true }); - const visited = []; + const visited: Array<[string, string]> = []; visit(ast, { enter: { @@ -140,8 +145,7 @@ describe('Visitor', () => { it('allows editing a node both on enter and on leave', () => { const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); - - let selectionSet; + let selectionSet: SelectionSetNode; const editedAST = visit(ast, { OperationDefinition: { @@ -267,7 +271,7 @@ describe('Visitor', () => { }); it('visits edited node', () => { - const addedField = { + const addedField: ASTNode = { kind: 'Field', name: { kind: 'Name', @@ -284,7 +288,7 @@ describe('Visitor', () => { if (node.kind === 'Field' && node.name.value === 'a') { return { kind: 'Field', - selectionSet: [addedField].concat(node.selectionSet), + selectionSet: [addedField, node.selectionSet], }; } if (node === addedField) { @@ -297,7 +301,7 @@ describe('Visitor', () => { }); it('allows skipping a sub-tree', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }', { noLocation: true }); visit(ast, { @@ -335,7 +339,7 @@ describe('Visitor', () => { }); it('allows early exit while visiting', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }', { noLocation: true }); visit(ast, { @@ -370,7 +374,7 @@ describe('Visitor', () => { }); it('allows early exit while leaving', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }', { noLocation: true }); visit(ast, { @@ -407,7 +411,7 @@ describe('Visitor', () => { }); it('allows a named functions visitor API', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }', { noLocation: true }); visit(ast, { @@ -444,7 +448,7 @@ describe('Visitor', () => { noLocation: true, experimentalFragmentVariables: true, }); - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; visit(ast, { enter(node) { @@ -491,11 +495,16 @@ describe('Visitor', () => { it('visits kitchen sink', () => { const ast = parse(kitchenSinkQuery); - const visited = []; - const argsStack = []; + const visited: Array<[ + string, + string, + string | number | undefined, + string | undefined, + ]> = []; + const argsStack: Array> = []; visit(ast, { - enter(node, key, parent) { + enter(node, key, parent: any) { visited.push([ 'enter', node.kind, @@ -507,7 +516,7 @@ describe('Visitor', () => { argsStack.push([...arguments]); }, - leave(node, key, parent) { + leave(node, key, parent: any) { visited.push([ 'leave', node.kind, @@ -868,7 +877,8 @@ describe('Visitor', () => { describe('Support for custom AST nodes', () => { const customAST = parse('{ a }'); - (customAST: any).definitions[0].selectionSet.selections.push({ + // @ts-expect-error - trying to access union of objects, but we know it's there + customAST.definitions[0].selectionSet.selections.push({ kind: 'CustomField', name: { kind: 'Name', @@ -889,7 +899,7 @@ describe('Visitor', () => { }); it('does not traverse unknown node kinds', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; visit(customAST, { enter(node) { visited.push(['enter', node.kind, getValue(node)]); @@ -917,18 +927,21 @@ describe('Visitor', () => { it('does traverse unknown node kinds with visitor keys', () => { const customQueryDocumentKeys = { ...QueryDocumentKeys }; - (customQueryDocumentKeys: any).CustomField = ['name', 'selectionSet']; + (customQueryDocumentKeys as any).CustomField = ['name', 'selectionSet']; - const visited = []; - const visitor = { - enter(node) { - visited.push(['enter', node.kind, getValue(node)]); - }, - leave(node) { - visited.push(['leave', node.kind, getValue(node)]); + const visited: Array<[string, string, string | undefined]> = []; + visit( + customAST, + { + enter(node) { + visited.push(['enter', node.kind, getValue(node)]); + }, + leave(node) { + visited.push(['leave', node.kind, getValue(node)]); + }, }, - }; - visit(customAST, visitor, customQueryDocumentKeys); + customQueryDocumentKeys, + ); expect(visited).to.deep.equal([ ['enter', 'Document', undefined], @@ -959,7 +972,7 @@ describe('Visitor', () => { // Note: nearly identical to the above test of the same test but // using visitInParallel. it('allows skipping a sub-tree', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }'); visit( @@ -1002,7 +1015,7 @@ describe('Visitor', () => { }); it('allows skipping different sub-trees', () => { - const visited = []; + const visited: Array<[string, string, string, string | undefined]> = []; const ast = parse('{ a { x }, b { y} }'); visit( @@ -1078,7 +1091,7 @@ describe('Visitor', () => { // Note: nearly identical to the above test of the same test but // using visitInParallel. it('allows early exit while visiting', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }'); visit( @@ -1118,7 +1131,7 @@ describe('Visitor', () => { }); it('allows early exit from different points', () => { - const visited = []; + const visited: Array<[string, string, string, string | undefined]> = []; const ast = parse('{ a { y }, b { x } }'); visit( @@ -1180,7 +1193,7 @@ describe('Visitor', () => { // Note: nearly identical to the above test of the same test but // using visitInParallel. it('allows early exit while leaving', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b { x }, c }'); visit( @@ -1221,7 +1234,7 @@ describe('Visitor', () => { }); it('allows early exit from leaving different points', () => { - const visited = []; + const visited: Array<[string, string, string, string | undefined]> = []; const ast = parse('{ a { y }, b { x } }'); visit( @@ -1297,7 +1310,7 @@ describe('Visitor', () => { }); it('allows for editing on enter', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); const editedAST = visit( @@ -1361,7 +1374,7 @@ describe('Visitor', () => { }); it('allows for editing on leave', () => { - const visited = []; + const visited: Array<[string, string, string | undefined]> = []; const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); const editedAST = visit( diff --git a/src/language/lexer.d.ts b/src/language/lexer.d.ts index 40dbf9a6b2..f85c4bda52 100644 --- a/src/language/lexer.d.ts +++ b/src/language/lexer.d.ts @@ -1,6 +1,6 @@ import { Token } from './ast'; -import { Source } from './source'; import { TokenKindEnum } from './tokenKind'; +import { Source } from './source'; /** * Given a Source object, this returns a Lexer for that source. diff --git a/src/subscription/__tests__/eventEmitterAsyncIterator-test.js b/src/subscription/__tests__/eventEmitterAsyncIterator-test.ts similarity index 90% rename from src/subscription/__tests__/eventEmitterAsyncIterator-test.js rename to src/subscription/__tests__/eventEmitterAsyncIterator-test.ts index 4e5ee51f36..55f0e0a523 100644 --- a/src/subscription/__tests__/eventEmitterAsyncIterator-test.js +++ b/src/subscription/__tests__/eventEmitterAsyncIterator-test.ts @@ -1,6 +1,4 @@ -// @flow strict - -import EventEmitter from 'events'; +import { EventEmitter } from 'events'; import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -11,7 +9,7 @@ describe('eventEmitterAsyncIterator', () => { it('subscribe async-iterator mock', async () => { // Create an AsyncIterator from an EventEmitter const emitter = new EventEmitter(); - const iterator = eventEmitterAsyncIterator(emitter, 'publish'); + const iterator = eventEmitterAsyncIterator(emitter, 'publish'); // Queue up publishes expect(emitter.emit('publish', 'Apple')).to.equal(true); @@ -43,8 +41,9 @@ describe('eventEmitterAsyncIterator', () => { const i5 = iterator.next().then((x) => x); // Terminate emitter - // $FlowFixMe - await iterator.return(); + if (iterator.return) { + await iterator.return(); + } // Publish is not caught after terminate expect(emitter.emit('publish', 'Fig')).to.equal(false); diff --git a/src/subscription/__tests__/eventEmitterAsyncIterator.js b/src/subscription/__tests__/eventEmitterAsyncIterator.ts similarity index 65% rename from src/subscription/__tests__/eventEmitterAsyncIterator.js rename to src/subscription/__tests__/eventEmitterAsyncIterator.ts index c1c5abbfa7..9fd32c91ae 100644 --- a/src/subscription/__tests__/eventEmitterAsyncIterator.js +++ b/src/subscription/__tests__/eventEmitterAsyncIterator.ts @@ -1,23 +1,25 @@ -// @flow strict - -import type EventEmitter from 'events'; +import { EventEmitter } from 'events'; /** * Create an AsyncIterator from an EventEmitter. Useful for mocking a * PubSub system for tests. */ -export default function eventEmitterAsyncIterator( +export default function eventEmitterAsyncIterator( eventEmitter: EventEmitter, eventName: string, -): AsyncIterator { - const pullQueue = []; - const pushQueue = []; +): AsyncIterator { + const pullQueue: Array<(...args: Array) => void> = []; + const pushQueue: Array = []; let listening = true; eventEmitter.addListener(eventName, pushValue); - function pushValue(event) { + function pushValue(event: T) { if (pullQueue.length !== 0) { - pullQueue.shift()({ value: event, done: false }); + const item = pullQueue.shift(); + + if (item) { + item({ value: event, done: false }); + } } else { pushQueue.push(event); } @@ -45,23 +47,20 @@ export default function eventEmitterAsyncIterator( } } - /* TODO: Flow doesn't support symbols as keys: - https://github.com/facebook/flow/issues/3258 */ - return ({ + return { next() { - return listening ? pullValue() : this.return(); + return listening ? pullValue() : (this as any).return(); }, return() { emptyQueue(); return Promise.resolve({ value: undefined, done: true }); }, - throw(error) { + throw(error: Error) { emptyQueue(); return Promise.reject(error); }, - // $FlowFixMe Blocked by https://github.com/facebook/flow/issues/3258 - [Symbol.asyncIterator]() { + [Symbol.asyncIterator as any]() { return this; }, - }: any); + }; } diff --git a/src/subscription/__tests__/mapAsyncIterator-test.js b/src/subscription/__tests__/mapAsyncIterator-test.ts similarity index 85% rename from src/subscription/__tests__/mapAsyncIterator-test.js rename to src/subscription/__tests__/mapAsyncIterator-test.ts index 931a3de6b7..5b7b3792f0 100644 --- a/src/subscription/__tests__/mapAsyncIterator-test.js +++ b/src/subscription/__tests__/mapAsyncIterator-test.ts @@ -1,14 +1,15 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; +import { PromiseOrValue } from '../../jsutils/PromiseOrValue'; + import invariant from '../../jsutils/invariant'; import mapAsyncIterator from '../mapAsyncIterator'; describe('mapAsyncIterator', () => { it('maps over async generator', async () => { + // FIXME: Missing await async function* source() { yield 1; yield 2; @@ -30,7 +31,6 @@ describe('mapAsyncIterator', () => { const items = [1, 2, 3]; const iterator: any = { - // $FlowFixMe Blocked by https://github.com/facebook/flow/issues/3258 [Symbol.asyncIterator]() { return this; }, @@ -42,7 +42,7 @@ describe('mapAsyncIterator', () => { }, }; - const doubles = mapAsyncIterator(iterator, (x) => x + x); + const doubles = mapAsyncIterator(iterator, (x: number) => x + x); expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); @@ -54,6 +54,7 @@ describe('mapAsyncIterator', () => { }); it('compatible with for-await-of', async () => { + // FIXME: Missing await async function* source() { yield 1; yield 2; @@ -70,6 +71,7 @@ describe('mapAsyncIterator', () => { }); it('maps over async values with async function', async () => { + // FIXME: Missing await async function* source() { yield 1; yield 2; @@ -79,6 +81,7 @@ describe('mapAsyncIterator', () => { // Flow test: this is *not* AsyncIterator> const doubles: AsyncIterator = mapAsyncIterator( source(), + // FIXME: Unknown type of x async (x) => (await x) + x, ); @@ -92,6 +95,7 @@ describe('mapAsyncIterator', () => { }); it('allows returning early from mapped async generator', async () => { + // FIXME: Missing await async function* source() { yield 1; yield 2; @@ -126,7 +130,6 @@ describe('mapAsyncIterator', () => { const items = [1, 2, 3]; const iterator: any = { - // $FlowFixMe Blocked by https://github.com/facebook/flow/issues/3258 [Symbol.asyncIterator]() { return this; }, @@ -138,7 +141,7 @@ describe('mapAsyncIterator', () => { }, }; - const doubles = mapAsyncIterator(iterator, (x) => x + x); + const doubles = mapAsyncIterator(iterator, (x: number) => x + x); expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); @@ -151,6 +154,7 @@ describe('mapAsyncIterator', () => { }); it('passes through early return from async values', async () => { + // FIXME: Missing await async function* source() { try { yield 1; @@ -164,7 +168,8 @@ describe('mapAsyncIterator', () => { } } - const doubles = mapAsyncIterator(source(), (x) => x + x); + // @ts-expect-error - we are trying to combine number and string with + operand + const doubles = mapAsyncIterator(source(), (x: number | string) => x + x); expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); @@ -190,7 +195,6 @@ describe('mapAsyncIterator', () => { const items = [1, 2, 3]; const iterator: any = { - // $FlowFixMe Blocked by https://github.com/facebook/flow/issues/3258 [Symbol.asyncIterator]() { return this; }, @@ -202,7 +206,7 @@ describe('mapAsyncIterator', () => { }, }; - const doubles = mapAsyncIterator(iterator, (x) => x + x); + const doubles = mapAsyncIterator(iterator, (x: number) => x + x); expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); @@ -218,6 +222,7 @@ describe('mapAsyncIterator', () => { }); it('passes through caught errors through async generators', async () => { + // FIXME: Missing await async function* source() { try { yield 1; @@ -230,7 +235,7 @@ describe('mapAsyncIterator', () => { } } - const doubles = mapAsyncIterator(source(), (x) => x + x); + const doubles = mapAsyncIterator(source(), (x: number) => x + x); expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); @@ -252,6 +257,7 @@ describe('mapAsyncIterator', () => { }); it('does not normally map over thrown errors', async () => { + // FIXME: Missing await async function* source() { yield 'Hello'; throw new Error('Goodbye'); @@ -276,6 +282,7 @@ describe('mapAsyncIterator', () => { }); it('maps over thrown errors if second callback provided', async () => { + // FIXME: Missing await async function* source() { yield 'Hello'; throw new Error('Goodbye'); @@ -303,9 +310,12 @@ describe('mapAsyncIterator', () => { }); }); - async function testClosesSourceWithMapper(mapper) { + async function testClosesSourceWithMapper( + mapper: (v: number) => PromiseOrValue, + ) { let didVisitFinally = false; + // FIXME: Missing await async function* source() { try { yield 1; @@ -342,8 +352,9 @@ describe('mapAsyncIterator', () => { } it('closes source if mapper throws an error', async () => { - await testClosesSourceWithMapper((x) => { + await testClosesSourceWithMapper((x: number) => { if (x > 1) { + // FIXME: Prefer string literal over plus operand throw new Error('Cannot count to ' + x); } return x; @@ -351,20 +362,24 @@ describe('mapAsyncIterator', () => { }); it('closes source if mapper rejects', async () => { - await testClosesSourceWithMapper((x) => + await testClosesSourceWithMapper((x: number) => x > 1 - ? Promise.reject(new Error('Cannot count to ' + x)) + ? // FIXME: Prefer string literal over plus operand + Promise.reject(new Error('Cannot count to ' + x)) : Promise.resolve(x), ); }); - async function testClosesSourceWithRejectMapper(mapper) { + async function testClosesSourceWithRejectMapper( + mapper: (e: Error) => PromiseOrValue, + ) { + // FIXME: Missing await async function* source() { yield 1; - throw new Error(2); + throw new Error('2'); } - const throwOver1 = mapAsyncIterator(source(), (x) => x, mapper); + const throwOver1 = mapAsyncIterator(source(), (x: number) => x, mapper); expect(await throwOver1.next()).to.deep.equal({ value: 1, done: false }); @@ -385,13 +400,13 @@ describe('mapAsyncIterator', () => { } it('closes source if mapper throws an error', async () => { - await testClosesSourceWithRejectMapper((error) => { + await testClosesSourceWithRejectMapper((error: Error) => { throw new Error('Cannot count to ' + error.message); }); }); it('closes source if mapper rejects', async () => { - await testClosesSourceWithRejectMapper((error) => + await testClosesSourceWithRejectMapper((error: Error) => Promise.reject(new Error('Cannot count to ' + error.message)), ); }); diff --git a/src/subscription/__tests__/subscribe-test.js b/src/subscription/__tests__/subscribe-test.ts similarity index 91% rename from src/subscription/__tests__/subscribe-test.js rename to src/subscription/__tests__/subscribe-test.ts index 0adec2327a..04c56174fc 100644 --- a/src/subscription/__tests__/subscribe-test.js +++ b/src/subscription/__tests__/subscribe-test.ts @@ -1,6 +1,4 @@ -// @flow strict - -import EventEmitter from 'events'; +import { EventEmitter } from 'events'; import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -10,7 +8,11 @@ import { parse } from '../../language/parser'; import { GraphQLError } from '../../error/GraphQLError'; import { GraphQLSchema } from '../../type/schema'; -import { GraphQLList, GraphQLObjectType } from '../../type/definition'; +import { + GraphQLList, + GraphQLObjectType, + GraphQLFieldResolver, +} from '../../type/definition'; import { GraphQLInt, GraphQLString, GraphQLBoolean } from '../../type/scalars'; import { createSourceEventStream, subscribe } from '../subscribe'; @@ -36,7 +38,8 @@ const InboxType = new GraphQLObjectType({ }, unread: { type: GraphQLInt, - resolve: (inbox) => inbox.emails.filter((email) => email.unread).length, + resolve: (inbox) => + inbox.emails.filter((email: Email) => email.unread).length, }, emails: { type: GraphQLList(EmailType) }, }, @@ -59,7 +62,10 @@ const EmailEventType = new GraphQLObjectType({ const emailSchema = emailSchemaWithResolvers(); -function emailSchemaWithResolvers(subscribeFn, resolveFn) { +function emailSchemaWithResolvers( + subscribeFn?: GraphQLFieldResolver, + resolveFn?: GraphQLFieldResolver, +) { return new GraphQLSchema({ query: QueryType, subscription: new GraphQLObjectType({ @@ -79,7 +85,7 @@ function emailSchemaWithResolvers(subscribeFn, resolveFn) { } const defaultSubscriptionAST = parse(` - subscription ($priority: Int = 0) { + subscription($priority: Int = 0) { importantEmail(priority: $priority) { email { from @@ -93,12 +99,29 @@ const defaultSubscriptionAST = parse(` } `); +interface Email { + from: string; + subject: string; + message: string; + unread: boolean; +} + +interface TestData { + inbox: { + emails: Array; + }; + importantEmail: () => AsyncIterator; +} + async function createSubscription( - pubsub, + pubsub: EventEmitter, schema = emailSchema, document = defaultSubscriptionAST, -) { - const data = { +): Promise<{ + sendImportantEmail: (e: Email) => boolean; + subscription: AsyncIterableIterator; +}> { + const data: TestData = { inbox: { emails: [ { @@ -114,7 +137,7 @@ async function createSubscription( }, }; - function sendImportantEmail(newEmail) { + function sendImportantEmail(newEmail: Email) { data.inbox.emails.push(newEmail); // Returns true if the event was consumed by a subscriber. return pubsub.emit('importantEmail', { @@ -128,12 +151,18 @@ async function createSubscription( // `subscribe` returns Promise return { sendImportantEmail, - // $FlowFixMe - subscription: await subscribe({ schema, document, rootValue: data }), + subscription: (await subscribe({ + schema, + document, + rootValue: data, + })) as AsyncIterableIterator, }; } -async function expectPromiseToThrow(promise, message) { +async function expectPromiseToThrow( + promise: () => Promise, + message: string, +) { try { await promise(); // istanbul ignore next (Shouldn't be reached) @@ -157,13 +186,15 @@ describe('Subscription Initialization Phase', () => { // Empty } - // $FlowFixMe - const ai = await subscribe(emailSchema, document, { + const ai = (await subscribe(emailSchema, document, { importantEmail: emptyAsyncIterator, - }); + })) as AsyncIterableIterator; - ai.next(); - ai.return(); + await ai.next(); + + if (ai.return) { + await ai.return(); + } }); it('accepts multiple subscription fields defined in schema', async () => { @@ -212,15 +243,14 @@ describe('Subscription Initialization Phase', () => { }), }); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema, document: parse(` subscription { importantEmail } `), - }); + })) as AsyncIterableIterator; pubsub.emit('importantEmail', { importantEmail: {}, @@ -247,15 +277,14 @@ describe('Subscription Initialization Phase', () => { }), }); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema, document: parse(` subscription { importantEmail } `), - }); + })) as AsyncIterableIterator; pubsub.emit('importantEmail', { importantEmail: {}, @@ -294,8 +323,7 @@ describe('Subscription Initialization Phase', () => { subscription: SubscriptionTypeMultiple, }); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema, document: parse(` subscription { @@ -303,15 +331,18 @@ describe('Subscription Initialization Phase', () => { nonImportantEmail } `), - }); + })) as AsyncIterableIterator; + // FIXME: https://github.com/graphql/graphql-js/issues/2610 subscription.next(); // Ask for a result, but ignore it. expect(didResolveImportantEmail).to.equal(true); expect(didResolveNonImportantEmail).to.equal(false); // Close subscription - subscription.return(); + if (subscription.return) { + await subscription.return(); + } }); it('throws an error if schema is missing', async () => { @@ -322,13 +353,13 @@ describe('Subscription Initialization Phase', () => { `); await expectPromiseToThrow( - // $DisableFlowOnNegativeTest + // @ts-expect-error - schema is null () => subscribe(null, document), 'Expected null to be a GraphQL schema.', ); await expectPromiseToThrow( - // $DisableFlowOnNegativeTest + // @ts-expect-error - no schema () => subscribe({ document }), 'Expected undefined to be a GraphQL schema.', ); @@ -336,13 +367,13 @@ describe('Subscription Initialization Phase', () => { it('throws an error if document is missing', async () => { await expectPromiseToThrow( - // $DisableFlowOnNegativeTest + // @ts-expect-error - null document () => subscribe(emailSchema, null), 'Must provide document.', ); await expectPromiseToThrow( - // $DisableFlowOnNegativeTest + // @ts-expect-error - no document () => subscribe({ schema: emailSchema }), 'Must provide document.', ); @@ -372,7 +403,7 @@ describe('Subscription Initialization Phase', () => { it('should pass through unexpected errors thrown in subscribe', async () => { let expectedError; try { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid document await subscribe({ schema: emailSchema, document: {} }); } catch (error) { expectedError = error; @@ -427,7 +458,7 @@ describe('Subscription Initialization Phase', () => { ); await testReportsError(subscriptionRejectingErrorSchema); - async function testReportsError(schema) { + async function testReportsError(schema: GraphQLSchema) { // Promise | ExecutionResult> const result = await subscribe({ schema, @@ -475,7 +506,7 @@ describe('Subscription Initialization Phase', () => { ); await testReportsError(subscriptionRejectingErrorSchema); - async function testReportsError(schema) { + async function testReportsError(schema: GraphQLSchema) { // Promise | ExecutionResult> const result = await createSourceEventStream( schema, @@ -647,6 +678,7 @@ describe('Subscription Publish Phase', () => { }); // The client decides to disconnect. + // @ts-expect-error - return might be empty, but we are aware of that expect(await subscription.return()).to.deep.equal({ done: true, value: undefined, @@ -771,7 +803,10 @@ describe('Subscription Publish Phase', () => { }); payload = subscription.next(); - subscription.return(); + + if (subscription.return) { + await subscription.return(); + } // A new email arrives! expect( @@ -829,6 +864,7 @@ describe('Subscription Publish Phase', () => { // Throw error let caughtError; try { + // @ts-expect-error - throw might be empty in the source declaration await subscription.throw('ouch'); } catch (e) { caughtError = e; @@ -919,6 +955,7 @@ describe('Subscription Publish Phase', () => { it('should handle error during execution of source event', async () => { const erroringEmailSchema = emailSchemaWithResolvers( + // FIXME: Missing await async function* () { yield { email: { subject: 'Hello' } }; yield { email: { subject: 'Goodbye' } }; @@ -932,8 +969,7 @@ describe('Subscription Publish Phase', () => { }, ); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema: erroringEmailSchema, document: parse(` subscription { @@ -944,7 +980,7 @@ describe('Subscription Publish Phase', () => { } } `), - }); + })) as AsyncIterableIterator; const payload1 = await subscription.next(); expect(payload1).to.deep.equal({ @@ -997,6 +1033,7 @@ describe('Subscription Publish Phase', () => { it('should pass through error thrown in source event stream', async () => { const erroringEmailSchema = emailSchemaWithResolvers( + // FIXME: Missing await async function* () { yield { email: { subject: 'Hello' } }; throw new Error('test error'); @@ -1004,8 +1041,7 @@ describe('Subscription Publish Phase', () => { (email) => email, ); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema: erroringEmailSchema, document: parse(` subscription { @@ -1016,7 +1052,7 @@ describe('Subscription Publish Phase', () => { } } `), - }); + })) as AsyncIterableIterator; const payload1 = await subscription.next(); expect(payload1).to.deep.equal({ @@ -1051,6 +1087,7 @@ describe('Subscription Publish Phase', () => { it('should resolve GraphQL error from source event stream', async () => { const erroringEmailSchema = emailSchemaWithResolvers( + // FIXME: Missing await async function* () { yield { email: { subject: 'Hello' } }; throw new GraphQLError('test error'); @@ -1058,8 +1095,7 @@ describe('Subscription Publish Phase', () => { (email) => email, ); - // $FlowFixMe - const subscription = await subscribe({ + const subscription = (await subscribe({ schema: erroringEmailSchema, document: parse(` subscription { @@ -1070,7 +1106,7 @@ describe('Subscription Publish Phase', () => { } } `), - }); + })) as AsyncIterableIterator; const payload1 = await subscription.next(); expect(payload1).to.deep.equal({ diff --git a/src/tslint.json b/src/tslint.json index 0d7a24bcde..436407be67 100644 --- a/src/tslint.json +++ b/src/tslint.json @@ -1,5 +1,8 @@ { "extends": "dtslint/dtslint.json", + "linterOptions": { + "exclude": ["./**/__tests__/**/*.ts", "./**/__testUtils__/**/*.ts"] + }, "rules": { "array-type": false, "strict-export-declare-modifiers": false diff --git a/src/type/__tests__/definition-test.js b/src/type/__tests__/definition-test.ts similarity index 92% rename from src/type/__tests__/definition-test.js rename to src/type/__tests__/definition-test.ts index 4b21a189b6..6b11be56ad 100644 --- a/src/type/__tests__/definition-test.js +++ b/src/type/__tests__/definition-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,8 +7,8 @@ import identityFunc from '../../jsutils/identityFunc'; import { parseValue } from '../../language/parser'; import { - type GraphQLType, - type GraphQLNullableType, + GraphQLType, + GraphQLNullableType, GraphQLScalarType, GraphQLObjectType, GraphQLInterfaceType, @@ -86,16 +84,16 @@ describe('Type System: Scalars', () => { }, }); - expect(scalar.parseLiteral(parseValue('null'))).to.equal( + expect(scalar.parseLiteral(parseValue('null'), {})).to.equal( 'parseValue: null', ); - expect(scalar.parseLiteral(parseValue('{ foo: "bar" }'))).to.equal( + expect(scalar.parseLiteral(parseValue('{ foo: "bar" }'), {})).to.equal( 'parseValue: { foo: "bar" }', ); }); it('rejects a Scalar type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - name is missing expect(() => new GraphQLScalarType({})).to.throw('Must provide name.'); }); @@ -104,7 +102,7 @@ describe('Type System: Scalars', () => { () => new GraphQLScalarType({ name: 'SomeScalar', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid serialize function serialize: {}, }), ).to.throw( @@ -129,9 +127,9 @@ describe('Type System: Scalars', () => { () => new GraphQLScalarType({ name: 'SomeScalar', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid param parseValue: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid param parseLiteral: {}, }), ).to.throw( @@ -144,7 +142,7 @@ describe('Type System: Scalars', () => { () => new GraphQLScalarType({ name: 'SomeScalar', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid param specifiedByUrl: {}, }), ).to.throw( @@ -328,7 +326,7 @@ describe('Type System: Objects', () => { }); it('rejects an Object type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid name expect(() => new GraphQLObjectType({})).to.throw('Must provide name.'); }); @@ -336,7 +334,7 @@ describe('Type System: Objects', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', fields: { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type f: undefined, }, }); @@ -348,7 +346,7 @@ describe('Type System: Objects', () => { it('rejects an Object type with incorrectly typed fields', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type fields: [{ field: ScalarType }], }); expect(() => objType.getFields()).to.throw( @@ -359,7 +357,7 @@ describe('Type System: Objects', () => { it('rejects an Object type with a field function that returns incorrect type', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type returned fields() { return [{ field: ScalarType }]; }, @@ -375,7 +373,7 @@ describe('Type System: Objects', () => { fields: { badField: { type: ScalarType, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid arg args: [{ badArg: ScalarType }], }, }, @@ -388,8 +386,8 @@ describe('Type System: Objects', () => { it('rejects an Object type with an isDeprecated instead of deprecationReason on field', () => { const OldObject = new GraphQLObjectType({ name: 'OldObject', - // $DisableFlowOnNegativeTest fields: { + // @ts-expect-error - invalid definition, should use deprecationReason field: { type: ScalarType, isDeprecated: true }, }, }); @@ -403,7 +401,7 @@ describe('Type System: Objects', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type interfaces: {}, }); expect(() => objType.getInterfaces()).to.throw( @@ -415,7 +413,7 @@ describe('Type System: Objects', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type interfaces() { return {}; }, @@ -428,8 +426,8 @@ describe('Type System: Objects', () => { it('rejects an empty Object field resolver', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', - // $DisableFlowOnNegativeTest fields: { + // @ts-expect-error - invalid resolver field: { type: ScalarType, resolve: {} }, }, }); @@ -442,8 +440,8 @@ describe('Type System: Objects', () => { it('rejects a constant scalar value resolver', () => { const objType = new GraphQLObjectType({ name: 'SomeObject', - // $DisableFlowOnNegativeTest fields: { + // @ts-expect-error - invalid resolver field: { type: ScalarType, resolve: 0 }, }, }); @@ -459,7 +457,7 @@ describe('Type System: Objects', () => { new GraphQLObjectType({ name: 'AnotherObject', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid isTypeOf function isTypeOf: {}, }), ).to.throw( @@ -498,7 +496,7 @@ describe('Type System: Interfaces', () => { }); it('rejects an Interface type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - name is missing expect(() => new GraphQLInterfaceType({})).to.throw('Must provide name.'); }); @@ -506,7 +504,7 @@ describe('Type System: Interfaces', () => { const objType = new GraphQLInterfaceType({ name: 'AnotherInterface', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type interfaces: {}, }); expect(() => objType.getInterfaces()).to.throw( @@ -518,7 +516,7 @@ describe('Type System: Interfaces', () => { const objType = new GraphQLInterfaceType({ name: 'AnotherInterface', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid return value interfaces() { return {}; }, @@ -534,7 +532,7 @@ describe('Type System: Interfaces', () => { new GraphQLInterfaceType({ name: 'AnotherInterface', fields: {}, - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid resolveType function resolveType: {}, }), ).to.throw( @@ -579,7 +577,7 @@ describe('Type System: Unions', () => { }); it('rejects an Union type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - name is missing expect(() => new GraphQLUnionType({})).to.throw('Must provide name.'); }); @@ -589,7 +587,7 @@ describe('Type System: Unions', () => { new GraphQLUnionType({ name: 'SomeUnion', types: [], - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid function resolveType: {}, }), ).to.throw( @@ -600,7 +598,7 @@ describe('Type System: Unions', () => { it('rejects a Union type with incorrectly typed types', () => { const unionType = new GraphQLUnionType({ name: 'SomeUnion', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid types field types: { ObjectType }, }); @@ -699,7 +697,7 @@ describe('Type System: Enums', () => { }); it('rejects an Enum type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - missing name expect(() => new GraphQLEnumType({ values: {} })).to.throw( 'Must provide name.', ); @@ -710,7 +708,7 @@ describe('Type System: Enums', () => { () => new GraphQLEnumType({ name: 'SomeEnum', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid values values: [{ FOO: 10 }], }), ).to.throw('SomeEnum values must be an object with value names as keys.'); @@ -721,7 +719,7 @@ describe('Type System: Enums', () => { () => new GraphQLEnumType({ name: 'SomeEnum', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid values values: { FOO: null }, }), ).to.throw( @@ -734,7 +732,7 @@ describe('Type System: Enums', () => { () => new GraphQLEnumType({ name: 'SomeEnum', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid values values: { FOO: 10 }, }), ).to.throw( @@ -747,8 +745,8 @@ describe('Type System: Enums', () => { () => new GraphQLEnumType({ name: 'SomeEnum', - // $DisableFlowOnNegativeTest values: { + // @ts-expect-error - invalid usage of deprecation FOO: { isDeprecated: true }, }, }), @@ -799,7 +797,7 @@ describe('Type System: Input Objects', () => { }); it('rejects an Input Object type without name', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - name is missing expect(() => new GraphQLInputObjectType({})).to.throw( 'Must provide name.', ); @@ -808,7 +806,7 @@ describe('Type System: Input Objects', () => { it('rejects an Input Object type with incorrect fields', () => { const inputObjType = new GraphQLInputObjectType({ name: 'SomeInputObject', - // $DisableFlowOnNegativeTest + // @ts-expect-error - no fields fields: [], }); expect(() => inputObjType.getFields()).to.throw( @@ -819,7 +817,7 @@ describe('Type System: Input Objects', () => { it('rejects an Input Object type with fields function that returns incorrect type', () => { const inputObjType = new GraphQLInputObjectType({ name: 'SomeInputObject', - // $DisableFlowOnNegativeTest + // @ts-expect-error - no fields fields: () => [], }); expect(() => inputObjType.getFields()).to.throw( @@ -832,8 +830,8 @@ describe('Type System: Input Objects', () => { it('rejects an Input Object type with resolvers', () => { const inputObjType = new GraphQLInputObjectType({ name: 'SomeInputObject', - // $DisableFlowOnNegativeTest fields: { + // @ts-expect-error - reject resolver f: { type: ScalarType, resolve: dummyFunc }, }, }); @@ -845,8 +843,8 @@ describe('Type System: Input Objects', () => { it('rejects an Input Object type with resolver constant', () => { const inputObjType = new GraphQLInputObjectType({ name: 'SomeInputObject', - // $DisableFlowOnNegativeTest fields: { + // @ts-expect-error - reject resolver f: { type: ScalarType, resolve: {} }, }, }); @@ -874,15 +872,15 @@ describe('Type System: List', () => { }); it('rejects a non-type as item type of list', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects object expectList({}).to.throw('Expected {} to be a GraphQL type.'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects String expectList(String).to.throw( 'Expected [function String] to be a GraphQL type.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects null expectList(null).to.throw('Expected null to be a GraphQL type.'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects undefined expectList(undefined).to.throw('Expected undefined to be a GraphQL type.'); }); }); @@ -904,21 +902,20 @@ describe('Type System: Non-Null', () => { }); it('rejects a non-type as nullable type of non-null', () => { - // $DisableFlowOnNegativeTest expectNonNull(NonNullScalarType).to.throw( 'Expected Scalar! to be a GraphQL nullable type.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects object expectNonNull({}).to.throw('Expected {} to be a GraphQL nullable type.'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects String expectNonNull(String).to.throw( 'Expected [function String] to be a GraphQL nullable type.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects null expectNonNull(null).to.throw( 'Expected null to be a GraphQL nullable type.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - rejects undefined expectNonNull(undefined).to.throw( 'Expected undefined to be a GraphQL nullable type.', ); @@ -959,7 +956,7 @@ describe('Type System: test utility methods', () => { }); it('Object.toStringifies types', () => { - function toString(obj) { + function toString(obj: any) { return Object.prototype.toString.call(obj); } diff --git a/src/type/__tests__/directive-test.js b/src/type/__tests__/directive-test.ts similarity index 94% rename from src/type/__tests__/directive-test.js rename to src/type/__tests__/directive-test.ts index 38bbe852a9..dbed8caf94 100644 --- a/src/type/__tests__/directive-test.js +++ b/src/type/__tests__/directive-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -85,7 +83,7 @@ describe('Type System: Directive', () => { }); it('rejects an unnamed directive', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - name is missing expect(() => new GraphQLDirective({ locations: ['Query'] })).to.throw( 'Directive must be named.', ); @@ -97,21 +95,21 @@ describe('Type System: Directive', () => { new GraphQLDirective({ name: 'Foo', locations: ['QUERY'], - // $DisableFlowOnNegativeTest + // @ts-expect-error - args is invalid args: [], }), ).to.throw('@Foo args must be an object with argument names as keys.'); }); it('rejects a directive with undefined locations', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - no locations expect(() => new GraphQLDirective({ name: 'Foo' })).to.throw( '@Foo locations must be an Array.', ); }); it('rejects a directive with incorrectly typed locations', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid locations expect(() => new GraphQLDirective({ name: 'Foo', locations: {} })).to.throw( '@Foo locations must be an Array.', ); diff --git a/src/type/__tests__/enumType-test.js b/src/type/__tests__/enumType-test.ts similarity index 98% rename from src/type/__tests__/enumType-test.js rename to src/type/__tests__/enumType-test.ts index e4b12195cb..2079d22584 100644 --- a/src/type/__tests__/enumType-test.js +++ b/src/type/__tests__/enumType-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -114,7 +112,7 @@ const schema = new GraphQLSchema({ subscription: SubscriptionType, }); -function executeQuery(source, variableValues) { +function executeQuery(source: string, variableValues?: Record) { return graphqlSync({ schema, source, variableValues }); } @@ -365,7 +363,7 @@ describe('Type System: Enum Values', () => { const oneValue = ComplexEnum.getValue('ONE'); expect(oneValue).to.include({ name: 'ONE', value: Complex1 }); - // $DisableFlowOnNegativeTest + // @ts-expect-error - incorrect usage const badUsage = ComplexEnum.getValue(Complex1); expect(badUsage).to.equal(undefined); }); diff --git a/src/type/__tests__/extensions-test.js b/src/type/__tests__/extensions-test.ts similarity index 95% rename from src/type/__tests__/extensions-test.js rename to src/type/__tests__/extensions-test.ts index 96027a116b..838d102ffd 100644 --- a/src/type/__tests__/extensions-test.js +++ b/src/type/__tests__/extensions-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -18,7 +16,7 @@ import { const dummyType = new GraphQLScalarType({ name: 'DummyScalar' }); -function expectObjMap(value) { +function expectObjMap(value: any) { invariant(value != null && typeof value === 'object'); expect(Object.getPrototypeOf(value)).to.equal(null); return expect(value); @@ -75,8 +73,8 @@ describe('Type System: Extensions', () => { const someFieldConfig = config.fields.someField; expect(someFieldConfig.extensions).to.equal(undefined); invariant(someFieldConfig.args); - const someArgConfig = someFieldConfig.args.someArg; - expect(someArgConfig.extensions).to.equal(undefined); + const someArgConfig = someFieldConfig.args?.someArg; + expect(someArgConfig?.extensions).to.equal(undefined); }); it('with extensions', () => { @@ -112,8 +110,8 @@ describe('Type System: Extensions', () => { const someFieldConfig = config.fields.someField; expectObjMap(someFieldConfig.extensions).to.deep.equal(fieldExtensions); invariant(someFieldConfig.args); - const someArgConfig = someFieldConfig.args.someArg; - expectObjMap(someArgConfig.extensions).to.deep.equal(argExtensions); + const someArgConfig = someFieldConfig.args?.someArg; + expectObjMap(someArgConfig?.extensions).to.deep.equal(argExtensions); }); }); @@ -144,8 +142,8 @@ describe('Type System: Extensions', () => { const someFieldConfig = config.fields.someField; expect(someFieldConfig.extensions).to.equal(undefined); invariant(someFieldConfig.args); - const someArgConfig = someFieldConfig.args.someArg; - expect(someArgConfig.extensions).to.equal(undefined); + const someArgConfig = someFieldConfig.args?.someArg; + expect(someArgConfig?.extensions).to.equal(undefined); }); it('with extensions', () => { @@ -183,8 +181,8 @@ describe('Type System: Extensions', () => { const someFieldConfig = config.fields.someField; expectObjMap(someFieldConfig.extensions).to.deep.equal(fieldExtensions); invariant(someFieldConfig.args); - const someArgConfig = someFieldConfig.args.someArg; - expectObjMap(someArgConfig.extensions).to.deep.equal(argExtensions); + const someArgConfig = someFieldConfig.args?.someArg; + expectObjMap(someArgConfig?.extensions).to.deep.equal(argExtensions); }); }); diff --git a/src/type/__tests__/introspection-test.js b/src/type/__tests__/introspection-test.ts similarity index 99% rename from src/type/__tests__/introspection-test.js rename to src/type/__tests__/introspection-test.ts index 842072de1b..f862fdd147 100644 --- a/src/type/__tests__/introspection-test.js +++ b/src/type/__tests__/introspection-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -15,6 +13,7 @@ import { GraphQLObjectType, GraphQLInputObjectType, GraphQLEnumType, + GraphQLResolveInfo, } from '../definition'; describe('Introspection', () => { @@ -1474,10 +1473,18 @@ describe('Introspection', () => { }); const schema = new GraphQLSchema({ query: QueryRoot }); - const source = getIntrospectionQuery({ directiveIsRepeatable: true }); + const source = getIntrospectionQuery({ + directiveIsRepeatable: true, + descriptions: true, + }); // istanbul ignore next (Called only to fail test) - function fieldResolver(_1, _2, _3, info) { + function fieldResolver( + _1: any, + _2: any, + _3: any, + info: GraphQLResolveInfo, + ) { invariant(false, `Called on ${info.parentType.name}::${info.fieldName}`); } diff --git a/src/type/__tests__/predicate-test.js b/src/type/__tests__/predicate-test.ts similarity index 97% rename from src/type/__tests__/predicate-test.js rename to src/type/__tests__/predicate-test.ts index 40dcca7ee8..a0fb2167c6 100644 --- a/src/type/__tests__/predicate-test.js +++ b/src/type/__tests__/predicate-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -67,6 +65,8 @@ import { assertNamedType, getNullableType, getNamedType, + GraphQLArgument, + GraphQLInputField, } from '../definition'; const ObjectType = new GraphQLObjectType({ name: 'Object', fields: {} }); @@ -291,7 +291,7 @@ describe('Type predicates', () => { }); describe('isInputType', () => { - function expectInputType(type) { + function expectInputType(type: any) { expect(isInputType(type)).to.equal(true); expect(() => assertInputType(type)).to.not.throw(); } @@ -312,7 +312,7 @@ describe('Type predicates', () => { expectInputType(GraphQLNonNull(InputObjectType)); }); - function expectNonInputType(type) { + function expectNonInputType(type: any) { expect(isInputType(type)).to.equal(false); expect(() => assertInputType(type)).to.throw(); } @@ -335,7 +335,7 @@ describe('Type predicates', () => { }); describe('isOutputType', () => { - function expectOutputType(type) { + function expectOutputType(type: any) { expect(isOutputType(type)).to.equal(true); expect(() => assertOutputType(type)).to.not.throw(); } @@ -362,7 +362,7 @@ describe('Type predicates', () => { expectOutputType(GraphQLNonNull(EnumType)); }); - function expectNonOutputType(type) { + function expectNonOutputType(type: any) { expect(isOutputType(type)).to.equal(false); expect(() => assertOutputType(type)).to.throw(); } @@ -492,7 +492,9 @@ describe('Type predicates', () => { describe('getNullableType', () => { it('returns undefined for no type', () => { + // @ts-expect-error - not type expect(getNullableType()).to.equal(undefined); + // @ts-expect-error - null type expect(getNullableType(null)).to.equal(undefined); }); @@ -523,7 +525,9 @@ describe('Type predicates', () => { describe('getNamedType', () => { it('returns undefined for no type', () => { + // @ts-expect-error - name is empty expect(getNamedType()).to.equal(undefined); + // @ts-expect-error - name is null expect(getNamedType(null)).to.equal(undefined); }); @@ -544,7 +548,7 @@ describe('Type predicates', () => { }); describe('isRequiredArgument', () => { - function buildArg(config) { + function buildArg(config: Partial): GraphQLArgument { return { name: 'someArg', description: undefined, @@ -552,7 +556,7 @@ describe('Type predicates', () => { extensions: undefined, astNode: undefined, ...config, - }; + } as GraphQLArgument; } it('returns true for required arguments', () => { @@ -588,15 +592,17 @@ describe('Type predicates', () => { }); describe('isRequiredInputField', () => { - function buildInputField(config) { - return { + function buildInputField( + config: Partial, + ): GraphQLInputField { + return ({ name: 'someInputField', description: undefined, defaultValue: undefined, extensions: undefined, astNode: undefined, ...config, - }; + } as any) as GraphQLInputField; } it('returns true for required input field', () => { diff --git a/src/type/__tests__/scalars-test.js b/src/type/__tests__/scalars-test.ts similarity index 95% rename from src/type/__tests__/scalars-test.js rename to src/type/__tests__/scalars-test.ts index 3ad38fa15c..f5978e9334 100644 --- a/src/type/__tests__/scalars-test.js +++ b/src/type/__tests__/scalars-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -16,7 +14,7 @@ import { describe('Type System: Specified scalar types', () => { describe('GraphQLInt', () => { it('parseValue', () => { - function parseValue(value) { + function parseValue(value: any) { return GraphQLInt.parseValue(value); } @@ -67,8 +65,8 @@ describe('Type System: Specified scalar types', () => { }); it('parseLiteral', () => { - function parseLiteral(str) { - return GraphQLInt.parseLiteral(parseValueToAST(str)); + function parseLiteral(str: string) { + return GraphQLInt.parseLiteral(parseValueToAST(str), {}); } expect(parseLiteral('1')).to.equal(1); @@ -114,7 +112,7 @@ describe('Type System: Specified scalar types', () => { describe('GraphQLFloat', () => { it('parseValue', () => { - function parseValue(value) { + function parseValue(value: any) { return GraphQLFloat.parseValue(value); } @@ -161,8 +159,8 @@ describe('Type System: Specified scalar types', () => { }); it('parseLiteral', () => { - function parseLiteral(str) { - return GraphQLFloat.parseLiteral(parseValueToAST(str)); + function parseLiteral(str: string) { + return GraphQLFloat.parseLiteral(parseValueToAST(str), {}); } expect(parseLiteral('1')).to.equal(1); @@ -203,7 +201,7 @@ describe('Type System: Specified scalar types', () => { describe('GraphQLString', () => { it('parseValue', () => { - function parseValue(value) { + function parseValue(value: any) { return GraphQLString.parseValue(value); } @@ -233,8 +231,8 @@ describe('Type System: Specified scalar types', () => { }); it('parseLiteral', () => { - function parseLiteral(str) { - return GraphQLString.parseLiteral(parseValueToAST(str)); + function parseLiteral(str: string) { + return GraphQLString.parseLiteral(parseValueToAST(str), {}); } expect(parseLiteral('"foo"')).to.equal('foo'); @@ -269,7 +267,7 @@ describe('Type System: Specified scalar types', () => { describe('GraphQLBoolean', () => { it('parseValue', () => { - function parseValue(value) { + function parseValue(value: any) { return GraphQLBoolean.parseValue(value); } @@ -306,8 +304,8 @@ describe('Type System: Specified scalar types', () => { }); it('parseLiteral', () => { - function parseLiteral(str) { - return GraphQLBoolean.parseLiteral(parseValueToAST(str)); + function parseLiteral(str: string) { + return GraphQLBoolean.parseLiteral(parseValueToAST(str), {}); } expect(parseLiteral('true')).to.equal(true); @@ -348,7 +346,7 @@ describe('Type System: Specified scalar types', () => { describe('GraphQLID', () => { it('parseValue', () => { - function parseValue(value) { + function parseValue(value: any) { return GraphQLID.parseValue(value); } @@ -386,8 +384,8 @@ describe('Type System: Specified scalar types', () => { }); it('parseLiteral', () => { - function parseLiteral(str) { - return GraphQLID.parseLiteral(parseValueToAST(str)); + function parseLiteral(str: string) { + return GraphQLID.parseLiteral(parseValueToAST(str), {}); } expect(parseLiteral('""')).to.equal(''); diff --git a/src/type/__tests__/schema-test.js b/src/type/__tests__/schema-test.ts similarity index 94% rename from src/type/__tests__/schema-test.js rename to src/type/__tests__/schema-test.ts index eee7f12029..4a4dc85abe 100644 --- a/src/type/__tests__/schema-test.js +++ b/src/type/__tests__/schema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -29,7 +27,7 @@ describe('Type System: Schema', () => { }, }); - const BlogAuthor = new GraphQLObjectType({ + const BlogAuthor: GraphQLObjectType = new GraphQLObjectType({ name: 'Author', fields: () => ({ id: { type: GraphQLString }, @@ -142,19 +140,19 @@ describe('Type System: Schema', () => { it('defines a query root', () => { const schema = new GraphQLSchema({ query: testType }); expect(schema.getQueryType()).to.equal(testType); - expect(schema.getTypeMap()).to.include.key('TestType'); + expect(schema.getTypeMap()).to.include.keys('TestType'); }); it('defines a mutation root', () => { const schema = new GraphQLSchema({ mutation: testType }); expect(schema.getMutationType()).to.equal(testType); - expect(schema.getTypeMap()).to.include.key('TestType'); + expect(schema.getTypeMap()).to.include.keys('TestType'); }); it('defines a subscription root', () => { const schema = new GraphQLSchema({ subscription: testType }); expect(schema.getSubscriptionType()).to.equal(testType); - expect(schema.getTypeMap()).to.include.key('TestType'); + expect(schema.getTypeMap()).to.include.keys('TestType'); }); }); @@ -255,6 +253,7 @@ describe('Type System: Schema', () => { }, }, }); + const schema = new GraphQLSchema({ directives: [directive] }); expect(schema.getTypeMap()).to.include.keys('Foo', 'Bar'); @@ -324,18 +323,17 @@ describe('Type System: Schema', () => { describe('when not assumed valid', () => { it('configures the schema to still needing validation', () => { expect( - new GraphQLSchema({ - assumeValid: false, - }).__validationErrors, + // @ts-expect-error - access to internal field + new GraphQLSchema({ assumeValid: false }).__validationErrors, ).to.equal(undefined); }); it('checks the configuration for mistakes', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid args expect(() => new GraphQLSchema(JSON.parse)).to.throw(); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid args expect(() => new GraphQLSchema({ types: {} })).to.throw(); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid args expect(() => new GraphQLSchema({ directives: {} })).to.throw(); }); }); @@ -364,7 +362,7 @@ describe('Type System: Schema', () => { }); const types = [{}, query, {}]; - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid types expect(() => new GraphQLSchema({ query, types })).to.throw( 'One of the provided types for building the Schema is missing a name.', ); @@ -400,9 +398,8 @@ describe('Type System: Schema', () => { describe('when assumed valid', () => { it('configures the schema to have no errors', () => { expect( - new GraphQLSchema({ - assumeValid: true, - }).__validationErrors, + // @ts-expect-error - access to internal field + new GraphQLSchema({ assumeValid: true }).__validationErrors, ).to.deep.equal([]); }); }); diff --git a/src/type/__tests__/serialization-test.js b/src/type/__tests__/serialization-test.ts similarity index 99% rename from src/type/__tests__/serialization-test.js rename to src/type/__tests__/serialization-test.ts index c851f02657..2882150505 100644 --- a/src/type/__tests__/serialization-test.js +++ b/src/type/__tests__/serialization-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/type/__tests__/validation-test.js b/src/type/__tests__/validation-test.ts similarity index 97% rename from src/type/__tests__/validation-test.js rename to src/type/__tests__/validation-test.ts index 599ed20285..f9829dc5b6 100644 --- a/src/type/__tests__/validation-test.js +++ b/src/type/__tests__/validation-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -17,9 +15,9 @@ import { GraphQLString } from '../scalars'; import { validateSchema, assertValidSchema } from '../validate'; import { GraphQLDirective, assertDirective } from '../directives'; import { - type GraphQLNamedType, - type GraphQLInputType, - type GraphQLOutputType, + GraphQLNamedType, + GraphQLInputType, + GraphQLOutputType, GraphQLList, GraphQLNonNull, GraphQLObjectType, @@ -33,20 +31,30 @@ import { assertUnionType, assertEnumType, assertInputObjectType, + GraphQLType, + GraphQLEnumValueConfigMap, } from '../definition'; const SomeSchema = buildSchema(` scalar SomeScalar - interface SomeInterface { f: SomeObject } + interface SomeInterface { + f: SomeObject + } - type SomeObject implements SomeInterface { f: SomeObject } + type SomeObject implements SomeInterface { + f: SomeObject + } union SomeUnion = SomeObject - enum SomeEnum { ONLY } + enum SomeEnum { + ONLY + } - input SomeInputObject { val: String = "hello" } + input SomeInputObject { + val: String = "hello" + } directive @SomeDirective on QUERY `); @@ -64,14 +72,14 @@ const SomeInputObjectType = assertInputObjectType( const SomeDirective = assertDirective(SomeSchema.getDirective('SomeDirective')); -function withModifiers( +function withModifiers( type: T, -): Array | GraphQLNonNull>> { +): Array | GraphQLNonNull> { return [ type, GraphQLList(type), GraphQLNonNull(type), - GraphQLNonNull(GraphQLList(type)), + GraphQLNonNull(new GraphQLList(type)), ]; } @@ -101,13 +109,13 @@ const notInputTypes: Array = [ ...withModifiers(SomeInterfaceType), ]; -function schemaWithFieldType(type) { +function schemaWithFieldType(type: GraphQLNamedType | GraphQLOutputType) { return new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', - fields: { f: { type } }, + fields: { f: { type: type as GraphQLOutputType } }, }), - types: [type], + types: [type as GraphQLNamedType], }); } @@ -388,7 +396,7 @@ describe('Type System: A Schema must have Object root types', () => { it('rejects a Schema whose types are incorrectly typed', () => { const schema = new GraphQLSchema({ query: SomeObjectType, - // $DisableFlowOnNegativeTest + // @ts-expect-error - incorrect types types: [{ name: 'SomeType' }, SomeDirective], }); expect(validateSchema(schema)).to.deep.equal([ @@ -397,7 +405,7 @@ describe('Type System: A Schema must have Object root types', () => { }, { message: 'Expected GraphQL named type but got: @SomeDirective.', - locations: [{ line: 14, column: 3 }], + locations: [{ line: 22, column: 3 }], }, ]); }); @@ -405,7 +413,7 @@ describe('Type System: A Schema must have Object root types', () => { it('rejects a Schema whose directives are incorrectly typed', () => { const schema = new GraphQLSchema({ query: SomeObjectType, - // $DisableFlowOnNegativeTest + // @ts-expect-error - incorrect types directives: [null, 'SomeDirective', SomeScalarType], }); expect(validateSchema(schema)).to.deep.equal([ @@ -683,7 +691,7 @@ describe('Type System: Union types must be valid', () => { for (const memberType of badUnionMemberTypes) { const badUnion = new GraphQLUnionType({ name: 'BadUnion', - // $DisableFlowOnNegativeTest + // @ts-expect-error - bad union type types: [memberType], }); const badSchema = schemaWithFieldType(badUnion); @@ -926,7 +934,7 @@ describe('Type System: Enum types must be well defined', () => { }); it('rejects an Enum type with incorrectly named values', () => { - function schemaWithEnum(values) { + function schemaWithEnum(values: GraphQLEnumValueConfigMap) { return schemaWithFieldType( new GraphQLEnumType({ name: 'SomeEnum', @@ -1005,7 +1013,7 @@ describe('Type System: Object fields must have output types', () => { } it('rejects an empty Object field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - empty type const schema = schemaWithObjectFieldOfType(undefined); expect(validateSchema(schema)).to.deep.equal([ { @@ -1018,7 +1026,7 @@ describe('Type System: Object fields must have output types', () => { for (const type of notOutputTypes) { const typeStr = inspect(type); it(`rejects a non-output type as an Object field type: ${typeStr}`, () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithObjectFieldOfType(type); expect(validateSchema(schema)).to.deep.equal([ { @@ -1029,7 +1037,7 @@ describe('Type System: Object fields must have output types', () => { } it('rejects a non-type value as an Object field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithObjectFieldOfType(Number); expect(validateSchema(schema)).to.deep.equal([ { @@ -1067,7 +1075,7 @@ describe('Type System: Objects can only implement unique interfaces', () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'BadObject', - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid value for an interface interfaces: [undefined], fields: { f: { type: GraphQLString } }, }), @@ -1326,7 +1334,7 @@ describe('Type System: Interface fields must have output types', () => { } it('rejects an empty Interface field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - empty interface array const schema = schemaWithInterfaceFieldOfType(undefined); expect(validateSchema(schema)).to.deep.equal([ { @@ -1343,7 +1351,7 @@ describe('Type System: Interface fields must have output types', () => { for (const type of notOutputTypes) { const typeStr = inspect(type); it(`rejects a non-output type as an Interface field type: ${typeStr}`, () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithInterfaceFieldOfType(type); expect(validateSchema(schema)).to.deep.equal([ { @@ -1357,7 +1365,7 @@ describe('Type System: Interface fields must have output types', () => { } it('rejects a non-type value as an Interface field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithInterfaceFieldOfType(Number); expect(validateSchema(schema)).to.deep.equal([ { @@ -1462,7 +1470,7 @@ describe('Type System: Arguments must have input types', () => { } it('rejects an empty field arg type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithArgOfType(undefined); expect(validateSchema(schema)).to.deep.equal([ { @@ -1479,7 +1487,7 @@ describe('Type System: Arguments must have input types', () => { for (const type of notInputTypes) { const typeStr = inspect(type); it(`rejects a non-input type as a field arg type: ${typeStr}`, () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithArgOfType(type); expect(validateSchema(schema)).to.deep.equal([ { @@ -1493,7 +1501,7 @@ describe('Type System: Arguments must have input types', () => { } it('rejects a non-type value as a field arg type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithArgOfType(Number); expect(validateSchema(schema)).to.deep.equal([ { @@ -1563,7 +1571,7 @@ describe('Type System: Input Object fields must have input types', () => { } it('rejects an empty input field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithInputFieldOfType(undefined); expect(validateSchema(schema)).to.deep.equal([ { @@ -1576,7 +1584,7 @@ describe('Type System: Input Object fields must have input types', () => { for (const type of notInputTypes) { const typeStr = inspect(type); it(`rejects a non-input type as an input field type: ${typeStr}`, () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithInputFieldOfType(type); expect(validateSchema(schema)).to.deep.equal([ { @@ -1587,7 +1595,7 @@ describe('Type System: Input Object fields must have input types', () => { } it('rejects a non-type value as an input field type', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type const schema = schemaWithInputFieldOfType(Number); expect(validateSchema(schema)).to.deep.equal([ { diff --git a/src/utilities/__tests__/TypeInfo-test.js b/src/utilities/__tests__/TypeInfo-test.ts similarity index 92% rename from src/utilities/__tests__/TypeInfo-test.js rename to src/utilities/__tests__/TypeInfo-test.ts index 53da7e747b..847e0a92cc 100644 --- a/src/utilities/__tests__/TypeInfo-test.js +++ b/src/utilities/__tests__/TypeInfo-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -8,8 +6,13 @@ import invariant from '../../jsutils/invariant'; import { parse, parseValue } from '../../language/parser'; import { print } from '../../language/printer'; import { visit } from '../../language/visitor'; +import type { OperationDefinitionNode } from '../../language/ast'; -import { getNamedType, isCompositeType } from '../../type/definition'; +import { + getNamedType, + isCompositeType, + GraphQLType, +} from '../../type/definition'; import { buildSchema } from '../buildASTSchema'; import { TypeInfo, visitWithTypeInfo } from '../TypeInfo'; @@ -60,7 +63,7 @@ describe('visitWithTypeInfo', () => { `); const typeInfo = new TypeInfo(schema); - const rootTypes = {}; + const rootTypes: Record = {}; visit( ast, visitWithTypeInfo(typeInfo, { @@ -82,7 +85,7 @@ describe('visitWithTypeInfo', () => { '{ human(id: 4) { name, pets { ... { name } }, unknown } }', ); - const visitorArgs = []; + const visitorArgs: Array<['enter' | 'leave', ...Array]> = []; visit(ast, { enter(...args) { visitorArgs.push(['enter', ...args]); @@ -92,7 +95,7 @@ describe('visitWithTypeInfo', () => { }, }); - const wrappedVisitorArgs = []; + const wrappedVisitorArgs: Array<['enter' | 'leave', ...Array]> = []; const typeInfo = new TypeInfo(testSchema); visit( ast, @@ -110,7 +113,14 @@ describe('visitWithTypeInfo', () => { }); it('maintains type info during visit', () => { - const visited = []; + const visited: Array<[ + string, + string, + string | null, + string | null, + string | null, + string | null, + ]> = []; const typeInfo = new TypeInfo(testSchema); @@ -195,7 +205,14 @@ describe('visitWithTypeInfo', () => { }); it('maintains type info during edit', () => { - const visited = []; + const visited: Array<[ + string, + string, + string | null, + string | null, + string | null, + string | null, + ]> = []; const typeInfo = new TypeInfo(testSchema); const ast = parse('{ human(id: 4) { name, pets }, alien }'); @@ -219,7 +236,7 @@ describe('visitWithTypeInfo', () => { if ( node.kind === 'Field' && !node.selectionSet && - isCompositeType(getNamedType(type)) + isCompositeType(getNamedType(type as GraphQLType)) ) { return { ...node, @@ -314,9 +331,13 @@ describe('visitWithTypeInfo', () => { const complexInputType = testSchema.getType('ComplexInput'); invariant(complexInputType != null); - const typeInfo = new TypeInfo(testSchema, undefined, complexInputType); + const typeInfo = new TypeInfo( + testSchema, + undefined, + complexInputType as GraphQLType, + ); - const visited = []; + const visited: Array<[string, string, string | null, string]> = []; visit( ast, visitWithTypeInfo(typeInfo, { @@ -359,15 +380,19 @@ describe('visitWithTypeInfo', () => { const humanType = testSchema.getType('Human'); invariant(humanType != null); - const typeInfo = new TypeInfo(testSchema, undefined, humanType); + const typeInfo = new TypeInfo( + testSchema, + undefined, + humanType as GraphQLType, + ); const ast = parse('{ name, pets { name } }'); const operationNode = ast.definitions[0]; invariant(operationNode.kind === 'OperationDefinition'); - const visited = []; + const visited: Array<[string, string, string | null, string, string]> = []; visit( - operationNode.selectionSet, + (operationNode as OperationDefinitionNode).selectionSet, visitWithTypeInfo(typeInfo, { enter(node) { const parentType = typeInfo.getParentType(); diff --git a/src/utilities/__tests__/assertValidName-test.js b/src/utilities/__tests__/assertValidName-test.ts similarity index 93% rename from src/utilities/__tests__/assertValidName-test.js rename to src/utilities/__tests__/assertValidName-test.ts index a05c694bd3..abf0193b9b 100644 --- a/src/utilities/__tests__/assertValidName-test.js +++ b/src/utilities/__tests__/assertValidName-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -17,7 +15,7 @@ describe('assertValidName()', () => { }); it('throws for non-strings', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type expect(() => assertValidName({})).to.throw('Expected name to be a string.'); }); diff --git a/src/utilities/__tests__/astFromValue-test.js b/src/utilities/__tests__/astFromValue-test.ts similarity index 99% rename from src/utilities/__tests__/astFromValue-test.js rename to src/utilities/__tests__/astFromValue-test.ts index 123f4ea27f..e473c7be40 100644 --- a/src/utilities/__tests__/astFromValue-test.js +++ b/src/utilities/__tests__/astFromValue-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/buildASTSchema-benchmark.js b/src/utilities/__tests__/buildASTSchema-benchmark.ts similarity index 95% rename from src/utilities/__tests__/buildASTSchema-benchmark.js rename to src/utilities/__tests__/buildASTSchema-benchmark.ts index 9a4a276959..dfb9f1d253 100644 --- a/src/utilities/__tests__/buildASTSchema-benchmark.js +++ b/src/utilities/__tests__/buildASTSchema-benchmark.ts @@ -1,5 +1,3 @@ -// @flow strict - import { parse } from '../../language/parser'; import { buildASTSchema } from '../buildASTSchema'; diff --git a/src/utilities/__tests__/buildASTSchema-test.js b/src/utilities/__tests__/buildASTSchema-test.ts similarity index 97% rename from src/utilities/__tests__/buildASTSchema-test.js rename to src/utilities/__tests__/buildASTSchema-test.ts index 25a353a869..29760e059d 100644 --- a/src/utilities/__tests__/buildASTSchema-test.js +++ b/src/utilities/__tests__/buildASTSchema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -34,19 +32,25 @@ import { assertUnionType, assertInterfaceType, assertScalarType, + GraphQLNamedType, } from '../../type/definition'; import { graphqlSync } from '../../graphql'; import { printType, printSchema } from '../printSchema'; -import { buildASTSchema, buildSchema } from '../buildASTSchema'; +import type { DefinitionNode, ASTNode } from '../../language/ast'; +import { + buildASTSchema, + buildSchema, + BuildSchemaOptions, +} from '../buildASTSchema'; /** * This function does a full cycle of going from a string with the contents of * the SDL, parsed in a schema AST, materializing that schema AST into an * in-memory GraphQLSchema, and then finally printing that object into the SDL */ -function cycleSDL(sdl, options) { +function cycleSDL(sdl: string, options?: BuildSchemaOptions) { const ast = parse(sdl); const schema = buildASTSchema(ast, options); @@ -54,16 +58,20 @@ function cycleSDL(sdl, options) { return printSchema(schema, { commentDescriptions }); } -function printASTNode(obj) { +function printASTNode(obj?: null | { astNode?: null | ASTNode }) { invariant(obj?.astNode != null); + // @ts-expect-error - might be null, but we know it's there return print(obj.astNode); } -function printAllASTNodes(obj) { +function printAllASTNodes(obj: GraphQLNamedType) { invariant(obj.astNode != null && obj.extensionASTNodes != null); return print({ kind: Kind.DOCUMENT, - definitions: [obj.astNode, ...obj.extensionASTNodes], + definitions: [ + obj.astNode as DefinitionNode, + ...(obj.extensionASTNodes as Array), + ], }); } @@ -94,7 +102,7 @@ describe('Schema Builder', () => { const source = '{ add(x: 34, y: 55) }'; const rootValue = { - add: ({ x, y }) => x + y, + add: ({ x, y }: { x: number; y: number }) => x + y, }; expect(graphqlSync({ schema, source, rootValue })).to.deep.equal({ data: { add: 89 }, @@ -1120,12 +1128,12 @@ describe('Schema Builder', () => { }); it('Rejects invalid AST', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid arg expect(() => buildASTSchema(null)).to.throw( 'Must provide valid Document AST', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid arg expect(() => buildASTSchema({})).to.throw( 'Must provide valid Document AST', ); diff --git a/src/utilities/__tests__/buildClientSchema-test.js b/src/utilities/__tests__/buildClientSchema-test.ts similarity index 96% rename from src/utilities/__tests__/buildClientSchema-test.js rename to src/utilities/__tests__/buildClientSchema-test.ts index 04fdb0ef7e..9299c1258b 100644 --- a/src/utilities/__tests__/buildClientSchema-test.js +++ b/src/utilities/__tests__/buildClientSchema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -79,7 +77,7 @@ describe('Type System: build schema from introspection', () => { const schema = buildSchema(sdl); const introspection = introspectionFromSchema(schema); - // $DisableFlowOnNegativeTest + // @ts-expect-error - trying to delete readonly field delete introspection.__schema.queryType; const clientSchema = buildClientSchema(introspection); @@ -483,7 +481,7 @@ describe('Type System: build schema from introspection', () => { const schema = buildSchema(sdl); const introspection = introspectionFromSchema(schema); - // $DisableFlowOnNegativeTest + // @ts-expect-error - trying to delete read only delete introspection.__schema.directives; const clientSchema = buildClientSchema(introspection); @@ -604,12 +602,12 @@ describe('Type System: build schema from introspection', () => { `); it('throws when introspection is missing __schema property', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type expect(() => buildClientSchema(null)).to.throw( 'Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: null.', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid type expect(() => buildClientSchema({})).to.throw( 'Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: {}.', ); @@ -618,7 +616,7 @@ describe('Type System: build schema from introspection', () => { it('throws when referenced unknown type', () => { const introspection = introspectionFromSchema(dummySchema); - // $DisableFlowOnNegativeTest + // @ts-expect-error - access to read only introspection.__schema.types = introspection.__schema.types.filter( ({ name }) => name !== 'Query', ); @@ -636,7 +634,7 @@ describe('Type System: build schema from introspection', () => { `); const introspection = introspectionFromSchema(schema); - // $DisableFlowOnNegativeTest + // @ts-expect-error - access to read only introspection.__schema.types = introspection.__schema.types.filter( ({ name }) => name !== 'Float', ); @@ -651,7 +649,7 @@ describe('Type System: build schema from introspection', () => { expect(introspection).to.have.nested.property('__schema.queryType.name'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete introspection.__schema.queryType.name; expect(() => buildClientSchema(introspection)).to.throw( @@ -667,7 +665,7 @@ describe('Type System: build schema from introspection', () => { expect(queryTypeIntrospection).to.have.property('kind'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete queryTypeIntrospection.kind; expect(() => buildClientSchema(introspection)).to.throw( @@ -683,7 +681,7 @@ describe('Type System: build schema from introspection', () => { expect(queryTypeIntrospection).to.have.property('interfaces'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete queryTypeIntrospection.interfaces; expect(() => buildClientSchema(introspection)).to.throw( @@ -698,7 +696,7 @@ describe('Type System: build schema from introspection', () => { ); expect(someInterfaceIntrospection).to.have.property('interfaces'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - access to read only someInterfaceIntrospection.interfaces = null; const clientSchema = buildClientSchema(introspection); @@ -713,7 +711,7 @@ describe('Type System: build schema from introspection', () => { expect(queryTypeIntrospection).to.have.property('fields'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete queryTypeIntrospection.fields; expect(() => buildClientSchema(introspection)).to.throw( @@ -729,7 +727,7 @@ describe('Type System: build schema from introspection', () => { expect(queryTypeIntrospection).to.have.nested.property('fields[0].args'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete queryTypeIntrospection.fields[0].args; expect(() => buildClientSchema(introspection)).to.throw( @@ -747,7 +745,7 @@ describe('Type System: build schema from introspection', () => { 'fields[0].args[0].type.name', 'String', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - access read only queryTypeIntrospection.fields[0].args[0].type.name = 'SomeUnion'; expect(() => buildClientSchema(introspection)).to.throw( @@ -765,7 +763,7 @@ describe('Type System: build schema from introspection', () => { 'fields[0].type.name', 'String', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - access read only queryTypeIntrospection.fields[0].type.name = 'SomeInputObject'; expect(() => buildClientSchema(introspection)).to.throw( @@ -781,7 +779,7 @@ describe('Type System: build schema from introspection', () => { expect(someUnionIntrospection).to.have.property('possibleTypes'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete someUnionIntrospection.possibleTypes; expect(() => buildClientSchema(introspection)).to.throw( @@ -797,7 +795,7 @@ describe('Type System: build schema from introspection', () => { expect(someEnumIntrospection).to.have.property('enumValues'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete someEnumIntrospection.enumValues; expect(() => buildClientSchema(introspection)).to.throw( @@ -813,7 +811,7 @@ describe('Type System: build schema from introspection', () => { expect(someInputObjectIntrospection).to.have.property('inputFields'); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete someInputObjectIntrospection.inputFields; expect(() => buildClientSchema(introspection)).to.throw( @@ -830,7 +828,7 @@ describe('Type System: build schema from introspection', () => { locations: ['QUERY'], }); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete someDirectiveIntrospection.locations; expect(() => buildClientSchema(introspection)).to.throw( @@ -847,7 +845,7 @@ describe('Type System: build schema from introspection', () => { args: [], }); - // $DisableFlowOnNegativeTest + // @ts-expect-error - delete read only delete someDirectiveIntrospection.args; expect(() => buildClientSchema(introspection)).to.throw( diff --git a/src/utilities/__tests__/coerceInputValue-test.js b/src/utilities/__tests__/coerceInputValue-test.ts similarity index 94% rename from src/utilities/__tests__/coerceInputValue-test.js rename to src/utilities/__tests__/coerceInputValue-test.ts index 7675ff44e3..3eb32533e3 100644 --- a/src/utilities/__tests__/coerceInputValue-test.js +++ b/src/utilities/__tests__/coerceInputValue-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -12,29 +10,39 @@ import { GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType, + GraphQLInputType, } from '../../type/definition'; import { coerceInputValue } from '../coerceInputValue'; -function expectValue(result) { +type ErrorsArray = Array<{ + path: ReadonlyArray; + value: any; + error: string; +}>; + +function expectValue(result: { errors?: ErrorsArray; value?: any }) { expect(result.errors).to.deep.equal([]); return expect(result.value); } -function expectErrors(result) { +function expectErrors(result: { errors?: ErrorsArray }) { return expect(result.errors); } describe('coerceInputValue', () => { - function coerceValue(inputValue, type) { - const errors = []; + function coerceValue(inputValue: V, type: GraphQLInputType) { + const errors: ErrorsArray = []; + + const value = coerceInputValue( + inputValue, + type, + (path, invalidValue, error) => { + errors.push({ path, value: invalidValue, error: error.message }); + }, + ); - const value = coerceInputValue(inputValue, type, onError); return { errors, value }; - - function onError(path, invalidValue, error) { - errors.push({ path, value: invalidValue, error: error.message }); - } } describe('for GraphQLNonNull', () => { @@ -262,7 +270,7 @@ describe('coerceInputValue', () => { }); describe('for GraphQLInputObject with default value', () => { - const TestInputObject = (defaultValue) => + const TestInputObject = (defaultValue: T) => new GraphQLInputObjectType({ name: 'TestInputObject', fields: { diff --git a/src/utilities/__tests__/concatAST-test.js b/src/utilities/__tests__/concatAST-test.ts similarity index 97% rename from src/utilities/__tests__/concatAST-test.js rename to src/utilities/__tests__/concatAST-test.ts index fc493ec905..089b36e9dd 100644 --- a/src/utilities/__tests__/concatAST-test.js +++ b/src/utilities/__tests__/concatAST-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/extendSchema-test.js b/src/utilities/__tests__/extendSchema-test.ts similarity index 97% rename from src/utilities/__tests__/extendSchema-test.js rename to src/utilities/__tests__/extendSchema-test.ts index 3c2ecb9798..81d47cd988 100644 --- a/src/utilities/__tests__/extendSchema-test.js +++ b/src/utilities/__tests__/extendSchema-test.ts @@ -1,8 +1,8 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; +import type { DefinitionNode, ASTNode } from '../../language/ast'; + import dedent from '../../__testUtils__/dedent'; import invariant from '../../jsutils/invariant'; @@ -37,15 +37,21 @@ import { printSchema } from '../printSchema'; import { extendSchema } from '../extendSchema'; import { buildSchema } from '../buildASTSchema'; -function printExtensionNodes(obj) { +function printExtensionNodes( + obj?: { extensionASTNodes?: null | ReadonlyArray } | null, +) { invariant(obj?.extensionASTNodes != null); return print({ kind: Kind.DOCUMENT, + // @ts-expect-error - might bw null, be we know it's there definitions: obj.extensionASTNodes, }); } -function printSchemaChanges(schema, extendedSchema) { +function printSchemaChanges( + schema: GraphQLSchema, + extendedSchema: GraphQLSchema, +) { const schemaDefinitions = parse(printSchema(schema)).definitions.map(print); const ast = parse(printSchema(extendedSchema)); return print({ @@ -56,8 +62,9 @@ function printSchemaChanges(schema, extendedSchema) { }); } -function printASTNode(obj) { +function printASTNode(obj?: null | { astNode?: null | ASTNode }) { invariant(obj?.astNode != null); + // @ts-expect-error - might be null, but we know it's there return print(obj.astNode); } @@ -521,12 +528,12 @@ describe('extendSchema', () => { testInterface.astNode, testType.astNode, testDirective.astNode, - ...query.extensionASTNodes, - ...someScalar.extensionASTNodes, - ...someEnum.extensionASTNodes, - ...someUnion.extensionASTNodes, - ...someInput.extensionASTNodes, - ...someInterface.extensionASTNodes, + ...query.extensionASTNodes!, + ...someScalar.extensionASTNodes!, + ...someEnum.extensionASTNodes!, + ...someUnion.extensionASTNodes!, + ...someInput.extensionASTNodes!, + ...someInterface.extensionASTNodes!, ]).to.have.members([ ...firstExtensionAST.definitions, ...secondExtensionAST.definitions, @@ -1244,12 +1251,12 @@ describe('extendSchema', () => { it('Rejects invalid AST', () => { const schema = new GraphQLSchema({}); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid AST expect(() => extendSchema(schema, null)).to.throw( 'Must provide valid Document AST', ); - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid AST expect(() => extendSchema(schema, {})).to.throw( 'Must provide valid Document AST', ); diff --git a/src/utilities/__tests__/findBreakingChanges-test.js b/src/utilities/__tests__/findBreakingChanges-test.ts similarity index 99% rename from src/utilities/__tests__/findBreakingChanges-test.js rename to src/utilities/__tests__/findBreakingChanges-test.ts index 1c5aad92a2..a4ab722084 100644 --- a/src/utilities/__tests__/findBreakingChanges-test.js +++ b/src/utilities/__tests__/findBreakingChanges-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/findDeprecatedUsages-test.js b/src/utilities/__tests__/findDeprecatedUsages-test.ts similarity index 99% rename from src/utilities/__tests__/findDeprecatedUsages-test.js rename to src/utilities/__tests__/findDeprecatedUsages-test.ts index f49c67589f..7814df129f 100644 --- a/src/utilities/__tests__/findDeprecatedUsages-test.js +++ b/src/utilities/__tests__/findDeprecatedUsages-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/getIntrospectionQuery-test.js b/src/utilities/__tests__/getIntrospectionQuery-test.ts similarity index 99% rename from src/utilities/__tests__/getIntrospectionQuery-test.js rename to src/utilities/__tests__/getIntrospectionQuery-test.ts index 462d683acf..3a6fad2c4b 100644 --- a/src/utilities/__tests__/getIntrospectionQuery-test.js +++ b/src/utilities/__tests__/getIntrospectionQuery-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/getOperationAST-test.js b/src/utilities/__tests__/getOperationAST-test.ts similarity index 99% rename from src/utilities/__tests__/getOperationAST-test.js rename to src/utilities/__tests__/getOperationAST-test.ts index 8bc4c1646a..029dd7706e 100644 --- a/src/utilities/__tests__/getOperationAST-test.js +++ b/src/utilities/__tests__/getOperationAST-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/getOperationRootType-test.js b/src/utilities/__tests__/getOperationRootType-test.ts similarity index 90% rename from src/utilities/__tests__/getOperationRootType-test.js rename to src/utilities/__tests__/getOperationRootType-test.ts index 5f811e9102..c614958a0f 100644 --- a/src/utilities/__tests__/getOperationRootType-test.js +++ b/src/utilities/__tests__/getOperationRootType-test.ts @@ -1,8 +1,12 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; +import type { + DocumentNode, + OperationDefinitionNode, + SchemaDefinitionNode, +} from '../../language/ast'; + import invariant from '../../jsutils/invariant'; import { Kind } from '../../language/kinds'; @@ -35,10 +39,11 @@ const subscriptionType = new GraphQLObjectType({ }), }); -function getOperationNode(doc) { +function getOperationNode(doc: DocumentNode): OperationDefinitionNode { const operationNode = doc.definitions[0]; - invariant(operationNode && operationNode.kind === Kind.OPERATION_DEFINITION); - return operationNode; + invariant(operationNode.kind === Kind.OPERATION_DEFINITION); + + return operationNode as OperationDefinitionNode; } describe('getOperationRootType', () => { @@ -77,12 +82,12 @@ describe('getOperationRootType', () => { `); const schemaNode = doc.definitions[0]; - invariant(schemaNode && schemaNode.kind === Kind.SCHEMA_DEFINITION); + invariant(schemaNode.kind === Kind.SCHEMA_DEFINITION); const [ queryNode, mutationNode, subscriptionNode, - ] = schemaNode.operationTypes; + ] = (schemaNode as SchemaDefinitionNode).operationTypes; expect(getOperationRootType(testSchema, queryNode)).to.equal(queryType); expect(getOperationRootType(testSchema, mutationNode)).to.equal( @@ -155,7 +160,7 @@ describe('getOperationRootType', () => { operation: 'non_existent_operation', }; - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid operation kind expect(() => getOperationRootType(testSchema, operationNode)).to.throw( 'Can only have query, mutation and subscription operations.', ); diff --git a/src/utilities/__tests__/introspectionFromSchema-test.js b/src/utilities/__tests__/introspectionFromSchema-test.ts similarity index 92% rename from src/utilities/__tests__/introspectionFromSchema-test.js rename to src/utilities/__tests__/introspectionFromSchema-test.ts index 2e527a0bec..0e554e7244 100644 --- a/src/utilities/__tests__/introspectionFromSchema-test.js +++ b/src/utilities/__tests__/introspectionFromSchema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -12,8 +10,9 @@ import { GraphQLObjectType } from '../../type/definition'; import { printSchema } from '../printSchema'; import { buildClientSchema } from '../buildClientSchema'; import { introspectionFromSchema } from '../introspectionFromSchema'; +import { IntrospectionQuery } from '../getIntrospectionQuery'; -function introspectionToSDL(introspection) { +function introspectionToSDL(introspection: IntrospectionQuery) { return printSchema(buildClientSchema(introspection)); } diff --git a/src/utilities/__tests__/lexicographicSortSchema-test.js b/src/utilities/__tests__/lexicographicSortSchema-test.ts similarity index 99% rename from src/utilities/__tests__/lexicographicSortSchema-test.js rename to src/utilities/__tests__/lexicographicSortSchema-test.ts index ebdf149cbd..fa4c60aafb 100644 --- a/src/utilities/__tests__/lexicographicSortSchema-test.js +++ b/src/utilities/__tests__/lexicographicSortSchema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -9,7 +7,7 @@ import { printSchema } from '../printSchema'; import { buildSchema } from '../buildASTSchema'; import { lexicographicSortSchema } from '../lexicographicSortSchema'; -function sortSDL(sdl) { +function sortSDL(sdl: string) { const schema = buildSchema(sdl); return printSchema(lexicographicSortSchema(schema)); } diff --git a/src/utilities/__tests__/printSchema-test.js b/src/utilities/__tests__/printSchema-test.ts similarity index 99% rename from src/utilities/__tests__/printSchema-test.js rename to src/utilities/__tests__/printSchema-test.ts index 6b5bbd7414..172197321c 100644 --- a/src/utilities/__tests__/printSchema-test.js +++ b/src/utilities/__tests__/printSchema-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -19,19 +17,20 @@ import { GraphQLUnionType, GraphQLEnumType, GraphQLInputObjectType, + GraphQLFieldConfig, } from '../../type/definition'; import { buildSchema } from '../buildASTSchema'; import { printSchema, printIntrospectionSchema } from '../printSchema'; -function expectPrintedSchema(schema) { +function expectPrintedSchema(schema: GraphQLSchema) { const schemaText = printSchema(schema); // keep printSchema and buildSchema in sync expect(printSchema(buildSchema(schemaText))).to.equal(schemaText); return expect(schemaText); } -function buildSingleFieldSchema(fieldConfig) { +function buildSingleFieldSchema(fieldConfig: GraphQLFieldConfig) { const Query = new GraphQLObjectType({ name: 'Query', fields: { singleField: fieldConfig }, @@ -153,7 +152,6 @@ describe('Type System Printer', () => { }); expectPrintedSchema(schema).to.equal( - // $FlowFixMe dedent(String.raw` type Query { singleField(argOne: String = "tes\t de\fault"): String diff --git a/src/utilities/__tests__/separateOperations-test.js b/src/utilities/__tests__/separateOperations-test.ts similarity index 99% rename from src/utilities/__tests__/separateOperations-test.js rename to src/utilities/__tests__/separateOperations-test.ts index a2d4a65758..4240705396 100644 --- a/src/utilities/__tests__/separateOperations-test.js +++ b/src/utilities/__tests__/separateOperations-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; diff --git a/src/utilities/__tests__/stripIgnoredCharacters-fuzz.js b/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts similarity index 92% rename from src/utilities/__tests__/stripIgnoredCharacters-fuzz.js rename to src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts index c853e1e768..9bc1ff8d27 100644 --- a/src/utilities/__tests__/stripIgnoredCharacters-fuzz.js +++ b/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import dedent from '../../__testUtils__/dedent'; @@ -13,12 +11,12 @@ import { Source } from '../../language/source'; import { stripIgnoredCharacters } from '../stripIgnoredCharacters'; -function lexValue(str) { +function lexValue(str: string): string { const lexer = new Lexer(new Source(str)); const value = lexer.advance().value; invariant(lexer.advance().kind === '', 'Expected EOF'); - return value; + return value as string; } describe('stripIgnoredCharacters', () => { @@ -29,6 +27,7 @@ describe('stripIgnoredCharacters', () => { allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'], maxLength: 7, })) { + // FIXME: Prefer string literal over plus operand const testStr = '"""' + fuzzStr + '"""'; let testValue; diff --git a/src/utilities/__tests__/stripIgnoredCharacters-test.js b/src/utilities/__tests__/stripIgnoredCharacters-test.ts similarity index 98% rename from src/utilities/__tests__/stripIgnoredCharacters-test.js rename to src/utilities/__tests__/stripIgnoredCharacters-test.ts index 8ac48694f0..2994580acf 100644 --- a/src/utilities/__tests__/stripIgnoredCharacters-test.js +++ b/src/utilities/__tests__/stripIgnoredCharacters-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -60,7 +58,7 @@ const nonPunctuatorTokens = [ '"""block\nstring\nvalue"""', // StringValue(BlockString) ]; -function lexValue(str) { +function lexValue(str: string) { const lexer = new Lexer(new Source(str)); const value = lexer.advance().value; @@ -68,9 +66,9 @@ function lexValue(str) { return value; } -function expectStripped(docString) { +function expectStripped(docString: string) { return { - toEqual(expected) { + toEqual(expected: any) { const stripped = stripIgnoredCharacters(docString); invariant( @@ -101,14 +99,14 @@ function expectStripped(docString) { describe('stripIgnoredCharacters', () => { it('asserts that a source was provided', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid source expect(() => stripIgnoredCharacters()).to.throw( 'Must provide string or Source. Received: undefined.', ); }); it('asserts that a valid source was provided', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid source expect(() => stripIgnoredCharacters({})).to.throw( 'Must provide string or Source. Received: {}.', ); @@ -400,7 +398,7 @@ describe('stripIgnoredCharacters', () => { }); it('strips ignored characters inside block strings', () => { - function expectStrippedString(blockStr) { + function expectStrippedString(blockStr: string) { const originalValue = lexValue(blockStr); const strippedValue = lexValue(stripIgnoredCharacters(blockStr)); diff --git a/src/utilities/__tests__/typeComparators-test.js b/src/utilities/__tests__/typeComparators-test.ts similarity index 98% rename from src/utilities/__tests__/typeComparators-test.js rename to src/utilities/__tests__/typeComparators-test.ts index f2123c576b..b69cff54de 100644 --- a/src/utilities/__tests__/typeComparators-test.js +++ b/src/utilities/__tests__/typeComparators-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -11,6 +9,7 @@ import { GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType, + GraphQLFieldConfigMap, } from '../../type/definition'; import { isEqualType, isTypeSubTypeOf } from '../typeComparators'; @@ -49,7 +48,7 @@ describe('typeComparators', () => { }); describe('isTypeSubTypeOf', () => { - function testSchema(fields) { + function testSchema(fields: GraphQLFieldConfigMap) { return new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', diff --git a/src/utilities/__tests__/valueFromAST-test.js b/src/utilities/__tests__/valueFromAST-test.ts similarity index 97% rename from src/utilities/__tests__/valueFromAST-test.js rename to src/utilities/__tests__/valueFromAST-test.ts index 91c82a2fed..e57fa30077 100644 --- a/src/utilities/__tests__/valueFromAST-test.js +++ b/src/utilities/__tests__/valueFromAST-test.ts @@ -1,8 +1,8 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; +import type { StringValueNode } from '../../language/ast'; + import invariant from '../../jsutils/invariant'; import identityFunc from '../../jsutils/identityFunc'; @@ -20,12 +20,17 @@ import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull, + GraphQLInputType, } from '../../type/definition'; import { valueFromAST } from '../valueFromAST'; describe('valueFromAST', () => { - function expectValueFrom(valueText, type, variables) { + function expectValueFrom( + valueText: string, + type: GraphQLInputType, + variables?: Record, + ) { const ast = parseValue(valueText); const value = valueFromAST(ast, type, variables); return expect(value); @@ -62,7 +67,7 @@ describe('valueFromAST', () => { name: 'PassthroughScalar', parseLiteral(node) { invariant(node.kind === 'StringValue'); - return node.value; + return (node as StringValueNode).value; }, parseValue: identityFunc, }); diff --git a/src/utilities/__tests__/valueFromASTUntyped-test.js b/src/utilities/__tests__/valueFromASTUntyped-test.ts similarity index 90% rename from src/utilities/__tests__/valueFromASTUntyped-test.js rename to src/utilities/__tests__/valueFromASTUntyped-test.ts index de32875d8f..3e093cfdfd 100644 --- a/src/utilities/__tests__/valueFromASTUntyped-test.js +++ b/src/utilities/__tests__/valueFromASTUntyped-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -8,11 +6,15 @@ import { parseValue } from '../../language/parser'; import { valueFromASTUntyped } from '../valueFromASTUntyped'; describe('valueFromASTUntyped', () => { - function testCase(valueText, expected) { + function testCase(valueText: string, expected: T) { expect(valueFromASTUntyped(parseValue(valueText))).to.deep.equal(expected); } - function testCaseWithVars(valueText, variables, expected) { + function testCaseWithVars( + valueText: string, + variables: null | Record, + expected: T, + ) { expect(valueFromASTUntyped(parseValue(valueText), variables)).to.deep.equal( expected, ); diff --git a/src/validation/__tests__/ExecutableDefinitionsRule-test.js b/src/validation/__tests__/ExecutableDefinitionsRule-test.ts similarity index 95% rename from src/validation/__tests__/ExecutableDefinitionsRule-test.js rename to src/validation/__tests__/ExecutableDefinitionsRule-test.ts index 1779d23209..4409767b5b 100644 --- a/src/validation/__tests__/ExecutableDefinitionsRule-test.js +++ b/src/validation/__tests__/ExecutableDefinitionsRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { ExecutableDefinitionsRule } from '../rules/ExecutableDefinitionsRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(ExecutableDefinitionsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/FieldsOnCorrectTypeRule-test.js b/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts similarity index 97% rename from src/validation/__tests__/FieldsOnCorrectTypeRule-test.js rename to src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts index b53d129d62..0bd8e0d886 100644 --- a/src/validation/__tests__/FieldsOnCorrectTypeRule-test.js +++ b/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -10,13 +8,15 @@ import { buildSchema } from '../../utilities/buildASTSchema'; import { validate } from '../validate'; import { FieldsOnCorrectTypeRule } from '../rules/FieldsOnCorrectTypeRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(FieldsOnCorrectTypeRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } @@ -257,7 +257,7 @@ describe('Validate: Fields on correct type', () => { }); describe('Fields on correct type error message', () => { - function expectErrorMessage(schema, queryStr) { + function expectErrorMessage(schema: GraphQLSchema, queryStr: string) { const errors = validate(schema, parse(queryStr), [ FieldsOnCorrectTypeRule, ]); diff --git a/src/validation/__tests__/FragmentsOnCompositeTypesRule-test.js b/src/validation/__tests__/FragmentsOnCompositeTypesRule-test.ts similarity index 97% rename from src/validation/__tests__/FragmentsOnCompositeTypesRule-test.js rename to src/validation/__tests__/FragmentsOnCompositeTypesRule-test.ts index 4bb7286efc..a9b7ec17d7 100644 --- a/src/validation/__tests__/FragmentsOnCompositeTypesRule-test.js +++ b/src/validation/__tests__/FragmentsOnCompositeTypesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { FragmentsOnCompositeTypesRule } from '../rules/FragmentsOnCompositeTypesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(FragmentsOnCompositeTypesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/KnownArgumentNamesRule-test.js b/src/validation/__tests__/KnownArgumentNamesRule-test.ts similarity index 96% rename from src/validation/__tests__/KnownArgumentNamesRule-test.js rename to src/validation/__tests__/KnownArgumentNamesRule-test.ts index 1746236216..98a5021226 100644 --- a/src/validation/__tests__/KnownArgumentNamesRule-test.js +++ b/src/validation/__tests__/KnownArgumentNamesRule-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; @@ -9,17 +7,19 @@ import { KnownArgumentNamesOnDirectivesRule, } from '../rules/KnownArgumentNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors, expectSDLValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(KnownArgumentNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors( schema, KnownArgumentNamesOnDirectivesRule, @@ -27,7 +27,7 @@ function expectSDLErrors(sdlStr, schema) { ); } -function expectValidSDL(sdlStr) { +function expectValidSDL(sdlStr: string) { expectSDLErrors(sdlStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/KnownDirectivesRule-test.js b/src/validation/__tests__/KnownDirectivesRule-test.ts similarity index 97% rename from src/validation/__tests__/KnownDirectivesRule-test.js rename to src/validation/__tests__/KnownDirectivesRule-test.ts index acc0b61a9a..22e89d47aa 100644 --- a/src/validation/__tests__/KnownDirectivesRule-test.js +++ b/src/validation/__tests__/KnownDirectivesRule-test.ts @@ -1,26 +1,26 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { KnownDirectivesRule } from '../rules/KnownDirectivesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors, expectSDLValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(KnownDirectivesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, KnownDirectivesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/KnownFragmentNamesRule-test.js b/src/validation/__tests__/KnownFragmentNamesRule-test.ts similarity index 94% rename from src/validation/__tests__/KnownFragmentNamesRule-test.js rename to src/validation/__tests__/KnownFragmentNamesRule-test.ts index 551f967a35..68477de864 100644 --- a/src/validation/__tests__/KnownFragmentNamesRule-test.js +++ b/src/validation/__tests__/KnownFragmentNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { KnownFragmentNamesRule } from '../rules/KnownFragmentNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(KnownFragmentNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/KnownTypeNamesRule-test.js b/src/validation/__tests__/KnownTypeNamesRule-test.ts similarity index 96% rename from src/validation/__tests__/KnownTypeNamesRule-test.js rename to src/validation/__tests__/KnownTypeNamesRule-test.ts index adfe354a28..8866a95029 100644 --- a/src/validation/__tests__/KnownTypeNamesRule-test.js +++ b/src/validation/__tests__/KnownTypeNamesRule-test.ts @@ -1,34 +1,34 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { KnownTypeNamesRule } from '../rules/KnownTypeNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors, expectValidationErrorsWithSchema, expectSDLValidationErrors, } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(KnownTypeNamesRule, queryStr); } -function expectErrorsWithSchema(schema, queryStr) { +function expectErrorsWithSchema(schema: GraphQLSchema, queryStr: string) { return expectValidationErrorsWithSchema(schema, KnownTypeNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, KnownTypeNamesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/LoneAnonymousOperationRule-test.js b/src/validation/__tests__/LoneAnonymousOperationRule-test.ts similarity index 95% rename from src/validation/__tests__/LoneAnonymousOperationRule-test.js rename to src/validation/__tests__/LoneAnonymousOperationRule-test.ts index 9ca95088ce..191870dd03 100644 --- a/src/validation/__tests__/LoneAnonymousOperationRule-test.js +++ b/src/validation/__tests__/LoneAnonymousOperationRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { LoneAnonymousOperationRule } from '../rules/LoneAnonymousOperationRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(LoneAnonymousOperationRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/LoneSchemaDefinitionRule-test.js b/src/validation/__tests__/LoneSchemaDefinitionRule-test.ts similarity index 93% rename from src/validation/__tests__/LoneSchemaDefinitionRule-test.js rename to src/validation/__tests__/LoneSchemaDefinitionRule-test.ts index 34190eab9b..25d605207c 100644 --- a/src/validation/__tests__/LoneSchemaDefinitionRule-test.js +++ b/src/validation/__tests__/LoneSchemaDefinitionRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { LoneSchemaDefinitionRule } from '../rules/LoneSchemaDefinitionRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, LoneSchemaDefinitionRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/NoFragmentCyclesRule-test.js b/src/validation/__tests__/NoFragmentCyclesRule-test.ts similarity index 98% rename from src/validation/__tests__/NoFragmentCyclesRule-test.js rename to src/validation/__tests__/NoFragmentCyclesRule-test.ts index 07f42cd766..94c3d1879b 100644 --- a/src/validation/__tests__/NoFragmentCyclesRule-test.js +++ b/src/validation/__tests__/NoFragmentCyclesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { NoFragmentCyclesRule } from '../rules/NoFragmentCyclesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(NoFragmentCyclesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/NoUndefinedVariablesRule-test.js b/src/validation/__tests__/NoUndefinedVariablesRule-test.ts similarity index 99% rename from src/validation/__tests__/NoUndefinedVariablesRule-test.js rename to src/validation/__tests__/NoUndefinedVariablesRule-test.ts index 5c90a00b89..6969c89d8d 100644 --- a/src/validation/__tests__/NoUndefinedVariablesRule-test.js +++ b/src/validation/__tests__/NoUndefinedVariablesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { NoUndefinedVariablesRule } from '../rules/NoUndefinedVariablesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(NoUndefinedVariablesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/NoUnusedFragmentsRule-test.js b/src/validation/__tests__/NoUnusedFragmentsRule-test.ts similarity index 97% rename from src/validation/__tests__/NoUnusedFragmentsRule-test.js rename to src/validation/__tests__/NoUnusedFragmentsRule-test.ts index 8d0e3b9498..d90b1b271a 100644 --- a/src/validation/__tests__/NoUnusedFragmentsRule-test.js +++ b/src/validation/__tests__/NoUnusedFragmentsRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { NoUnusedFragmentsRule } from '../rules/NoUnusedFragmentsRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(NoUnusedFragmentsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/NoUnusedVariablesRule-test.js b/src/validation/__tests__/NoUnusedVariablesRule-test.ts similarity index 98% rename from src/validation/__tests__/NoUnusedVariablesRule-test.js rename to src/validation/__tests__/NoUnusedVariablesRule-test.ts index 4eea095e0c..aa111b11f5 100644 --- a/src/validation/__tests__/NoUnusedVariablesRule-test.js +++ b/src/validation/__tests__/NoUnusedVariablesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { NoUnusedVariablesRule } from '../rules/NoUnusedVariablesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(NoUnusedVariablesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.js b/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts similarity index 98% rename from src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.js rename to src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts index 8d46357e89..f01b7b2a93 100644 --- a/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.js +++ b/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts @@ -1,25 +1,25 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { OverlappingFieldsCanBeMergedRule } from '../rules/OverlappingFieldsCanBeMergedRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors, expectValidationErrorsWithSchema, } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(OverlappingFieldsCanBeMergedRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectErrorsWithSchema(schema, queryStr) { +function expectErrorsWithSchema(schema: GraphQLSchema, queryStr: string) { return expectValidationErrorsWithSchema( schema, OverlappingFieldsCanBeMergedRule, @@ -27,7 +27,7 @@ function expectErrorsWithSchema(schema, queryStr) { ); } -function expectValidWithSchema(schema, queryStr) { +function expectValidWithSchema(schema: GraphQLSchema, queryStr: string) { expectErrorsWithSchema(schema, queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/PossibleFragmentSpreadsRule-test.js b/src/validation/__tests__/PossibleFragmentSpreadsRule-test.ts similarity index 98% rename from src/validation/__tests__/PossibleFragmentSpreadsRule-test.js rename to src/validation/__tests__/PossibleFragmentSpreadsRule-test.ts index 6f70058125..267dbd3b38 100644 --- a/src/validation/__tests__/PossibleFragmentSpreadsRule-test.js +++ b/src/validation/__tests__/PossibleFragmentSpreadsRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { PossibleFragmentSpreadsRule } from '../rules/PossibleFragmentSpreadsRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(PossibleFragmentSpreadsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/PossibleTypeExtensionsRule-test.js b/src/validation/__tests__/PossibleTypeExtensionsRule-test.ts similarity index 97% rename from src/validation/__tests__/PossibleTypeExtensionsRule-test.js rename to src/validation/__tests__/PossibleTypeExtensionsRule-test.ts index 4f1bcde0c3..100d8c1804 100644 --- a/src/validation/__tests__/PossibleTypeExtensionsRule-test.js +++ b/src/validation/__tests__/PossibleTypeExtensionsRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { PossibleTypeExtensionsRule } from '../rules/PossibleTypeExtensionsRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, PossibleTypeExtensionsRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.js b/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts similarity index 97% rename from src/validation/__tests__/ProvidedRequiredArgumentsRule-test.js rename to src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts index d7198b481e..45c40e4661 100644 --- a/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.js +++ b/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; @@ -9,17 +7,19 @@ import { ProvidedRequiredArgumentsOnDirectivesRule, } from '../rules/ProvidedRequiredArgumentsRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectValidationErrors, expectSDLValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(ProvidedRequiredArgumentsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors( schema, ProvidedRequiredArgumentsOnDirectivesRule, @@ -27,7 +27,7 @@ function expectSDLErrors(sdlStr, schema) { ); } -function expectValidSDL(sdlStr) { +function expectValidSDL(sdlStr: string) { expectSDLErrors(sdlStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/ScalarLeafsRule-test.js b/src/validation/__tests__/ScalarLeafsRule-test.ts similarity index 97% rename from src/validation/__tests__/ScalarLeafsRule-test.js rename to src/validation/__tests__/ScalarLeafsRule-test.ts index 5f6cc30ab1..a441d4fcc7 100644 --- a/src/validation/__tests__/ScalarLeafsRule-test.js +++ b/src/validation/__tests__/ScalarLeafsRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { ScalarLeafsRule } from '../rules/ScalarLeafsRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(ScalarLeafsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/SingleFieldSubscriptionsRule-test.js b/src/validation/__tests__/SingleFieldSubscriptionsRule-test.ts similarity index 96% rename from src/validation/__tests__/SingleFieldSubscriptionsRule-test.js rename to src/validation/__tests__/SingleFieldSubscriptionsRule-test.ts index bbd55b0d8c..c8ddc5add3 100644 --- a/src/validation/__tests__/SingleFieldSubscriptionsRule-test.js +++ b/src/validation/__tests__/SingleFieldSubscriptionsRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { SingleFieldSubscriptionsRule } from '../rules/SingleFieldSubscriptionsRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(SingleFieldSubscriptionsRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueArgumentNamesRule-test.js b/src/validation/__tests__/UniqueArgumentNamesRule-test.ts similarity index 97% rename from src/validation/__tests__/UniqueArgumentNamesRule-test.js rename to src/validation/__tests__/UniqueArgumentNamesRule-test.ts index a72cec64c8..a18c56bd8f 100644 --- a/src/validation/__tests__/UniqueArgumentNamesRule-test.js +++ b/src/validation/__tests__/UniqueArgumentNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { UniqueArgumentNamesRule } from '../rules/UniqueArgumentNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(UniqueArgumentNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueDirectiveNamesRule-test.js b/src/validation/__tests__/UniqueDirectiveNamesRule-test.ts similarity index 93% rename from src/validation/__tests__/UniqueDirectiveNamesRule-test.js rename to src/validation/__tests__/UniqueDirectiveNamesRule-test.ts index 65261e985c..44feac47fa 100644 --- a/src/validation/__tests__/UniqueDirectiveNamesRule-test.js +++ b/src/validation/__tests__/UniqueDirectiveNamesRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { UniqueDirectiveNamesRule } from '../rules/UniqueDirectiveNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, UniqueDirectiveNamesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueDirectivesPerLocationRule-test.js b/src/validation/__tests__/UniqueDirectivesPerLocationRule-test.ts similarity index 98% rename from src/validation/__tests__/UniqueDirectivesPerLocationRule-test.js rename to src/validation/__tests__/UniqueDirectivesPerLocationRule-test.ts index 411b6cd9d8..8a8f82f444 100644 --- a/src/validation/__tests__/UniqueDirectivesPerLocationRule-test.js +++ b/src/validation/__tests__/UniqueDirectivesPerLocationRule-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import { parse } from '../../language/parser'; @@ -7,6 +5,8 @@ import { extendSchema } from '../../utilities/extendSchema'; import { UniqueDirectivesPerLocationRule } from '../rules/UniqueDirectivesPerLocationRule'; +import { GraphQLSchema } from '../../type/schema'; + import { testSchema, expectValidationErrorsWithSchema, @@ -21,7 +21,7 @@ const extensionSDL = ` `; const schemaWithDirectives = extendSchema(testSchema, parse(extensionSDL)); -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrorsWithSchema( schemaWithDirectives, UniqueDirectivesPerLocationRule, @@ -29,11 +29,11 @@ function expectErrors(queryStr) { ); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors( schema, UniqueDirectivesPerLocationRule, diff --git a/src/validation/__tests__/UniqueEnumValueNamesRule-test.js b/src/validation/__tests__/UniqueEnumValueNamesRule-test.ts similarity index 95% rename from src/validation/__tests__/UniqueEnumValueNamesRule-test.js rename to src/validation/__tests__/UniqueEnumValueNamesRule-test.ts index f5c2db52b3..f92d8f8e63 100644 --- a/src/validation/__tests__/UniqueEnumValueNamesRule-test.js +++ b/src/validation/__tests__/UniqueEnumValueNamesRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { UniqueEnumValueNamesRule } from '../rules/UniqueEnumValueNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, UniqueEnumValueNamesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.js b/src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.ts similarity index 98% rename from src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.js rename to src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.ts index 759ad4b1a2..a4de750f51 100644 --- a/src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.js +++ b/src/validation/__tests__/UniqueFieldDefinitionNamesRule-test.ts @@ -1,14 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { UniqueFieldDefinitionNamesRule } from '../rules/UniqueFieldDefinitionNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors( schema, UniqueFieldDefinitionNamesRule, @@ -16,7 +16,7 @@ function expectSDLErrors(sdlStr, schema) { ); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueFragmentNamesRule-test.js b/src/validation/__tests__/UniqueFragmentNamesRule-test.ts similarity index 96% rename from src/validation/__tests__/UniqueFragmentNamesRule-test.js rename to src/validation/__tests__/UniqueFragmentNamesRule-test.ts index cf6a67da06..f67b462e80 100644 --- a/src/validation/__tests__/UniqueFragmentNamesRule-test.js +++ b/src/validation/__tests__/UniqueFragmentNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { UniqueFragmentNamesRule } from '../rules/UniqueFragmentNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(UniqueFragmentNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueInputFieldNamesRule-test.js b/src/validation/__tests__/UniqueInputFieldNamesRule-test.ts similarity index 96% rename from src/validation/__tests__/UniqueInputFieldNamesRule-test.js rename to src/validation/__tests__/UniqueInputFieldNamesRule-test.ts index 14b70ff8a4..8f2426db4e 100644 --- a/src/validation/__tests__/UniqueInputFieldNamesRule-test.js +++ b/src/validation/__tests__/UniqueInputFieldNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { UniqueInputFieldNamesRule } from '../rules/UniqueInputFieldNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(UniqueInputFieldNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueOperationNamesRule-test.js b/src/validation/__tests__/UniqueOperationNamesRule-test.ts similarity index 96% rename from src/validation/__tests__/UniqueOperationNamesRule-test.js rename to src/validation/__tests__/UniqueOperationNamesRule-test.ts index 6f1de34b4c..720a285d26 100644 --- a/src/validation/__tests__/UniqueOperationNamesRule-test.js +++ b/src/validation/__tests__/UniqueOperationNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { UniqueOperationNamesRule } from '../rules/UniqueOperationNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(UniqueOperationNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueOperationTypesRule-test.js b/src/validation/__tests__/UniqueOperationTypesRule-test.ts similarity index 97% rename from src/validation/__tests__/UniqueOperationTypesRule-test.js rename to src/validation/__tests__/UniqueOperationTypesRule-test.ts index cf26459103..9ef53f825a 100644 --- a/src/validation/__tests__/UniqueOperationTypesRule-test.js +++ b/src/validation/__tests__/UniqueOperationTypesRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { UniqueOperationTypesRule } from '../rules/UniqueOperationTypesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, UniqueOperationTypesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueTypeNamesRule-test.js b/src/validation/__tests__/UniqueTypeNamesRule-test.ts similarity index 95% rename from src/validation/__tests__/UniqueTypeNamesRule-test.js rename to src/validation/__tests__/UniqueTypeNamesRule-test.ts index 961116fd81..13db7144d0 100644 --- a/src/validation/__tests__/UniqueTypeNamesRule-test.js +++ b/src/validation/__tests__/UniqueTypeNamesRule-test.ts @@ -1,18 +1,18 @@ -// @flow strict - import { describe, it } from 'mocha'; import { buildSchema } from '../../utilities/buildASTSchema'; import { UniqueTypeNamesRule } from '../rules/UniqueTypeNamesRule'; +import { GraphQLSchema } from '../../type/schema'; + import { expectSDLValidationErrors } from './harness'; -function expectSDLErrors(sdlStr, schema) { +function expectSDLErrors(sdlStr: string, schema?: GraphQLSchema) { return expectSDLValidationErrors(schema, UniqueTypeNamesRule, sdlStr); } -function expectValidSDL(sdlStr, schema) { +function expectValidSDL(sdlStr: string, schema?: GraphQLSchema) { expectSDLErrors(sdlStr, schema).to.deep.equal([]); } diff --git a/src/validation/__tests__/UniqueVariableNamesRule-test.js b/src/validation/__tests__/UniqueVariableNamesRule-test.ts similarity index 94% rename from src/validation/__tests__/UniqueVariableNamesRule-test.js rename to src/validation/__tests__/UniqueVariableNamesRule-test.ts index 779d581704..4b950fb4cf 100644 --- a/src/validation/__tests__/UniqueVariableNamesRule-test.js +++ b/src/validation/__tests__/UniqueVariableNamesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { UniqueVariableNamesRule } from '../rules/UniqueVariableNamesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(UniqueVariableNamesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/ValuesOfCorrectTypeRule-test.js b/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts similarity index 99% rename from src/validation/__tests__/ValuesOfCorrectTypeRule-test.js rename to src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts index 723208a872..1831b4670d 100644 --- a/src/validation/__tests__/ValuesOfCorrectTypeRule-test.js +++ b/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { describe, it } from 'mocha'; import inspect from '../../jsutils/inspect'; @@ -15,11 +13,11 @@ import { expectValidationErrorsWithSchema, } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(ValuesOfCorrectTypeRule, queryStr); } -function expectErrorsWithSchema(schema, queryStr) { +function expectErrorsWithSchema(schema: GraphQLSchema, queryStr: string) { return expectValidationErrorsWithSchema( schema, ValuesOfCorrectTypeRule, @@ -27,11 +25,11 @@ function expectErrorsWithSchema(schema, queryStr) { ); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } -function expectValidWithSchema(schema, queryStr) { +function expectValidWithSchema(schema: GraphQLSchema, queryStr: string) { expectErrorsWithSchema(schema, queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/VariablesAreInputTypesRule-test.js b/src/validation/__tests__/VariablesAreInputTypesRule-test.ts similarity index 93% rename from src/validation/__tests__/VariablesAreInputTypesRule-test.js rename to src/validation/__tests__/VariablesAreInputTypesRule-test.ts index 6c489745d6..5a19fca650 100644 --- a/src/validation/__tests__/VariablesAreInputTypesRule-test.js +++ b/src/validation/__tests__/VariablesAreInputTypesRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { VariablesAreInputTypesRule } from '../rules/VariablesAreInputTypesRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(VariablesAreInputTypesRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/VariablesInAllowedPositionRule-test.js b/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts similarity index 99% rename from src/validation/__tests__/VariablesInAllowedPositionRule-test.js rename to src/validation/__tests__/VariablesInAllowedPositionRule-test.ts index 5654f7e955..2b9ebc5c2d 100644 --- a/src/validation/__tests__/VariablesInAllowedPositionRule-test.js +++ b/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts @@ -1,16 +1,14 @@ -// @flow strict - import { describe, it } from 'mocha'; import { VariablesInAllowedPositionRule } from '../rules/VariablesInAllowedPositionRule'; import { expectValidationErrors } from './harness'; -function expectErrors(queryStr) { +function expectErrors(queryStr: string) { return expectValidationErrors(VariablesInAllowedPositionRule, queryStr); } -function expectValid(queryStr) { +function expectValid(queryStr: string) { expectErrors(queryStr).to.deep.equal([]); } diff --git a/src/validation/__tests__/harness.js b/src/validation/__tests__/harness.ts similarity index 96% rename from src/validation/__tests__/harness.js rename to src/validation/__tests__/harness.ts index a9490e3170..ab46fa0617 100644 --- a/src/validation/__tests__/harness.js +++ b/src/validation/__tests__/harness.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { parse } from '../../language/parser'; @@ -9,10 +7,7 @@ import { GraphQLSchema } from '../../type/schema'; import { buildSchema } from '../../utilities/buildASTSchema'; import { validate, validateSDL } from '../validate'; -import { - type ValidationRule, - type SDLValidationRule, -} from '../ValidationContext'; +import { ValidationRule, SDLValidationRule } from '../ValidationContext'; export const testSchema = buildSchema(` interface Being { @@ -162,7 +157,7 @@ export function expectValidationErrors(rule: ValidationRule, queryStr: string) { } export function expectSDLValidationErrors( - schema: ?GraphQLSchema, + schema: GraphQLSchema | undefined, rule: SDLValidationRule, sdlStr: string, ) { diff --git a/src/validation/__tests__/validation-test.js b/src/validation/__tests__/validation-test.ts similarity index 88% rename from src/validation/__tests__/validation-test.js rename to src/validation/__tests__/validation-test.ts index 4ddb16d4f1..6203f2ab27 100644 --- a/src/validation/__tests__/validation-test.js +++ b/src/validation/__tests__/validation-test.ts @@ -1,5 +1,3 @@ -// @flow strict - import { expect } from 'chai'; import { describe, it } from 'mocha'; @@ -11,12 +9,13 @@ import { TypeInfo } from '../../utilities/TypeInfo'; import { buildSchema } from '../../utilities/buildASTSchema'; import { validate } from '../validate'; +import { ValidationRule } from '../ValidationContext'; import { testSchema } from './harness'; describe('Validate: Supports full validation', () => { it('rejects invalid documents', () => { - // $DisableFlowOnNegativeTest + // @ts-expect-error - invalid documents expect(() => validate(testSchema, null)).to.throw('Must provide document.'); }); @@ -97,18 +96,16 @@ describe('Validate: Supports full validation', () => { } `); - function customRule(context) { - return { - Directive(node) { - const directiveDef = context.getDirective(); - const error = new GraphQLError( - 'Reporting directive: ' + String(directiveDef), - node, - ); - context.reportError(error); - }, - }; - } + const customRule: ValidationRule = (context) => ({ + Directive(node) { + const directiveDef = context.getDirective(); + const error = new GraphQLError( + 'Reporting directive: ' + String(directiveDef), + node, + ); + context.reportError(error); + }, + }); const errors = validate(schema, doc, [customRule]); expect(errors).to.deep.equal([ @@ -130,11 +127,11 @@ describe('Validate: Limit maximum number of validation errors', () => { `; const doc = parse(query, { noLocation: true }); - function validateDocument(options) { + function validateDocument(options: { maxErrors?: number }) { return validate(testSchema, doc, undefined, undefined, options); } - function invalidFieldError(fieldName) { + function invalidFieldError(fieldName: string) { return { message: `Cannot query field "${fieldName}" on type "QueryRoot".`, locations: [], diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..fa4c43ac4b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2018", + "moduleResolution": "node", + "lib": ["es6", "esnext.asynciterable"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "./", + "noEmit": true, + "forceConsistentCasingInFileNames": true + } +}