From 1cd28abbe35879892aacacc0308761a7616664c3 Mon Sep 17 00:00:00 2001 From: c0d01a5 Date: Wed, 31 Mar 2021 20:55:56 -0700 Subject: [PATCH] feat: support esbuild options --- README.md | 24 ++++++----- src/index.ts | 105 ++++++++++++++++++++++++++++--------------------- src/options.ts | 12 ------ 3 files changed, 71 insertions(+), 70 deletions(-) delete mode 100644 src/options.ts diff --git a/README.md b/README.md index 924278e..3ef35f2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # esbuild-jest ### A Jest transformer using esbuild + With this transformer you can use and transform (ts, js, tsx and jsx) files [![npm](https://img.shields.io/npm/v/esbuild-jest.svg)](https://www.npmjs.com/package/esbuild-jest) @@ -25,34 +26,31 @@ esbuild-jest transformer should be used in your Jest config file like this: ``` #### Setting up Jest config file with transformOptions + ```typescript -export interface Options { - jsxFactory?: string - jsxFragment?: string - sourcemap?: boolean | 'inline' | 'external' +import type { Loader, TransformOptions } from "esbuild"; + +export interface Options extends TransformOptions { loaders?: { - [ext: string]: Loader - }, - target?: string - format?: string + [ext: string]: Loader; + }; } ``` ```js { "transform": { - "^.+\\.tsx?$": [ - "esbuild-jest", - { + "^.+\\.tsx?$": [ + "esbuild-jest", + { sourcemap: true, loaders: { '.spec.ts': 'tsx' } - } + } ] } } ``` > Note: if you are using tsconfig.json and jsconfig.json with "paths", Please look `alias-hq` and there documentation https://github.com/davestewart/alias-hq/blob/master/docs/integrations.md - diff --git a/src/index.ts b/src/index.ts index e2bca0f..3965306 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,77 +1,92 @@ -import { extname } from 'path' +import { extname } from "path"; -import { Config } from '@jest/types' -import { TransformOptions as JestTransformOptions, Transformer } from '@jest/transform' -import { Format, Loader, TransformOptions, transformSync } from 'esbuild' +import { Config } from "@jest/types"; +import { + TransformOptions as JestTransformOptions, + Transformer, +} from "@jest/transform"; +import { Loader, TransformOptions, transformSync } from "esbuild"; -import { Options } from './options' -import { getExt, loaders } from './utils' +export interface Options extends TransformOptions { + loaders?: { + [ext: string]: Loader; + }; +} + +import { getExt, loaders } from "./utils"; const createTransformer = (options?: Options) => ({ - process(content: string, - filename: string, - config: Config.ProjectConfig, + process( + content: string, + filename: string, + config: Config.ProjectConfig, opts?: JestTransformOptions ) { - const sources = { code: content } - const ext = getExt(filename), extName = extname(filename).slice(1) + const { loaders: userLoaders = {}, ...esbuildOptions } = options || {}; + const { sourcemap, jsxFactory, jsxFragment } = esbuildOptions; + const sources = { code: content }; + const ext = getExt(filename), + extName = extname(filename).slice(1); - const enableSourcemaps = options?.sourcemap || false - const loader = (options?.loaders && options?.loaders[ext] - ? options.loaders[ext] - : loaders.includes(extName) ? extName: 'text' - ) as Loader - const sourcemaps: Partial = enableSourcemaps - ? { sourcemap: true, sourcesContent: false, sourcefile: filename } - : {} + const enableSourcemaps = sourcemap || false; + const loader = (userLoaders[ext] + ? userLoaders[ext] + : loaders.includes(extName) + ? extName + : "text") as Loader; + const sourcemaps: Partial = enableSourcemaps + ? { sourcemap: true, sourcesContent: false, sourcefile: filename } + : {}; - /// this logic or code from + /// this logic or code from /// https://github.com/threepointone/esjest-transform/blob/main/src/index.js /// this will support the jest.mock /// https://github.com/aelbore/esbuild-jest/issues/12 /// TODO: transform the jest.mock to a function using babel traverse/parse then hoist it if (sources.code.indexOf("ock(") >= 0 || opts?.instrument) { - const source = require('./transformer').babelTransform({ + const source = require("./transformer").babelTransform({ sourceText: content, sourcePath: filename, config, - options: opts - }) - sources.code = source + options: opts, + }); + sources.code = source; } const result = transformSync(sources.code, { loader, - format: options?.format as Format || 'cjs', - target: options?.target || 'es2018', - ...(options?.jsxFactory ? { jsxFactory: options.jsxFactory }: {}), - ...(options?.jsxFragment ? { jsxFragment: options.jsxFragment }: {}), - ...sourcemaps - }) - + ...esbuildOptions, + format: esbuildOptions.format || "cjs", + target: esbuildOptions.target || "es2018", + ...(jsxFactory ? { jsxFactory } : {}), + ...(jsxFragment ? { jsxFragment } : {}), + ...sourcemaps, + }); + let { map, code } = result; if (enableSourcemaps) { map = { ...JSON.parse(result.map), sourcesContent: null, - } - + }; + // Append the inline sourcemap manually to ensure the "sourcesContent" // is null. Otherwise, breakpoints won't pause within the actual source. - code = code + '\n//# sourceMappingURL=data:application/json;base64,' + Buffer.from(JSON.stringify(map)).toString('base64') + code = + code + + "\n//# sourceMappingURL=data:application/json;base64," + + Buffer.from(JSON.stringify(map)).toString("base64"); } else { - map = null + map = null; } - - return { code, map } - } -}) -const transformer: Pick = { - canInstrument: true, - createTransformer -} + return { code, map }; + }, +}); -export * from './options' +const transformer: Pick = { + canInstrument: true, + createTransformer, +}; -export default transformer \ No newline at end of file +export default transformer; diff --git a/src/options.ts b/src/options.ts deleted file mode 100644 index 992e457..0000000 --- a/src/options.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Loader } from 'esbuild' - -export interface Options { - jsxFactory?: string - jsxFragment?: string - sourcemap?: boolean | 'inline' | 'external' - loaders?: { - [ext: string]: Loader - }, - target?: string - format?: string -} \ No newline at end of file