Skip to content

Commit 2f16810

Browse files
committed
fixes
1 parent ad04c2d commit 2f16810

6 files changed

Lines changed: 149 additions & 13 deletions

File tree

‎dev-packages/e2e-tests/test-applications/node-esbuild/assert.mjs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @module
1818
*/
1919
import { execFileSync } from 'node:child_process';
20-
import { existsSync } from 'node:fs';
20+
import { existsSync, readFileSync } from 'node:fs';
2121
import { dirname, join } from 'node:path';
2222
import { fileURLToPath } from 'node:url';
2323

@@ -47,6 +47,27 @@ function run(name, { withImport = false } = {}) {
4747

4848
const graphqlSpanCount = result => result.spans.filter(s => s.origin === GRAPHQL_ORIGIN).length;
4949

50+
// Guards the build config, not just its runtime output. The span assertions below can pass by
51+
// accident when the externalization knob is a no-op (e.g. a Vite SSR build externalizes deps by
52+
// default, so a mis-set toggle silently ships an external graphql in every variant while the counts
53+
// still come out right). Assert the bundle SHAPE instead: an inlined build carries graphql's own
54+
// source (its exported `GraphQLSchema`) and has no bare `graphql` import left; an external build
55+
// keeps the bare `graphql` import/require and never inlines that source. Bundler-agnostic — matches
56+
// ESM `from 'graphql'` and CJS `require('graphql')` alike.
57+
const GRAPHQL_BARE_REFERENCE = /(?:from|require\()\s*['"]graphql['"]/;
58+
const GRAPHQL_SOURCE_MARKER = 'GraphQLSchema';
59+
60+
function assertBundleShape(name, { inlined }) {
61+
const bundle = readFileSync(entryPath(name), 'utf8');
62+
const hasBareReference = GRAPHQL_BARE_REFERENCE.test(bundle);
63+
const hasGraphqlSource = bundle.includes(GRAPHQL_SOURCE_MARKER);
64+
if (inlined) {
65+
check(!hasBareReference && hasGraphqlSource, `${name}: graphql is inlined into the bundle`);
66+
} else {
67+
check(hasBareReference && !hasGraphqlSource, `${name}: graphql is kept external to the bundle`);
68+
}
69+
}
70+
5071
const scenarios = {
5172
plain: run('plain'),
5273
plugin: run('plugin'),
@@ -68,6 +89,11 @@ for (const [label, result] of Object.entries(scenarios)) {
6889
check(result.data?.hello === 'world', `${label}: graphql query works`);
6990
}
7091

92+
assertBundleShape('plain', { inlined: true });
93+
assertBundleShape('plugin', { inlined: true });
94+
assertBundleShape('plain-external', { inlined: false });
95+
assertBundleShape('plugin-external', { inlined: false });
96+
7197
check(oneSet > 0, 'plugin build (build-time) emits a set of graphql spans');
7298
check(graphqlSpanCount(scenarios.plain) === 0, 'plain build (no plugin, no --import) emits no graphql spans');
7399
check(

‎dev-packages/e2e-tests/test-applications/node-rolldown/assert.mjs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @module
1818
*/
1919
import { execFileSync } from 'node:child_process';
20-
import { existsSync } from 'node:fs';
20+
import { existsSync, readFileSync } from 'node:fs';
2121
import { dirname, join } from 'node:path';
2222
import { fileURLToPath } from 'node:url';
2323

@@ -47,6 +47,27 @@ function run(name, { withImport = false } = {}) {
4747

4848
const graphqlSpanCount = result => result.spans.filter(s => s.origin === GRAPHQL_ORIGIN).length;
4949

50+
// Guards the build config, not just its runtime output. The span assertions below can pass by
51+
// accident when the externalization knob is a no-op (e.g. a Vite SSR build externalizes deps by
52+
// default, so a mis-set toggle silently ships an external graphql in every variant while the counts
53+
// still come out right). Assert the bundle SHAPE instead: an inlined build carries graphql's own
54+
// source (its exported `GraphQLSchema`) and has no bare `graphql` import left; an external build
55+
// keeps the bare `graphql` import/require and never inlines that source. Bundler-agnostic — matches
56+
// ESM `from 'graphql'` and CJS `require('graphql')` alike.
57+
const GRAPHQL_BARE_REFERENCE = /(?:from|require\()\s*['"]graphql['"]/;
58+
const GRAPHQL_SOURCE_MARKER = 'GraphQLSchema';
59+
60+
function assertBundleShape(name, { inlined }) {
61+
const bundle = readFileSync(entryPath(name), 'utf8');
62+
const hasBareReference = GRAPHQL_BARE_REFERENCE.test(bundle);
63+
const hasGraphqlSource = bundle.includes(GRAPHQL_SOURCE_MARKER);
64+
if (inlined) {
65+
check(!hasBareReference && hasGraphqlSource, `${name}: graphql is inlined into the bundle`);
66+
} else {
67+
check(hasBareReference && !hasGraphqlSource, `${name}: graphql is kept external to the bundle`);
68+
}
69+
}
70+
5071
const scenarios = {
5172
plain: run('plain'),
5273
plugin: run('plugin'),
@@ -68,6 +89,11 @@ for (const [label, result] of Object.entries(scenarios)) {
6889
check(result.data?.hello === 'world', `${label}: graphql query works`);
6990
}
7091

92+
assertBundleShape('plain', { inlined: true });
93+
assertBundleShape('plugin', { inlined: true });
94+
assertBundleShape('plain-external', { inlined: false });
95+
assertBundleShape('plugin-external', { inlined: false });
96+
7197
check(oneSet > 0, 'plugin build (build-time) emits a set of graphql spans');
7298
check(graphqlSpanCount(scenarios.plain) === 0, 'plain build (no plugin, no --import) emits no graphql spans');
7399
check(

‎dev-packages/e2e-tests/test-applications/node-rollup/assert.mjs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @module
1818
*/
1919
import { execFileSync } from 'node:child_process';
20-
import { existsSync } from 'node:fs';
20+
import { existsSync, readFileSync } from 'node:fs';
2121
import { dirname, join } from 'node:path';
2222
import { fileURLToPath } from 'node:url';
2323

@@ -47,6 +47,27 @@ function run(name, { withImport = false } = {}) {
4747

4848
const graphqlSpanCount = result => result.spans.filter(s => s.origin === GRAPHQL_ORIGIN).length;
4949

50+
// Guards the build config, not just its runtime output. The span assertions below can pass by
51+
// accident when the externalization knob is a no-op (e.g. a Vite SSR build externalizes deps by
52+
// default, so a mis-set toggle silently ships an external graphql in every variant while the counts
53+
// still come out right). Assert the bundle SHAPE instead: an inlined build carries graphql's own
54+
// source (its exported `GraphQLSchema`) and has no bare `graphql` import left; an external build
55+
// keeps the bare `graphql` import/require and never inlines that source. Bundler-agnostic — matches
56+
// ESM `from 'graphql'` and CJS `require('graphql')` alike.
57+
const GRAPHQL_BARE_REFERENCE = /(?:from|require\()\s*['"]graphql['"]/;
58+
const GRAPHQL_SOURCE_MARKER = 'GraphQLSchema';
59+
60+
function assertBundleShape(name, { inlined }) {
61+
const bundle = readFileSync(entryPath(name), 'utf8');
62+
const hasBareReference = GRAPHQL_BARE_REFERENCE.test(bundle);
63+
const hasGraphqlSource = bundle.includes(GRAPHQL_SOURCE_MARKER);
64+
if (inlined) {
65+
check(!hasBareReference && hasGraphqlSource, `${name}: graphql is inlined into the bundle`);
66+
} else {
67+
check(hasBareReference && !hasGraphqlSource, `${name}: graphql is kept external to the bundle`);
68+
}
69+
}
70+
5071
const scenarios = {
5172
plain: run('plain'),
5273
plugin: run('plugin'),
@@ -68,6 +89,11 @@ for (const [label, result] of Object.entries(scenarios)) {
6889
check(result.data?.hello === 'world', `${label}: graphql query works`);
6990
}
7091

92+
assertBundleShape('plain', { inlined: true });
93+
assertBundleShape('plugin', { inlined: true });
94+
assertBundleShape('plain-external', { inlined: false });
95+
assertBundleShape('plugin-external', { inlined: false });
96+
7197
check(oneSet > 0, 'plugin build (build-time) emits a set of graphql spans');
7298
check(graphqlSpanCount(scenarios.plain) === 0, 'plain build (no plugin, no --import) emits no graphql spans');
7399
check(

‎dev-packages/e2e-tests/test-applications/node-vite/assert.mjs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @module
1818
*/
1919
import { execFileSync } from 'node:child_process';
20-
import { existsSync } from 'node:fs';
20+
import { existsSync, readFileSync } from 'node:fs';
2121
import { dirname, join } from 'node:path';
2222
import { fileURLToPath } from 'node:url';
2323

@@ -47,6 +47,27 @@ function run(name, { withImport = false } = {}) {
4747

4848
const graphqlSpanCount = result => result.spans.filter(s => s.origin === GRAPHQL_ORIGIN).length;
4949

50+
// Guards the build config, not just its runtime output. The span assertions below can pass by
51+
// accident when the externalization knob is a no-op (e.g. a Vite SSR build externalizes deps by
52+
// default, so a mis-set toggle silently ships an external graphql in every variant while the counts
53+
// still come out right). Assert the bundle SHAPE instead: an inlined build carries graphql's own
54+
// source (its exported `GraphQLSchema`) and has no bare `graphql` import left; an external build
55+
// keeps the bare `graphql` import/require and never inlines that source. Bundler-agnostic — matches
56+
// ESM `from 'graphql'` and CJS `require('graphql')` alike.
57+
const GRAPHQL_BARE_REFERENCE = /(?:from|require\()\s*['"]graphql['"]/;
58+
const GRAPHQL_SOURCE_MARKER = 'GraphQLSchema';
59+
60+
function assertBundleShape(name, { inlined }) {
61+
const bundle = readFileSync(entryPath(name), 'utf8');
62+
const hasBareReference = GRAPHQL_BARE_REFERENCE.test(bundle);
63+
const hasGraphqlSource = bundle.includes(GRAPHQL_SOURCE_MARKER);
64+
if (inlined) {
65+
check(!hasBareReference && hasGraphqlSource, `${name}: graphql is inlined into the bundle`);
66+
} else {
67+
check(hasBareReference && !hasGraphqlSource, `${name}: graphql is kept external to the bundle`);
68+
}
69+
}
70+
5071
const scenarios = {
5172
plain: run('plain'),
5273
plugin: run('plugin'),
@@ -68,6 +89,11 @@ for (const [label, result] of Object.entries(scenarios)) {
6889
check(result.data?.hello === 'world', `${label}: graphql query works`);
6990
}
7091

92+
assertBundleShape('plain', { inlined: true });
93+
assertBundleShape('plugin', { inlined: true });
94+
assertBundleShape('plain-external', { inlined: false });
95+
assertBundleShape('plugin-external', { inlined: false });
96+
7197
check(oneSet > 0, 'plugin build (build-time) emits a set of graphql spans');
7298
check(graphqlSpanCount(scenarios.plain) === 0, 'plain build (no plugin, no --import) emits no graphql spans');
7399
check(

‎dev-packages/e2e-tests/test-applications/node-vite/build.mjs‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,17 @@ const makeSentryPlugin = () =>
2727
release: { create: false, finalize: false, inject: false },
2828
});
2929

30-
function run(name, { external, plugins }) {
30+
function run(name, { graphqlExternal, plugins }) {
3131
return build({
3232
logLevel: 'silent',
33+
// Whether graphql is inlined or external is governed by Vite's SSR externalization
34+
// (`ssr.external` / `ssr.noExternal`), NOT `rollupOptions.external`: a Vite SSR build
35+
// externalizes node_modules deps by default, so without an explicit `ssr.noExternal` graphql
36+
// stays external no matter what `rollupOptions.external` says. Set it per-variant so the
37+
// build-time (inlined) and runtime (external) paths are each genuinely exercised. For the
38+
// `*-external` variants `ssr.external` also wins over the plugin's own `noExternal` force-bundle,
39+
// so graphql is left for the runtime `--import` hook to transform as it loads from node_modules.
40+
ssr: graphqlExternal ? { external: ['graphql'] } : { noExternal: ['graphql'] },
3341
build: {
3442
outDir: join(__dirname, 'dist', name),
3543
emptyOutDir: true,
@@ -40,20 +48,18 @@ function run(name, { external, plugins }) {
4048
// SSR build so the plugin's build-time transform applies (it only runs for server builds).
4149
ssr: join(__dirname, 'src', 'entry.mjs'),
4250
rollupOptions: {
43-
// The `*-external` variants keep graphql out of the bundle, so it is resolved from node_modules
44-
// at runtime and the `--import` hook can transform it as it loads.
45-
external: external ? [...nodeExternals, 'graphql'] : nodeExternals,
51+
external: nodeExternals,
4652
output: { entryFileNames: 'main.mjs', format: 'es' },
4753
},
4854
},
4955
plugins,
5056
});
5157
}
5258

53-
await run('plain', { external: false, plugins: [] });
54-
await run('plugin', { external: false, plugins: [makeSentryPlugin()] });
55-
await run('plain-external', { external: true, plugins: [] });
56-
await run('plugin-external', { external: true, plugins: [makeSentryPlugin()] });
59+
await run('plain', { graphqlExternal: false, plugins: [] });
60+
await run('plugin', { graphqlExternal: false, plugins: [makeSentryPlugin()] });
61+
await run('plain-external', { graphqlExternal: true, plugins: [] });
62+
await run('plugin-external', { graphqlExternal: true, plugins: [makeSentryPlugin()] });
5763

5864
// eslint-disable-next-line no-console
5965
console.log('built plain + plugin (inlined) and plain-external + plugin-external with vite');

‎dev-packages/e2e-tests/test-applications/node-webpack/assert.mjs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @module
1818
*/
1919
import { execFileSync } from 'node:child_process';
20-
import { existsSync } from 'node:fs';
20+
import { existsSync, readFileSync } from 'node:fs';
2121
import { dirname, join } from 'node:path';
2222
import { fileURLToPath } from 'node:url';
2323

@@ -47,6 +47,27 @@ function run(name, { withImport = false } = {}) {
4747

4848
const graphqlSpanCount = result => result.spans.filter(s => s.origin === GRAPHQL_ORIGIN).length;
4949

50+
// Guards the build config, not just its runtime output. The span assertions below can pass by
51+
// accident when the externalization knob is a no-op (e.g. a Vite SSR build externalizes deps by
52+
// default, so a mis-set toggle silently ships an external graphql in every variant while the counts
53+
// still come out right). Assert the bundle SHAPE instead: an inlined build carries graphql's own
54+
// source (its exported `GraphQLSchema`) and has no bare `graphql` import left; an external build
55+
// keeps the bare `graphql` import/require and never inlines that source. Bundler-agnostic — matches
56+
// ESM `from 'graphql'` and CJS `require('graphql')` alike.
57+
const GRAPHQL_BARE_REFERENCE = /(?:from|require\()\s*['"]graphql['"]/;
58+
const GRAPHQL_SOURCE_MARKER = 'GraphQLSchema';
59+
60+
function assertBundleShape(name, { inlined }) {
61+
const bundle = readFileSync(entryPath(name), 'utf8');
62+
const hasBareReference = GRAPHQL_BARE_REFERENCE.test(bundle);
63+
const hasGraphqlSource = bundle.includes(GRAPHQL_SOURCE_MARKER);
64+
if (inlined) {
65+
check(!hasBareReference && hasGraphqlSource, `${name}: graphql is inlined into the bundle`);
66+
} else {
67+
check(hasBareReference && !hasGraphqlSource, `${name}: graphql is kept external to the bundle`);
68+
}
69+
}
70+
5071
const scenarios = {
5172
plain: run('plain'),
5273
plugin: run('plugin'),
@@ -68,6 +89,11 @@ for (const [label, result] of Object.entries(scenarios)) {
6889
check(result.data?.hello === 'world', `${label}: graphql query works`);
6990
}
7091

92+
assertBundleShape('plain', { inlined: true });
93+
assertBundleShape('plugin', { inlined: true });
94+
assertBundleShape('plain-external', { inlined: false });
95+
assertBundleShape('plugin-external', { inlined: false });
96+
7197
check(oneSet > 0, 'plugin build (build-time) emits a set of graphql spans');
7298
check(graphqlSpanCount(scenarios.plain) === 0, 'plain build (no plugin, no --import) emits no graphql spans');
7399
check(

0 commit comments

Comments
 (0)