Skip to content

Commit 2c297a9

Browse files
committed
feat: metafile support, jestConfig transformation
BREAKING CHANGE: new bundles are using @swc/jest
1 parent 749926f commit 2c297a9

File tree

7 files changed

+85
-57
lines changed

7 files changed

+85
-57
lines changed

__fixtures__/simple-project/.esbuild-jestrc.js

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/** @type {import('esbuild-jest-cli').ESBuildJestConfig} */
22
module.exports = {
3-
"esbuild": {
4-
"sourcemap": true,
5-
"platform": "node",
6-
"outdir": "../simple-project-bundled",
7-
"external": ["chalk", "dtrace-provider", "@linked-dependencies/external"],
3+
esbuild: {
4+
sourcemap: true,
5+
platform: "node",
6+
metafile: true,
7+
outdir: "../simple-project-bundled",
8+
external: ["chalk", "dtrace-provider", "@linked-dependencies/external"],
89
},
9-
"useTransformer": ({ build, transformer }) => {
10+
useTransformer: ({ build, transformer }) => {
1011
build.onLoad({ filter: /lodash\/noop/ }, async (args) => {
1112
const fs = await import('fs');
1213
const raw = await fs.promises.readFile(args.path, 'utf8');
@@ -18,9 +19,14 @@ module.exports = {
1819
};
1920
});
2021
},
21-
"package": {
22-
"name": "custom-name",
23-
"dependencies": {
22+
jestConfig: {
23+
transform: {
24+
'someCuriousPattern': '@swc/jest',
25+
},
26+
},
27+
package: {
28+
name: "custom-name",
29+
dependencies: {
2430
"@linked-dependencies/external": "../linked-dependencies/external",
2531
}
2632
}

__fixtures__/simple-project/jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
],
1212
testMatch: [
1313
'<rootDir>/src/**/*.test.js',
14+
'<rootDir>/src/**/*.test.cjs',
1415
],
1516
testEnvironment: 'jest-environment-emit/node',
1617
};

index.d.mts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import type { PluginBuild, BuildOptions } from 'esbuild';
2+
import type { Config as JestConfig } from '@jest/types';
23
import type { ScriptTransformer } from '@jest/transform';
34

45
export type ESBuildJestConfig = {
56
esbuild: Omit<
67
BuildOptions,
78
| 'bundle'
89
| 'splitting'
9-
| 'metafile'
1010
| 'outbase'
1111
| 'banner'
1212
| 'format'
1313
| 'entryPoints'
1414
>;
15+
jestConfig: JestConfig.InitialOptions | ((base: JestConfig.InitialOptions) => JestConfig.InitialOptions);
1516
package: Record<string, unknown> | ((base: Record<string, unknown>) => Record<string, unknown>);
1617
useTransformer: (context: { build: PluginBuild; transformer: ScriptTransformer; }) => void | Promise<void>;
1718
postTransform: (filePath: string, fileContent: string) => string;

index.mjs

+4-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ export async function build(esbuildJestConfig = {}) {
9696
globalConfig,
9797
projectConfig,
9898
tests: tests.map(t => t.path),
99-
package: wrapPackageMiddleware(esbuildJestConfig.package),
99+
jestConfig: wrapPatcherMiddleware(esbuildJestConfig.jestConfig),
100+
package: wrapPatcherMiddleware(esbuildJestConfig.package),
101+
writeMetafile: esbuildBaseConfig.metafile,
100102
useTransformer: esbuildJestConfig.useTransformer,
101103
}),
102104
...(esbuildBaseConfig.plugins || []),
@@ -108,7 +110,7 @@ export async function build(esbuildJestConfig = {}) {
108110
return buildResult;
109111
}
110112

111-
function wrapPackageMiddleware(config) {
113+
function wrapPatcherMiddleware(config) {
112114
return typeof config === 'function' ? config : createPackageMerger(config)
113115
}
114116

plugin.mjs

+54-44
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { writeFile } from 'node:fs/promises';
2-
import { sep, join, relative, resolve } from 'node:path';
1+
import {writeFile} from 'node:fs/promises';
2+
import {join, resolve, sep} from 'node:path';
33
import importFrom from 'import-from';
4-
import { logger, optimizeTracing } from "./utils/logger.mjs";
5-
import { convertPathToImport } from "./utils/resolve-module.mjs";
6-
import { isBuiltinReporter } from "./utils/is-builtin-reporter.mjs";
7-
import { mapSourceToOutputFiles } from "./utils/map-inputs-outputs.mjs";
8-
import { moveJsFile } from "./utils/move-js-file.mjs";
9-
import { pruneDirectory } from "./utils/prune-directory.mjs";
10-
import { JEST_DEPENDENCIES } from "./utils/jest-dependencies.mjs";
4+
import {logger, optimizeTracing} from "./utils/logger.mjs";
5+
import {convertPathToImport} from "./utils/resolve-module.mjs";
6+
import {isBuiltinReporter} from "./utils/is-builtin-reporter.mjs";
7+
import {mapSourceToOutputFiles, relativizeEntries} from "./utils/map-inputs-outputs.mjs";
8+
import {moveJsFile} from "./utils/move-js-file.mjs";
9+
import {pruneDirectory} from "./utils/prune-directory.mjs";
10+
import {JEST_DEPENDENCIES} from "./utils/jest-dependencies.mjs";
1111

1212
const noop = () => {};
1313

@@ -24,11 +24,13 @@ const __JEST_CONFIG = (log, config) => __CONTENT(log, config, 'create jest confi
2424
const __PACKAGE_JSON = (log, packageJson) => __CONTENT(log, packageJson, 'create package.json');
2525

2626
export default ({
27+
jestConfig: jestConfigMiddleware,
2728
package: packageMiddleware,
2829
globalConfig,
2930
projectConfig,
3031
tests,
3132
useTransformer = noop,
33+
writeMetafile = false,
3234
}) => {
3335
return {
3436
name: 'jest',
@@ -55,7 +57,46 @@ export default ({
5557

5658
__FILE_MAPPING_CREATING(logger, mappingInput);
5759
const mapping = mapSourceToOutputFiles(mappingInput);
60+
await moveExternalEntryPointsBackToRoot(mapping);
61+
await pruneDirectory(join(outdir, 'node_modules'));
5862
__FILE_MAPPING_CREATED(logger, mapping);
63+
const flattenedConfig = jestConfigMiddleware({
64+
maxWorkers: globalConfig.maxWorkers,
65+
testTimeout: globalConfig.testTimeout,
66+
reporters: globalConfig.reporters.map(mapReporter),
67+
68+
...projectConfig,
69+
cacheDirectory: undefined,
70+
cwd: undefined,
71+
coverageDirectory: mapFile(projectConfig.coverageDirectory),
72+
globalSetup: mapFile(projectConfig.globalSetup),
73+
globalTeardown: mapFile(projectConfig.globalTeardown),
74+
id: undefined,
75+
moduleNameMapper: undefined,
76+
rootDir: undefined,
77+
roots: undefined,
78+
runner: undefined,
79+
setupFiles: projectConfig.setupFiles.map(mapFile),
80+
setupFilesAfterEnv: projectConfig.setupFilesAfterEnv.map(mapFile),
81+
testEnvironment: mapFile(projectConfig.testEnvironment),
82+
testMatch: tests.map(mapFile),
83+
testRunner: mapTestRunner(mapFile(projectConfig.testRunner)),
84+
transform: {
85+
'^(?!node_modules/).+\\.js$': '@swc/jest',
86+
'^.+\\.jsx$': '@swc/jest',
87+
'^.+\\.tsx?$': '@swc/jest',
88+
},
89+
transformIgnorePatterns: [],
90+
});
91+
__JEST_CONFIG(logger, flattenedConfig);
92+
await writeFile(join(outdir, 'jest.config.json'), JSON.stringify(flattenedConfig, null, 2));
93+
94+
if (writeMetafile) {
95+
await writeFile(join(outdir, 'metafile.json'), JSON.stringify({
96+
...result.metafile,
97+
mapping: relativizeEntries([rootDir, outdir], mapping),
98+
}, null, 2) + '\n');
99+
}
59100

60101
/**
61102
* @param {string} file
@@ -125,37 +166,6 @@ export default ({
125166
const segments = modulePath.split(sep);
126167
return segments.map(x => x === 'node_modules' && replacements++ === 0 ? 'bundled_modules' : x).join(sep);
127168
}
128-
129-
await moveExternalEntryPointsBackToRoot();
130-
await pruneDirectory(join(outdir, 'node_modules'));
131-
132-
const flattenedConfig = {
133-
maxWorkers: globalConfig.maxWorkers,
134-
testTimeout: globalConfig.testTimeout,
135-
reporters: globalConfig.reporters.map(mapReporter),
136-
137-
...projectConfig,
138-
cacheDirectory: undefined,
139-
cwd: undefined,
140-
coverageDirectory: mapFile(projectConfig.coverageDirectory),
141-
globalSetup: mapFile(projectConfig.globalSetup),
142-
globalTeardown: mapFile(projectConfig.globalTeardown),
143-
id: undefined,
144-
moduleNameMapper: undefined,
145-
rootDir: undefined,
146-
roots: undefined,
147-
runner: undefined,
148-
setupFiles: projectConfig.setupFiles.map(mapFile),
149-
setupFilesAfterEnv: projectConfig.setupFilesAfterEnv.map(mapFile),
150-
testEnvironment: mapFile(projectConfig.testEnvironment),
151-
testMatch: tests.map(mapFile),
152-
testRunner: mapTestRunner(mapFile(projectConfig.testRunner)),
153-
transform: undefined,
154-
transformIgnorePatterns: undefined,
155-
};
156-
157-
__JEST_CONFIG(logger, flattenedConfig);
158-
await writeFile(join(outdir, 'jest.config.json'), JSON.stringify(flattenedConfig, null, 2));
159169
});
160170

161171
build.onEnd(async (result) => {
@@ -175,12 +185,12 @@ export default ({
175185
version: '0.0.0',
176186
private: true,
177187
scripts: {
178-
test: "NODE_OPTIONS='-r @babel/register' jest"
188+
test: "NODE_OPTIONS='-r @swc-node/register' jest"
179189
},
180190
dependencies: {
181-
"@babel/core": "^7.24.6",
182-
"@babel/plugin-transform-modules-commonjs": "^7.24.6",
183-
"@babel/register": "^7.24.6",
191+
"@swc/core": "^1.10.1",
192+
"@swc/jest": "^0.2.37",
193+
"@swc-node/register": "^1.10.9",
184194

185195
...externalDependencies,
186196
},

utils/map-inputs-outputs.mjs

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,20 @@ export function mapSourceToOutputFiles({ rootDir, outdir, sourceFiles, outputFil
2929
return result;
3030
}
3131

32+
export function relativizeEntries(rootDirs, mapping) {
33+
return Object.fromEntries(
34+
Object.entries(mapping).map(([source, output]) => [
35+
path.relative(rootDirs[0], source),
36+
path.relative(rootDirs[1], output),
37+
]),
38+
);
39+
}
40+
3241
function adaptTwoDots(filePath) {
3342
const segments = filePath.split(path.sep);
3443
return segments.map(convertTwoDots).join(path.sep);
3544
}
3645

3746
function convertTwoDots(segment) {
3847
return segment === '_.._' ? '..' : segment;
39-
4048
}

0 commit comments

Comments
 (0)