Skip to content

Commit 7d134d6

Browse files
PabloSzxIvanGoncharov
authored andcommittedSep 20, 2022
npm esm tag
1 parent cbc22f2 commit 7d134d6

16 files changed

+154
-38
lines changed
 

‎.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/node_modules
66
/reports
77
/npmDist
8+
/npmEsmDist
89
/denoDist
910
/websiteDist
1011

‎.eslintrc.yml

+4
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,10 @@ rules:
473473
yield-star-spacing: off
474474

475475
overrides:
476+
- files:
477+
- 'integrationTests/node-esm/**/*.js'
478+
parserOptions:
479+
sourceType: module
476480
- files: '**/*.ts'
477481
parser: '@typescript-eslint/parser'
478482
parserOptions:

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
/node_modules
1414
/reports
1515
/npmDist
16+
/npmEsmDist
1617
/denoDist
1718
/websiteDist

‎.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
/node_modules
77
/reports
88
/npmDist
9+
/npmEsmDist
910
/denoDist
1011
/websiteDist

‎integrationTests/node/index.js ‎integrationTests/node/index.mjs

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
import assert from 'assert';
33
import { readFileSync } from 'fs';
44

5-
import { graphqlSync } from 'graphql';
6-
import { buildSchema } from 'graphql/utilities';
7-
import { version } from 'graphql/version';
5+
import { graphqlSync } from 'graphql-esm';
6+
import { buildSchema } from 'graphql-esm/utilities';
7+
import { version } from 'graphql-esm/version';
88

99
assert.deepStrictEqual(
10-
version,
11-
JSON.parse(readFileSync('./node_modules/graphql/package.json')).version,
10+
version + '+esm',
11+
JSON.parse(readFileSync('./node_modules/graphql-esm/package.json')).version,
1212
);
1313

1414
const schema = buildSchema('type Query { hello: String }');

‎integrationTests/node/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"test": "node test.js"
77
},
88
"dependencies": {
9-
"graphql": "file:../graphql.tgz"
9+
"graphql": "file:../graphql.tgz",
10+
"graphql-esm": "file:../graphql-esm.tgz"
1011
}
1112
}

‎integrationTests/node/test.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ for (const version of nodeVersions) {
1414
console.log(`Testing on node@${version} ...`);
1515

1616
childProcess.execSync(
17-
`docker run --rm --volume "$PWD":/usr/src/app -w /usr/src/app node:${version}-slim node ./index.js`,
17+
`docker run --rm --volume "$PWD":/usr/src/app -w /usr/src/app node:${version}-slim node ./index.cjs`,
18+
{ stdio: 'inherit' },
19+
);
20+
21+
childProcess.execSync(
22+
`docker run --rm --volume "$PWD":/usr/src/app -w /usr/src/app node:${version}-slim node ./index.mjs`,
1823
{ stdio: 'inherit' },
1924
);
2025
}

‎integrationTests/ts/esm.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { ExecutionResult } from 'graphql-esm/execution';
2+
3+
import { graphqlSync } from 'graphql-esm';
4+
import {
5+
GraphQLString,
6+
GraphQLSchema,
7+
GraphQLObjectType,
8+
} from 'graphql-esm/type';
9+
10+
const queryType: GraphQLObjectType = new GraphQLObjectType({
11+
name: 'Query',
12+
fields: () => ({
13+
sayHi: {
14+
type: GraphQLString,
15+
args: {
16+
who: {
17+
type: GraphQLString,
18+
defaultValue: 'World',
19+
},
20+
},
21+
resolve(_root, args: { who: string }) {
22+
return 'Hello ' + args.who;
23+
},
24+
},
25+
}),
26+
});
27+
28+
const schema: GraphQLSchema = new GraphQLSchema({ query: queryType });
29+
30+
const result: ExecutionResult = graphqlSync({
31+
schema,
32+
source: `
33+
query helloWho($who: String){
34+
test(who: $who)
35+
}
36+
`,
37+
variableValues: { who: 'Dolly' },
38+
});

‎integrationTests/ts/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"dependencies": {
99
"graphql": "file:../graphql.tgz",
10+
"graphql-esm": "file:../graphql-esm.tgz",
1011
"typescript-4.4": "npm:typescript@4.4.x",
1112
"typescript-4.5": "npm:typescript@4.5.x",
1213
"typescript-4.6": "npm:typescript@4.6.x",
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// eslint-disable-next-line node/no-missing-import, import/no-unresolved
2+
import { graphqlSync } from 'graphql-esm';
3+
4+
// eslint-disable-next-line node/no-missing-import, import/no-unresolved
5+
import { buildSchema } from 'graphql-esm/utilities/buildASTSchema';
6+
7+
const schema = buildSchema('type Query { hello: String }');
8+
9+
export const result = graphqlSync({
10+
schema,
11+
source: '{ hello }',
12+
rootValue: { hello: 'world' },
13+
});

‎integrationTests/webpack/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"dependencies": {
99
"graphql": "file:../graphql.tgz",
10+
"graphql-esm": "file:../graphql-esm.tgz",
1011
"webpack": "5.x.x",
1112
"webpack-cli": "4.x.x"
1213
}

‎integrationTests/webpack/test.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import assert from 'assert';
22

3-
import mainCJS from './dist/main.cjs';
3+
import cjs from './dist/main-cjs.cjs';
4+
import mjs from './dist/main-mjs.cjs';
45

5-
assert.deepStrictEqual(mainCJS.result, {
6+
assert.deepStrictEqual(cjs.result, {
67
data: {
78
__proto__: null,
89
hello: 'world',
910
},
1011
});
12+
13+
assert.deepStrictEqual(mjs.result, {
14+
data: {
15+
__proto__: null,
16+
hello: 'world',
17+
},
18+
});
19+
1120
console.log('Test script: Got correct result from Webpack bundle!');

‎integrationTests/webpack/webpack.config.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
{
22
"mode": "production",
3-
"entry": "./entry.js",
3+
"entry": {
4+
"cjs": "./entry.js",
5+
"mjs": "./entry-esm.mjs"
6+
},
47
"output": {
5-
"filename": "main.cjs",
8+
"filename": "main-[name].cjs",
69
"library": {
710
"type": "commonjs2"
811
}

‎resources/build-npm.ts

+53-26
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from 'node:path';
44

55
import ts from 'typescript';
66

7+
import { changeExtensionInImportPaths } from './change-extension-in-import-paths.js';
78
import { inlineInvariant } from './inline-invariant.js';
89
import {
910
readPackageJSON,
@@ -12,17 +13,20 @@ import {
1213
writeGeneratedFile,
1314
} from './utils.js';
1415

15-
buildPackage();
16+
console.log('\n./npmDist');
17+
buildPackage('./npmDist', false);
1618
showDirStats('./npmDist');
1719

18-
function buildPackage() {
19-
fs.rmSync('./npmDist', { recursive: true, force: true });
20-
fs.mkdirSync('./npmDist');
20+
console.log('\n./npmEsmDist');
21+
buildPackage('./npmEsmDist', true);
22+
showDirStats('./npmEsmDist');
2123

22-
fs.copyFileSync('./LICENSE', './npmDist/LICENSE');
23-
fs.copyFileSync('./README.md', './npmDist/README.md');
24+
function buildPackage(outDir: string, isESMOnly: boolean): void {
25+
fs.rmSync(outDir, { recursive: true, force: true });
26+
fs.mkdirSync(outDir);
2427

25-
const { emittedTSFiles } = emitTSFiles('./npmDist');
28+
fs.copyFileSync('./LICENSE', `./${outDir}/LICENSE`);
29+
fs.copyFileSync('./README.md', `./${outDir}/README.md`);
2630

2731
const packageJSON = readPackageJSON();
2832

@@ -39,7 +43,7 @@ function buildPackage() {
3943
// TODO: revisit once TS implements https://github.com/microsoft/TypeScript/issues/32166
4044
const notSupportedTSVersionFile = 'NotSupportedTSVersion.d.ts';
4145
fs.writeFileSync(
42-
path.join('./npmDist', notSupportedTSVersionFile),
46+
path.join(outDir, notSupportedTSVersionFile),
4347
// Provoke syntax error to show this message
4448
`"Package 'graphql' support only TS versions that are ${supportedTSVersions[0]}".`,
4549
);
@@ -49,19 +53,6 @@ function buildPackage() {
4953
'*': { '*': [notSupportedTSVersionFile] },
5054
};
5155

52-
packageJSON.exports = {};
53-
54-
for (const filepath of emittedTSFiles) {
55-
if (path.basename(filepath) === 'index.js') {
56-
const relativePath = './' + path.relative('./npmDist', filepath);
57-
packageJSON.exports[path.dirname(relativePath)] = relativePath;
58-
}
59-
}
60-
61-
// Temporary workaround to allow "internal" imports, no grantees provided
62-
packageJSON.exports['./*.js'] = './*.js';
63-
packageJSON.exports['./*'] = './*.js';
64-
6556
// TODO: move to integration tests
6657
const publishTag = packageJSON.publishConfig?.tag;
6758
assert(publishTag != null, 'Should have packageJSON.publishConfig defined!');
@@ -90,16 +81,51 @@ function buildPackage() {
9081
);
9182
}
9283

84+
if (isESMOnly) {
85+
packageJSON.exports = {};
86+
87+
const { emittedTSFiles } = emitTSFiles({
88+
outDir,
89+
module: 'es2020',
90+
extension: '.js',
91+
});
92+
93+
for (const filepath of emittedTSFiles) {
94+
if (path.basename(filepath) === 'index.js') {
95+
const relativePath = './' + path.relative('./npmEsmDist', filepath);
96+
packageJSON.exports[path.dirname(relativePath)] = relativePath;
97+
}
98+
}
99+
100+
// Temporary workaround to allow "internal" imports, no grantees provided
101+
packageJSON.exports['./*.js'] = './*.js';
102+
packageJSON.exports['./*'] = './*.js';
103+
104+
packageJSON.publishConfig.tag += '-esm';
105+
packageJSON.version += '+esm';
106+
} else {
107+
delete packageJSON.type;
108+
packageJSON.main = 'index';
109+
packageJSON.module = 'index.mjs';
110+
emitTSFiles({ outDir, module: 'commonjs', extension: '.js' });
111+
emitTSFiles({ outDir, module: 'es2020', extension: '.mjs' });
112+
}
113+
93114
// Should be done as the last step so only valid packages can be published
94-
writeGeneratedFile('./npmDist/package.json', JSON.stringify(packageJSON));
115+
writeGeneratedFile(`./${outDir}/package.json`, JSON.stringify(packageJSON));
95116
}
96117

97118
// Based on https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#getting-the-dts-from-a-javascript-file
98-
function emitTSFiles(outDir: string): {
119+
function emitTSFiles(options: {
120+
outDir: string;
121+
module: string;
122+
extension: string;
123+
}): {
99124
emittedTSFiles: ReadonlyArray<string>;
100125
} {
126+
const { outDir, module, extension } = options;
101127
const tsOptions = readTSConfig({
102-
module: 'es2020',
128+
module,
103129
noEmit: false,
104130
declaration: true,
105131
declarationDir: outDir,
@@ -108,11 +134,12 @@ function emitTSFiles(outDir: string): {
108134
});
109135

110136
const tsHost = ts.createCompilerHost(tsOptions);
111-
tsHost.writeFile = writeGeneratedFile;
137+
tsHost.writeFile = (filepath, body) =>
138+
writeGeneratedFile(filepath.replace(/.js$/, extension), body);
112139

113140
const tsProgram = ts.createProgram(['src/index.ts'], tsOptions, tsHost);
114141
const tsResult = tsProgram.emit(undefined, undefined, undefined, undefined, {
115-
after: [inlineInvariant],
142+
after: [changeExtensionInImportPaths({ extension }), inlineInvariant],
116143
});
117144
assert(
118145
!tsResult.emitSkipped,

‎resources/integration-test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ describe('Integration Tests', () => {
1111
});
1212

1313
npm().run('build:npm');
14+
1415
const distDir = localRepoPath('npmDist');
1516
const archiveName = npm({ cwd: tmpDirPath(), quiet: true }).pack(distDir);
1617
fs.renameSync(tmpDirPath(archiveName), tmpDirPath('graphql.tgz'));
1718

19+
const esmDistDir = localRepoPath('npmEsmDist');
20+
const archiveEsmName = npm({ cwd: tmpDirPath(), quiet: true }).pack(
21+
esmDistDir,
22+
);
23+
fs.renameSync(tmpDirPath(archiveEsmName), tmpDirPath('graphql-esm.tgz'));
24+
1825
npm().run('build:deno');
1926

2027
function testOnNodeProject(projectName: string) {

‎resources/utils.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,11 @@ interface PackageJSON {
198198
types?: string;
199199
typesVersions: { [ranges: string]: { [path: string]: Array<string> } };
200200
devDependencies?: { [name: string]: string };
201-
publishConfig?: { tag?: string };
201+
publishConfig: { tag: string };
202+
203+
// TODO: remove after we drop CJS support
204+
main?: string;
205+
module?: string;
202206
}
203207

204208
export function readPackageJSON(

0 commit comments

Comments
 (0)
Please sign in to comment.