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

feat(jest-util): add requireOrImportModule util for importing CJS or ESM #11199

Merged
merged 8 commits into from Mar 16, 2021
25 changes: 2 additions & 23 deletions packages/jest-transform/src/ScriptTransformer.ts
Expand Up @@ -7,7 +7,6 @@

import {createHash} from 'crypto';
import * as path from 'path';
import {pathToFileURL} from 'url';
import {transformSync as babelTransform} from '@babel/core';
// @ts-expect-error: should just be `require.resolve`, but the tests mess that up
import babelPluginIstanbul from 'babel-plugin-istanbul';
Expand All @@ -21,6 +20,7 @@ import type {Config} from '@jest/types';
import HasteMap from 'jest-haste-map';
import {
createDirectory,
importModule,
interopRequireDefault,
isPromise,
tryRealpath,
Expand Down Expand Up @@ -252,28 +252,7 @@ class ScriptTransformer {
await Promise.all(
this._config.transform.map(
async ([, transformPath, transformerConfig]) => {
let transformer: Transformer;

try {
transformer = interopRequireDefault(require(transformPath)).default;
} catch (error) {
if (error.code === 'ERR_REQUIRE_ESM') {
const configUrl = pathToFileURL(transformPath);

// node `import()` supports URL, but TypeScript doesn't know that
const importedConfig = await import(configUrl.href);

if (!importedConfig.default) {
throw new Error(
`Jest: Failed to load ESM transformer at ${transformPath} - did you use a default export?`,
);
}

transformer = importedConfig.default;
} else {
throw error;
}
}
let transformer: Transformer = await importModule(transformPath);

if (!transformer) {
throw new TypeError('Jest: a transform must export something.');
Expand Down
27 changes: 27 additions & 0 deletions packages/jest-util/src/importModule.ts
@@ -0,0 +1,27 @@
import {pathToFileURL} from 'url';
import interopRequireDefault from './interopRequireDefault';

export default async function importModule<T>(filePath: string): Promise<T> {
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
let module: T;
try {
module = interopRequireDefault(require(filePath)).default;
} catch (error) {
if (error.code === 'ERR_REQUIRE_ESM') {
const configUrl = pathToFileURL(filePath);

// node `import()` supports URL, but TypeScript doesn't know that
const importedConfig = await import(configUrl.href);

if (!importedConfig.default) {
throw new Error(
`Jest: Failed to load ESM at ${filePath} - did you use a default export?`,
);
}

module = importedConfig.default;
} else {
throw error;
}
}
return module;
}
1 change: 1 addition & 0 deletions packages/jest-util/src/index.ts
Expand Up @@ -23,3 +23,4 @@ export * as preRunMessage from './preRunMessage';
export {default as pluralize} from './pluralize';
export {default as formatTime} from './formatTime';
export {default as tryRealpath} from './tryRealpath';
export {default as importModule} from './importModule';
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved