diff --git a/integrationTests/integration-test.js b/integrationTests/integration-test.js index ff3d8cbbdec..3edab8cd2fd 100644 --- a/integrationTests/integration-test.js +++ b/integrationTests/integration-test.js @@ -53,9 +53,7 @@ describe('Integration Tests', () => { } testOnNodeProject('ts'); - testOnNodeProject('ts-esm'); testOnNodeProject('node'); testOnNodeProject('node-esm'); testOnNodeProject('webpack'); - testOnNodeProject('webpack-esm'); }); diff --git a/integrationTests/node-esm/index.js b/integrationTests/node-esm/index.js index 1d540ca0ed7..44f5afd921d 100644 --- a/integrationTests/node-esm/index.js +++ b/integrationTests/node-esm/index.js @@ -1,21 +1,20 @@ /* eslint-disable node/no-missing-import, import/no-unresolved */ import { deepStrictEqual, strictEqual } from 'assert'; -import { readFileSync } from 'fs'; // Regular import import { graphqlSync } from 'graphql'; -// import with explicit extension +// Import with explicit extension import { version } from 'graphql/version.js'; // _/index.js import import { buildSchema } from 'graphql/utilities'; -// import without explicit extension +// Import without explicit extension import { isPromise } from 'graphql/jsutils/isPromise'; -deepStrictEqual( - version, - JSON.parse(readFileSync('./node_modules/graphql/package.json')).version, -); +// Import package.json +import pkg from 'graphql/package.json'; + +deepStrictEqual(version, pkg.version); const schema = buildSchema('type Query { hello: String }'); @@ -33,3 +32,8 @@ deepStrictEqual(result, { }); strictEqual(isPromise(Promise.resolve()), true); + +// The possible promise rejection is handled by "--unhandled-rejections=strict" +import('graphql/jsutils/isPromise').then(({ isPromise }) => { + strictEqual(isPromise(Promise.resolve()), true); +}); diff --git a/integrationTests/node-esm/test.js b/integrationTests/node-esm/test.js index 788aedbf3cb..f40d724d2f9 100644 --- a/integrationTests/node-esm/test.js +++ b/integrationTests/node-esm/test.js @@ -14,5 +14,9 @@ for (const version of nodeVersions) { console.log(`Testing on ${version} ...`); const nodePath = resolve('node_modules', version, 'bin/node'); - execSync(nodePath + ' index.js', { stdio: 'inherit' }); + execSync( + nodePath + + ' --experimental-json-modules --unhandled-rejections=strict index.js', + { stdio: 'inherit' }, + ); } diff --git a/integrationTests/ts-esm/TypedQueryDocumentNode-test.ts b/integrationTests/ts-esm/TypedQueryDocumentNode-test.ts deleted file mode 100644 index 89044efbfec..00000000000 --- a/integrationTests/ts-esm/TypedQueryDocumentNode-test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { ExecutionResult } from 'graphql/execution'; -import type { TypedQueryDocumentNode } from 'graphql/utilities'; - -import { parse } from 'graphql/language'; -import { execute } from 'graphql/execution'; -import { buildSchema } from 'graphql/utilities'; - -const schema = buildSchema(` - type Query { - test: String - } -`); - -// Tests for TS specific TypedQueryDocumentNode type -const queryDocument = parse('{ test }'); - -type ResponseData = { test: string }; -const typedQueryDocument = queryDocument as TypedQueryDocumentNode< - ResponseData, - {} ->; - -// Supports conversion to DocumentNode -execute({ schema, document: typedQueryDocument }); - -function wrappedExecute(document: TypedQueryDocumentNode) { - return execute({ schema, document }) as ExecutionResult; -} - -const response = wrappedExecute(typedQueryDocument); -const responseData: ResponseData | undefined | null = response.data; - -declare function runQueryA( - q: TypedQueryDocumentNode<{ output: string }, { input: string | null }>, -): void; - -// valid -declare const optionalInputRequiredOutput: TypedQueryDocumentNode< - { output: string }, - { input: string | null } ->; -runQueryA(optionalInputRequiredOutput); - -declare function runQueryB( - q: TypedQueryDocumentNode<{ output: string | null }, { input: string }>, -): void; - -// still valid: We still accept {output: string} as a valid result. -// We're now passing in {input: string} which is still assignable to {input: string | null} -runQueryB(optionalInputRequiredOutput); - -// valid: we now accept {output: null} as a valid Result -declare const optionalInputOptionalOutput: TypedQueryDocumentNode< - { output: string | null }, - { input: string | null } ->; -runQueryB(optionalInputOptionalOutput); - -// valid: we now only pass {input: string} to the query -declare const requiredInputRequiredOutput: TypedQueryDocumentNode< - { output: string }, - { input: string } ->; -runQueryB(requiredInputRequiredOutput); - -// valid: we now accept {output: null} as a valid Result AND -// we now only pass {input: string} to the query -declare const requiredInputOptionalOutput: TypedQueryDocumentNode< - { output: null }, - { input: string } ->; -runQueryB(requiredInputOptionalOutput); diff --git a/integrationTests/ts-esm/extensions-test.ts b/integrationTests/ts-esm/extensions-test.ts deleted file mode 100644 index 689d9435982..00000000000 --- a/integrationTests/ts-esm/extensions-test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { GraphQLError } from 'graphql/error'; -import { GraphQLString, GraphQLObjectType } from 'graphql/type'; - -interface SomeExtension { - meaningOfLife: 42; -} - -declare module 'graphql' { - interface GraphQLObjectTypeExtensions<_TSource, _TContext> { - someObjectExtension?: SomeExtension; - } - - interface GraphQLFieldExtensions<_TSource, _TContext, _TArgs> { - someFieldExtension?: SomeExtension; - } - - interface GraphQLArgumentExtensions { - someArgumentExtension?: SomeExtension; - } -} - -const queryType: GraphQLObjectType = new GraphQLObjectType({ - name: 'Query', - fields: () => ({ - sayHi: { - type: GraphQLString, - args: { - who: { - type: GraphQLString, - extensions: { - someArgumentExtension: { meaningOfLife: 42 }, - }, - }, - }, - resolve: (_root, args) => 'Hello ' + (args.who || 'World'), - extensions: { - someFieldExtension: { meaningOfLife: 42 }, - }, - }, - }), - extensions: { - someObjectExtension: { meaningOfLife: 42 }, - }, -}); - -function checkExtensionTypes(_test: SomeExtension | null | undefined) {} - -checkExtensionTypes(queryType.extensions.someObjectExtension); - -const sayHiField = queryType.getFields().sayHi; -checkExtensionTypes(sayHiField.extensions.someFieldExtension); - -checkExtensionTypes(sayHiField.args[0].extensions.someArgumentExtension); - -declare module 'graphql' { - export interface GraphQLErrorExtensions { - someErrorExtension?: SomeExtension; - } -} - -const error = new GraphQLError('foo'); -checkExtensionTypes(error.extensions.someErrorExtension); diff --git a/integrationTests/ts-esm/internalImports-test.ts b/integrationTests/ts-esm/internalImports-test.ts deleted file mode 100644 index 62d9628df8e..00000000000 --- a/integrationTests/ts-esm/internalImports-test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { NameNode } from 'graphql/language'; - -// Parser class is internal API so so any changes to it are never considered breaking changes. -// We just want to test that we are able to import it. -import { Parser } from 'graphql/language/parser'; - -const parser = new Parser('foo'); -const ast: NameNode = parser.parseName(); diff --git a/integrationTests/ts-esm/package.json b/integrationTests/ts-esm/package.json deleted file mode 100644 index 2c98c6957fd..00000000000 --- a/integrationTests/ts-esm/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "private": true, - "description": "graphql-js ESM should compile with all supported TS versions", - "scripts": { - "test": "node test.js" - }, - "dependencies": { - "graphql": "file:../graphql-esm.tgz", - "typescript-4.2": "npm:typescript@4.2.x", - "typescript-4.3": "npm:typescript@4.3.x", - "typescript-4.4": "npm:typescript@4.4.x", - "typescript-4.5": "npm:typescript@4.5.1-rc" - } -} diff --git a/integrationTests/ts-esm/test.js b/integrationTests/ts-esm/test.js deleted file mode 100644 index b328fe160be..00000000000 --- a/integrationTests/ts-esm/test.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -const path = require('path'); -const childProcess = require('child_process'); - -const { dependencies } = require('./package.json'); - -const tsVersions = Object.keys(dependencies) - .filter((pkg) => pkg.startsWith('typescript-')) - .sort((a, b) => b.localeCompare(a)); - -for (const version of tsVersions) { - console.log(`Testing on ${version} ...`); - childProcess.execSync(tscPath(version), { stdio: 'inherit' }); -} - -function tscPath(version) { - return path.join(__dirname, 'node_modules', version, 'bin/tsc'); -} diff --git a/integrationTests/ts-esm/tsconfig.json b/integrationTests/ts-esm/tsconfig.json deleted file mode 100644 index 8bf6a2ba346..00000000000 --- a/integrationTests/ts-esm/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "module": "esnext", - "moduleResolution": "node", - "target": "es2019", - "lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"], - "strict": true, - "noEmit": true, - "types": [] - } -} diff --git a/integrationTests/ts-esm/basic-test.ts b/integrationTests/ts/esm.ts similarity index 72% rename from integrationTests/ts-esm/basic-test.ts rename to integrationTests/ts/esm.ts index a28bd840e76..f4451a166ef 100644 --- a/integrationTests/ts-esm/basic-test.ts +++ b/integrationTests/ts/esm.ts @@ -1,34 +1,38 @@ -import type { ExecutionResult } from 'graphql/execution'; - -import { graphqlSync } from 'graphql'; -import { GraphQLString, GraphQLSchema, GraphQLObjectType } from 'graphql/type'; - -const queryType: GraphQLObjectType = new GraphQLObjectType({ - name: 'Query', - fields: () => ({ - sayHi: { - type: GraphQLString, - args: { - who: { - type: GraphQLString, - defaultValue: 'World', - }, - }, - resolve(_root, args: { who: string }) { - return 'Hello ' + args.who; - }, - }, - }), -}); - -const schema: GraphQLSchema = new GraphQLSchema({ query: queryType }); - -const result: ExecutionResult = graphqlSync({ - schema, - source: ` - query helloWho($who: String){ - test(who: $who) - } - `, - variableValues: { who: 'Dolly' }, -}); +import type { ExecutionResult } from 'graphql-esm/execution'; + +import { graphqlSync } from 'graphql-esm'; +import { + GraphQLString, + GraphQLSchema, + GraphQLObjectType, +} from 'graphql-esm/type'; + +const queryType: GraphQLObjectType = new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + sayHi: { + type: GraphQLString, + args: { + who: { + type: GraphQLString, + defaultValue: 'World', + }, + }, + resolve(_root, args: { who: string }) { + return 'Hello ' + args.who; + }, + }, + }), +}); + +const schema: GraphQLSchema = new GraphQLSchema({ query: queryType }); + +const result: ExecutionResult = graphqlSync({ + schema, + source: ` + query helloWho($who: String){ + test(who: $who) + } + `, + variableValues: { who: 'Dolly' }, +}); diff --git a/integrationTests/ts/package.json b/integrationTests/ts/package.json index 9fc71009d1f..5669e71b113 100644 --- a/integrationTests/ts/package.json +++ b/integrationTests/ts/package.json @@ -6,6 +6,7 @@ }, "dependencies": { "graphql": "file:../graphql.tgz", + "graphql-esm": "file:../graphql-esm.tgz", "typescript-4.1": "npm:typescript@4.1.x", "typescript-4.2": "npm:typescript@4.2.x", "typescript-4.3": "npm:typescript@4.3.x", diff --git a/integrationTests/webpack-esm/package.json b/integrationTests/webpack-esm/package.json deleted file mode 100644 index a0a2c55493b..00000000000 --- a/integrationTests/webpack-esm/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "module", - "private": true, - "description": "graphql-js ESM should be compatible with Webpack", - "scripts": { - "test": "webpack && node test.js" - }, - "dependencies": { - "graphql": "file:../graphql-esm.tgz", - "webpack": "5.x.x", - "webpack-cli": "4.x.x" - } -} diff --git a/integrationTests/webpack-esm/test.js b/integrationTests/webpack-esm/test.js deleted file mode 100644 index e0fd787c73e..00000000000 --- a/integrationTests/webpack-esm/test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { deepStrictEqual } from 'assert'; - -// eslint-disable-next-line node/no-missing-import, import/no-unresolved -import { result } from './dist/main.mjs'; - -deepStrictEqual(result, { - data: { - __proto__: null, - hello: 'world', - }, -}); -console.log('Test script: Got correct result from Webpack bundle!'); diff --git a/integrationTests/webpack-esm/webpack.config.json b/integrationTests/webpack-esm/webpack.config.json deleted file mode 100644 index 0acb68777f0..00000000000 --- a/integrationTests/webpack-esm/webpack.config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "mode": "production", - "entry": "./entry.js", - "experiments": { - "outputModule": true - }, - "output": { - "library": { - "type": "module" - } - } -} diff --git a/integrationTests/webpack-esm/entry.js b/integrationTests/webpack/entry-esm.mjs similarity index 56% rename from integrationTests/webpack-esm/entry.js rename to integrationTests/webpack/entry-esm.mjs index 78ff5b9cb99..1dec59e0436 100644 --- a/integrationTests/webpack-esm/entry.js +++ b/integrationTests/webpack/entry-esm.mjs @@ -1,5 +1,8 @@ // eslint-disable-next-line node/no-missing-import, import/no-unresolved -import { buildSchema, graphqlSync } from 'graphql'; +import { graphqlSync } from 'graphql-esm'; + +// eslint-disable-next-line node/no-missing-import, import/no-unresolved +import { buildSchema } from 'graphql-esm/utilities/buildASTSchema'; const schema = buildSchema('type Query { hello: String }'); diff --git a/integrationTests/webpack/package.json b/integrationTests/webpack/package.json index aec7a21afb4..83001bb4b71 100644 --- a/integrationTests/webpack/package.json +++ b/integrationTests/webpack/package.json @@ -6,6 +6,7 @@ }, "dependencies": { "graphql": "file:../graphql.tgz", + "graphql-esm": "file:../graphql-esm.tgz", "webpack": "5.x.x", "webpack-cli": "4.x.x" } diff --git a/integrationTests/webpack/test.js b/integrationTests/webpack/test.js index 40c22233d4f..6bd4e0c04c7 100644 --- a/integrationTests/webpack/test.js +++ b/integrationTests/webpack/test.js @@ -3,12 +3,23 @@ const assert = require('assert'); // eslint-disable-next-line node/no-missing-require -const { result } = require('./dist/main.js'); +const { result: cjs } = require('./dist/cjs.js'); -assert.deepStrictEqual(result, { +assert.deepStrictEqual(cjs, { data: { __proto__: null, hello: 'world', }, }); + +// eslint-disable-next-line node/no-missing-require +const { result: esm } = require('./dist/esm.js'); + +assert.deepStrictEqual(esm, { + data: { + __proto__: null, + hello: 'world', + }, +}); + console.log('Test script: Got correct result from Webpack bundle!'); diff --git a/integrationTests/webpack/webpack.config.json b/integrationTests/webpack/webpack.config.json index 830b2bd52dc..c74ab3e4472 100644 --- a/integrationTests/webpack/webpack.config.json +++ b/integrationTests/webpack/webpack.config.json @@ -1,6 +1,9 @@ { "mode": "production", - "entry": "./entry.js", + "entry": { + "cjs": "./entry.js", + "esm": "./entry-esm.mjs" + }, "output": { "libraryTarget": "commonjs2" } diff --git a/resources/build-npm.js b/resources/build-npm.js index de037310f76..8534a4a514f 100644 --- a/resources/build-npm.js +++ b/resources/build-npm.js @@ -87,14 +87,6 @@ function buildNPM() { assert(packageJSON.types === undefined, 'Unexpected "types" in package.json'); - if (isESMOnly) { - packageJSON.typesVersions = { - '>=4.2.0': { - '*': ['*'], - }, - }; - } - const supportedTSVersions = Object.keys(packageJSON.typesVersions); assert( supportedTSVersions.length === 1, @@ -168,7 +160,6 @@ function buildPackageJSON( delete packageJSON.module; packageJSON.version = `${packageJSON.version}-esm`; - packageJSON.main = 'index.js'; packageJSON.type = 'module'; packageJSON.exports = {