diff --git a/__fixtures__/simple-project/.esbuild-jestrc.js b/__fixtures__/simple-project/.esbuild-jestrc.js index a6bc626..5383c8f 100644 --- a/__fixtures__/simple-project/.esbuild-jestrc.js +++ b/__fixtures__/simple-project/.esbuild-jestrc.js @@ -1,12 +1,13 @@ /** @type {import('esbuild-jest-cli').ESBuildJestConfig} */ module.exports = { - "esbuild": { - "sourcemap": true, - "platform": "node", - "outdir": "../simple-project-bundled", - "external": ["chalk", "dtrace-provider", "@linked-dependencies/external"], + esbuild: { + sourcemap: true, + platform: "node", + metafile: true, + outdir: "../simple-project-bundled", + external: ["chalk", "dtrace-provider", "@linked-dependencies/external"], }, - "useTransformer": ({ build, transformer }) => { + useTransformer: ({ build, transformer }) => { build.onLoad({ filter: /lodash\/noop/ }, async (args) => { const fs = await import('fs'); const raw = await fs.promises.readFile(args.path, 'utf8'); @@ -18,9 +19,14 @@ module.exports = { }; }); }, - "package": { - "name": "custom-name", - "dependencies": { + jestConfig: { + transform: { + 'someCuriousPattern': '@swc/jest', + }, + }, + package: { + name: "custom-name", + dependencies: { "@linked-dependencies/external": "../linked-dependencies/external", } } diff --git a/__fixtures__/simple-project/jest.config.js b/__fixtures__/simple-project/jest.config.js index 7db0e8a..177bdd3 100644 --- a/__fixtures__/simple-project/jest.config.js +++ b/__fixtures__/simple-project/jest.config.js @@ -11,6 +11,7 @@ module.exports = { ], testMatch: [ '/src/**/*.test.js', + '/src/**/*.test.cjs', ], testEnvironment: 'jest-environment-emit/node', }; diff --git a/__fixtures__/simple-project/src/entry2.test.js b/__fixtures__/simple-project/src/entry2.test.cjs similarity index 100% rename from __fixtures__/simple-project/src/entry2.test.js rename to __fixtures__/simple-project/src/entry2.test.cjs diff --git a/index.d.mts b/index.d.mts index 289eed4..e5cc076 100644 --- a/index.d.mts +++ b/index.d.mts @@ -1,4 +1,5 @@ import type { PluginBuild, BuildOptions } from 'esbuild'; +import type { Config as JestConfig } from '@jest/types'; import type { ScriptTransformer } from '@jest/transform'; export type ESBuildJestConfig = { @@ -6,12 +7,12 @@ export type ESBuildJestConfig = { BuildOptions, | 'bundle' | 'splitting' - | 'metafile' | 'outbase' | 'banner' | 'format' | 'entryPoints' >; + jestConfig: JestConfig.InitialOptions | ((base: JestConfig.InitialOptions) => JestConfig.InitialOptions); package: Record | ((base: Record) => Record); useTransformer: (context: { build: PluginBuild; transformer: ScriptTransformer; }) => void | Promise; postTransform: (filePath: string, fileContent: string) => string; diff --git a/index.mjs b/index.mjs index e93d3f8..86ade2e 100644 --- a/index.mjs +++ b/index.mjs @@ -96,7 +96,9 @@ export async function build(esbuildJestConfig = {}) { globalConfig, projectConfig, tests: tests.map(t => t.path), - package: wrapPackageMiddleware(esbuildJestConfig.package), + jestConfig: wrapPatcherMiddleware(esbuildJestConfig.jestConfig), + package: wrapPatcherMiddleware(esbuildJestConfig.package), + writeMetafile: esbuildBaseConfig.metafile, useTransformer: esbuildJestConfig.useTransformer, }), ...(esbuildBaseConfig.plugins || []), @@ -108,7 +110,7 @@ export async function build(esbuildJestConfig = {}) { return buildResult; } -function wrapPackageMiddleware(config) { +function wrapPatcherMiddleware(config) { return typeof config === 'function' ? config : createPackageMerger(config) } diff --git a/plugin.mjs b/plugin.mjs index a4c3d9d..ca1f689 100644 --- a/plugin.mjs +++ b/plugin.mjs @@ -1,13 +1,13 @@ -import { writeFile } from 'node:fs/promises'; -import { sep, join, relative, resolve } from 'node:path'; +import {writeFile} from 'node:fs/promises'; +import {join, resolve, sep} from 'node:path'; import importFrom from 'import-from'; -import { logger, optimizeTracing } from "./utils/logger.mjs"; -import { convertPathToImport } from "./utils/resolve-module.mjs"; -import { isBuiltinReporter } from "./utils/is-builtin-reporter.mjs"; -import { mapSourceToOutputFiles } from "./utils/map-inputs-outputs.mjs"; -import { moveJsFile } from "./utils/move-js-file.mjs"; -import { pruneDirectory } from "./utils/prune-directory.mjs"; -import { JEST_DEPENDENCIES } from "./utils/jest-dependencies.mjs"; +import {logger, optimizeTracing} from "./utils/logger.mjs"; +import {convertPathToImport} from "./utils/resolve-module.mjs"; +import {isBuiltinReporter} from "./utils/is-builtin-reporter.mjs"; +import {mapSourceToOutputFiles, relativizeEntries} from "./utils/map-inputs-outputs.mjs"; +import {moveJsFile} from "./utils/move-js-file.mjs"; +import {pruneDirectory} from "./utils/prune-directory.mjs"; +import {JEST_DEPENDENCIES} from "./utils/jest-dependencies.mjs"; const noop = () => {}; @@ -24,11 +24,13 @@ const __JEST_CONFIG = (log, config) => __CONTENT(log, config, 'create jest confi const __PACKAGE_JSON = (log, packageJson) => __CONTENT(log, packageJson, 'create package.json'); export default ({ + jestConfig: jestConfigMiddleware, package: packageMiddleware, globalConfig, projectConfig, tests, useTransformer = noop, + writeMetafile = false, }) => { return { name: 'jest', @@ -55,7 +57,46 @@ export default ({ __FILE_MAPPING_CREATING(logger, mappingInput); const mapping = mapSourceToOutputFiles(mappingInput); + await moveExternalEntryPointsBackToRoot(mapping); + await pruneDirectory(join(outdir, 'node_modules')); __FILE_MAPPING_CREATED(logger, mapping); + const flattenedConfig = jestConfigMiddleware({ + maxWorkers: globalConfig.maxWorkers, + testTimeout: globalConfig.testTimeout, + reporters: globalConfig.reporters.map(mapReporter), + + ...projectConfig, + cacheDirectory: undefined, + cwd: undefined, + coverageDirectory: mapFile(projectConfig.coverageDirectory), + globalSetup: mapFile(projectConfig.globalSetup), + globalTeardown: mapFile(projectConfig.globalTeardown), + id: undefined, + moduleNameMapper: undefined, + rootDir: undefined, + roots: undefined, + runner: undefined, + setupFiles: projectConfig.setupFiles.map(mapFile), + setupFilesAfterEnv: projectConfig.setupFilesAfterEnv.map(mapFile), + testEnvironment: mapFile(projectConfig.testEnvironment), + testMatch: tests.map(mapFile), + testRunner: mapTestRunner(mapFile(projectConfig.testRunner)), + transform: { + '^(?!node_modules/).+\\.js$': '@swc/jest', + '^.+\\.jsx$': '@swc/jest', + '^.+\\.tsx?$': '@swc/jest', + }, + transformIgnorePatterns: [], + }); + __JEST_CONFIG(logger, flattenedConfig); + await writeFile(join(outdir, 'jest.config.json'), JSON.stringify(flattenedConfig, null, 2)); + + if (writeMetafile) { + await writeFile(join(outdir, 'metafile.json'), JSON.stringify({ + ...result.metafile, + mapping: relativizeEntries([rootDir, outdir], mapping), + }, null, 2) + '\n'); + } /** * @param {string} file @@ -125,37 +166,6 @@ export default ({ const segments = modulePath.split(sep); return segments.map(x => x === 'node_modules' && replacements++ === 0 ? 'bundled_modules' : x).join(sep); } - - await moveExternalEntryPointsBackToRoot(); - await pruneDirectory(join(outdir, 'node_modules')); - - const flattenedConfig = { - maxWorkers: globalConfig.maxWorkers, - testTimeout: globalConfig.testTimeout, - reporters: globalConfig.reporters.map(mapReporter), - - ...projectConfig, - cacheDirectory: undefined, - cwd: undefined, - coverageDirectory: mapFile(projectConfig.coverageDirectory), - globalSetup: mapFile(projectConfig.globalSetup), - globalTeardown: mapFile(projectConfig.globalTeardown), - id: undefined, - moduleNameMapper: undefined, - rootDir: undefined, - roots: undefined, - runner: undefined, - setupFiles: projectConfig.setupFiles.map(mapFile), - setupFilesAfterEnv: projectConfig.setupFilesAfterEnv.map(mapFile), - testEnvironment: mapFile(projectConfig.testEnvironment), - testMatch: tests.map(mapFile), - testRunner: mapTestRunner(mapFile(projectConfig.testRunner)), - transform: undefined, - transformIgnorePatterns: undefined, - }; - - __JEST_CONFIG(logger, flattenedConfig); - await writeFile(join(outdir, 'jest.config.json'), JSON.stringify(flattenedConfig, null, 2)); }); build.onEnd(async (result) => { @@ -175,12 +185,12 @@ export default ({ version: '0.0.0', private: true, scripts: { - test: "NODE_OPTIONS='-r @babel/register' jest" + test: "NODE_OPTIONS='-r @swc-node/register' jest" }, dependencies: { - "@babel/core": "^7.24.6", - "@babel/plugin-transform-modules-commonjs": "^7.24.6", - "@babel/register": "^7.24.6", + "@swc/core": "^1.10.1", + "@swc/jest": "^0.2.37", + "@swc-node/register": "^1.10.9", ...externalDependencies, }, diff --git a/utils/map-inputs-outputs.mjs b/utils/map-inputs-outputs.mjs index 864e3dc..f49fddf 100644 --- a/utils/map-inputs-outputs.mjs +++ b/utils/map-inputs-outputs.mjs @@ -29,6 +29,15 @@ export function mapSourceToOutputFiles({ rootDir, outdir, sourceFiles, outputFil return result; } +export function relativizeEntries(rootDirs, mapping) { + return Object.fromEntries( + Object.entries(mapping).map(([source, output]) => [ + path.relative(rootDirs[0], source), + path.relative(rootDirs[1], output), + ]), + ); +} + function adaptTwoDots(filePath) { const segments = filePath.split(path.sep); return segments.map(convertTwoDots).join(path.sep); @@ -36,5 +45,4 @@ function adaptTwoDots(filePath) { function convertTwoDots(segment) { return segment === '_.._' ? '..' : segment; - }