Skip to content

Commit 422f59a

Browse files
committed
alternative check for multiple graphql packages
1 parent 04e948b commit 422f59a

File tree

6 files changed

+105
-10
lines changed

6 files changed

+105
-10
lines changed

integrationTests/webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "graphql-js should be compatible with Webpack",
44
"type": "module",
55
"scripts": {
6-
"test": "webpack && node test.js"
6+
"test": "webpack && node test.js && node test-esm.js"
77
},
88
"dependencies": {
99
"graphql": "file:../graphql.tgz",

integrationTests/webpack/test-esm.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import assert from 'assert';
2+
3+
/* eslint-disable n/no-missing-import */
4+
import mjs from './dist/main-mjs.cjs';
5+
/* eslint-enable n/no-missing-import */
6+
7+
assert.deepStrictEqual(mjs.result, {
8+
data: {
9+
__proto__: null,
10+
hello: 'world',
11+
},
12+
});
13+
14+
console.log('Test script: Got correct result from Webpack esm bundle!');

integrationTests/webpack/test.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import assert from 'assert';
22

33
/* eslint-disable n/no-missing-import */
44
import cjs from './dist/main-cjs.cjs';
5-
import mjs from './dist/main-mjs.cjs';
65
/* eslint-enable n/no-missing-import */
76

87
assert.deepStrictEqual(cjs.result, {
@@ -12,11 +11,4 @@ assert.deepStrictEqual(cjs.result, {
1211
},
1312
});
1413

15-
assert.deepStrictEqual(mjs.result, {
16-
data: {
17-
__proto__: null,
18-
hello: 'world',
19-
},
20-
});
21-
22-
console.log('Test script: Got correct result from Webpack bundle!');
14+
console.log('Test script: Got correct result from Webpack cjs bundle!');
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* eslint-disable no-console */
2+
import { expect } from 'chai';
3+
import { afterEach, beforeEach, describe, it } from 'mocha';
4+
5+
import { checkForMultiplePackageInstances } from '../checkForMultiplePackageInstances.js';
6+
7+
describe('check for different library versions', () => {
8+
class OtherPackageClass {}
9+
const graphqlPackageInstanceCheckSymbol = Symbol.for(
10+
'graphql-js:check-multiple-package-instances',
11+
);
12+
const globalObject = globalThis as {
13+
[graphqlPackageInstanceCheckSymbol]?: unknown;
14+
};
15+
const orig = globalObject[graphqlPackageInstanceCheckSymbol];
16+
const origError = console.error;
17+
let errors: Array<unknown> = [];
18+
beforeEach(() => {
19+
errors = [];
20+
console.error = (...args) => {
21+
errors = args;
22+
};
23+
});
24+
25+
afterEach(() => {
26+
globalObject[graphqlPackageInstanceCheckSymbol] = orig;
27+
console.error = origError;
28+
});
29+
30+
it('does not log an error under normal circumstances', () => {
31+
checkForMultiplePackageInstances();
32+
expect(errors).to.deep.equal([]);
33+
checkForMultiplePackageInstances();
34+
expect(errors).to.deep.equal([]);
35+
checkForMultiplePackageInstances();
36+
expect(errors).to.deep.equal([]);
37+
});
38+
39+
it('logs an error if another package has been loaded first', () => {
40+
// simulate other version of this lib to have been loaded before this version
41+
globalObject[graphqlPackageInstanceCheckSymbol] = new OtherPackageClass();
42+
43+
checkForMultiplePackageInstances();
44+
45+
expect(errors[0]).to.match(
46+
/Multiple colliding versions of the `graphql` package detected\./m,
47+
);
48+
});
49+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const graphqlPackageInstanceCheckSymbol = Symbol.for(
2+
'graphql-js:check-multiple-package-instances',
3+
);
4+
5+
class Check {}
6+
7+
/**
8+
* A check which throws an error warning when multi-realm constructors are detected.
9+
*/
10+
export function checkForMultiplePackageInstances() {
11+
const globalObject = globalThis as {
12+
[graphqlPackageInstanceCheckSymbol]?: Check;
13+
};
14+
if (!globalObject[graphqlPackageInstanceCheckSymbol]) {
15+
globalObject[graphqlPackageInstanceCheckSymbol] = new Check();
16+
return;
17+
}
18+
if (!(globalObject[graphqlPackageInstanceCheckSymbol] instanceof Check)) {
19+
// eslint-disable-next-line no-console
20+
console.error(
21+
new Error(
22+
`Multiple colliding versions of the \`graphql\` package detected.
23+
24+
Ensure that there is only one instance of "graphql" in the node_modules
25+
directory. If different versions of "graphql" are the dependencies of other
26+
relied on modules, use "resolutions" to ensure only one version is installed.
27+
28+
https://yarnpkg.com/en/docs/selective-version-resolutions
29+
30+
Duplicate "graphql" modules cannot be used at the same time since different
31+
versions may have different capabilities and behavior. The data from one
32+
version used in the function from another could produce confusing and
33+
spurious results.`,
34+
),
35+
);
36+
}
37+
}

src/jsutils/instanceOf.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { checkForMultiplePackageInstances } from './checkForMultiplePackageInstances.js';
12
import { inspect } from './inspect.js';
23

4+
checkForMultiplePackageInstances();
5+
36
/**
47
* A replacement for instanceof which includes an error warning when multi-realm
58
* constructors are detected.

0 commit comments

Comments
 (0)