Skip to content

Commit

Permalink
feat: more flexible transformer mechanism (#19)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: migrate your preTransform and postTransform callbacks
  • Loading branch information
noomorph authored Jun 2, 2024
1 parent 391a116 commit d3fc458
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 44 deletions.
16 changes: 11 additions & 5 deletions __fixtures__/simple-project/.esbuild-jestrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @type {import('esbuild-jest-cli').ESBuildJestConfig} */
module.exports = {
"esbuild": {
"sourcemap": true,
Expand All @@ -8,12 +9,17 @@ module.exports = {
},
"external": ["chalk", "dtrace-provider", "@linked-dependencies/external"],
},
"preTransform": (path, contents) => {
if (path.includes('lodash/noop')) {
return 'console.log("You called noop!");\n' + contents;
}
"useTransformer": ({ build, transformer }) => {
build.onLoad({ filter: /lodash\/noop/ }, async (args) => {
const fs = await import('fs');
const raw = await fs.promises.readFile(args.path, 'utf8');
const { code: transformed } = transformer.transformSource(args.path, raw, {});

return contents;
return {
contents: 'console.log("You called noop!");\n' + transformed,
loader: 'js',
};
});
},
"package": {
"name": "custom-name",
Expand Down
5 changes: 3 additions & 2 deletions index.d.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {BuildOptions} from 'esbuild';
import type { PluginBuild, BuildOptions } from 'esbuild';
import type { ScriptTransformer } from '@jest/transform';

export type ESBuildJestConfig = {
esbuild: Omit<
Expand All @@ -12,7 +13,7 @@ export type ESBuildJestConfig = {
| 'entryPoints'
>;
package: Record<string, unknown> | ((base: Record<string, unknown>) => Record<string, unknown>);
preTransform: (filePath: string, fileContent: string) => string;
useTransformer: (context: { build: PluginBuild; transformer: ScriptTransformer; }) => void | Promise<void>;
postTransform: (filePath: string, fileContent: string) => string;
};

Expand Down
4 changes: 2 additions & 2 deletions index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const __IS_EXTERNAL__ = optimizeTracing((id, external) => {
optimizedLogger.trace(`mark as ${external ? 'external' : 'internal'}: ${id}`);
});

/** @param {import('esbuild-jest-cli').ESBuildJestConfig} esbuildJestConfig */
export async function build(esbuildJestConfig = {}) {
const rootDir = process.cwd();

Expand Down Expand Up @@ -101,8 +102,7 @@ export async function build(esbuildJestConfig = {}) {
projectConfig,
tests: tests.map(t => t.path),
package: wrapPackageMiddleware(esbuildJestConfig.package),
preTransform: esbuildJestConfig.preTransform,
postTransform: esbuildJestConfig.postTransform,
useTransformer: esbuildJestConfig.useTransformer,
}),
...(esbuildBaseConfig.plugins || []),
],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
},
"devDependencies": {
"@jest/types": "^29.6.3",
"@jest/transform": "^29.6.3",
"esbuild": "^0.19.8"
}
}
43 changes: 8 additions & 35 deletions plugin.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { readFile, writeFile } from 'node:fs/promises';
import { sep, join, relative, resolve } from 'node:path';
import { writeFile } from 'node:fs/promises';
import { sep, join, resolve } from 'node:path';
import importFrom from 'import-from';
import { logger, optimizedLogger, optimizeTracing } from "./utils/logger.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 } 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 passThrough = (filePath, fileContents) => fileContents;
const noop = () => {};

const __CONTENT = optimizeTracing((log, content, message) => log.trace(
typeof content === 'object'
Expand All @@ -18,16 +18,6 @@ const __CONTENT = optimizeTracing((log, content, message) => log.trace(
message
));

const __DIFF = optimizeTracing((log, before, after, message) => {
if (before !== after) {
__CONTENT(log, after, message);
}
});

const __READ = (log, content) => __CONTENT(log, content, 'read file');
const __PREPROCESS = (log, before, after) => __DIFF(log, before, after, 'pre-process file');
const __TRANSFORM = (log, content) => __CONTENT(log, content, 'transform file');
const __POSTPROCESS = (log, before, after) => __DIFF(log, before, after, 'post-process file');
const __FILE_MAPPING_CREATING = (log, input) => __CONTENT(log, input, 'creating file mapping');
const __FILE_MAPPING_CREATED = (log, input) => __CONTENT(log, input, 'created file mapping');
const __JEST_CONFIG = (log, config) => __CONTENT(log, config, 'create jest config');
Expand All @@ -38,8 +28,7 @@ export default ({
globalConfig,
projectConfig,
tests,
preTransform = passThrough,
postTransform = passThrough,
useTransformer = noop,
}) => {
return {
name: 'jest',
Expand All @@ -51,25 +40,9 @@ export default ({
const { createScriptTransformer } = importFrom(rootDir, '@jest/transform');
const transformer = await createScriptTransformer(projectConfig);

build.onLoad({ filter: /.*/ }, async (args) => {
const log = optimizedLogger.child({ tid: ['jest-transform', args.path] });

return log.trace.complete(relative(rootDir, args.path), async () => {
const fileContent = await readFile(args.path, 'utf8');
__READ(log, fileContent);

const preprocessed = preTransform(args.path, fileContent);
__PREPROCESS(log, fileContent, preprocessed);

const { code: transformed } = transformer.transformSource(args.path, preprocessed, {});
__TRANSFORM(log, transformed);

const contents = postTransform(args.path, transformed);
__POSTPROCESS(log, transformed, contents);

const loader = args.path.endsWith('.json') ? 'json' : 'js';
return { contents, loader };
});
await useTransformer({
build,
transformer,
});

build.onEnd(async (result) => {
Expand Down

0 comments on commit d3fc458

Please sign in to comment.