Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: keep graphql import as require in cjs #2258

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions config/plugins/esbuild/graphQLImportPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fs from 'fs/promises'
import type { Plugin } from 'esbuild'

/**
* A plugin to replace `require('graphql')` statements with `await import('graphql')`
* only for ESM bundles. This makes the GraphQL module to be imported lazily
* while maintaining the CommonJS compatibility.
* @see https://github.com/mswjs/msw/issues/2254
*/
export function graphqlImportPlugin(): Plugin {
return {
name: 'graphql-import-plugin',
setup(build) {
if (build.initialOptions.format !== 'esm') {
return
}

build.onLoad({ filter: /\.ts$/ }, async (args) => {
const contents = await fs.readFile(args.path, 'utf-8')
const match = /require\(['"]graphql['"]\)/g.exec(contents)

if (match) {
return {
loader: 'ts',
contents:
contents.slice(0, match.index - 1) +
`await import('graphql').catch((error) => {console.error('[MSW] Failed to parse a GraphQL query: cannot import the "graphql" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.'); throw error})` +
contents.slice(match.index + match[0].length),
}
}
})
},
}
}
14 changes: 8 additions & 6 deletions src/core/utils/internal/parseGraphQLRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ export function parseDocumentNode(node: DocumentNode): ParsedGraphQLQuery {
}

async function parseQuery(query: string): Promise<ParsedGraphQLQuery | Error> {
const { parse } = await import('graphql').catch((error) => {
devUtils.error(
'Failed to parse a GraphQL query: cannot import the "graphql" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.',
)
throw error
})
/**
* @note Use `require` to get the "graphql" module here.
* It has to be scoped to this function because this module leaks to the
* root export. It has to be `require` because tools like Jest have trouble
* handling dynamic imports. It gets replaced with a dynamic import on build time.
*/
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { parse } = require('graphql')

try {
const ast = parse(query)
Expand Down
3 changes: 2 additions & 1 deletion tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from './config/plugins/esbuild/copyWorkerPlugin'
import { resolveCoreImportsPlugin } from './config/plugins/esbuild/resolveCoreImportsPlugin'
import { forceEsmExtensionsPlugin } from './config/plugins/esbuild/forceEsmExtensionsPlugin'
import { graphqlImportPlugin } from './config/plugins/esbuild/graphQLImportPlugin'
import packageJson from './package.json'

// Externalize the in-house dependencies so that the user
Expand All @@ -33,7 +34,7 @@ const coreConfig: Options = {
sourcemap: true,
dts: true,
tsconfig: path.resolve(__dirname, 'src/tsconfig.core.build.json'),
esbuildPlugins: [forceEsmExtensionsPlugin()],
esbuildPlugins: [graphqlImportPlugin(), forceEsmExtensionsPlugin()],
}

const nodeConfig: Options = {
Expand Down
Loading