diff --git a/docs/user/config/astTransformers.md b/docs/user/config/astTransformers.md index e947cbcd75..9c747e099d 100644 --- a/docs/user/config/astTransformers.md +++ b/docs/user/config/astTransformers.md @@ -5,7 +5,12 @@ title: AST transformers option `ts-jest` by default does hoisting for a few `jest` methods via a TypeScript AST transformer. One can also create custom TypeScript AST transformers and provide them to `ts-jest` to include into compilation process. -The option is `astTransformers` and it allows ones to specify which TypeScript AST transformers to use with `ts-jest`. +The option is `astTransformers` and it allows ones to specify which 3 types of TypeScript AST transformers to use with `ts-jest`: + +- `before` means your transformers get run before TS ones, which means your transformers will get raw TS syntax +instead of transpiled syntax (e.g `import` instead of `require` or `define` ). +- `after` means your transformers get run after TS ones, which gets transpiled syntax. +- `afterDeclarations` means your transformers get run during `d.ts` generation phase, allowing you to transform output type declarations. ### Examples @@ -17,7 +22,9 @@ module.exports = { // [...] globals: { 'ts-jest': { - astTransformers: ['my-custom-transformer'], + astTransformers: { + before: ['my-custom-transformer'], + }, } } }; @@ -32,7 +39,9 @@ module.exports = { "jest": { "globals": { "ts-jest": { - astTransformers: ['my-custom-transformer'], + astTransformers: { + "before": ["my-custom-transformer"] + } } } } @@ -43,5 +52,4 @@ module.exports = { ### Writing custom TypeScript AST transformers -To write a custom TypeScript AST transformers, one can take a look at the one that `ts-jest` is using at -https://github.com/kulshekhar/ts-jest/tree/master/src/transformers +To write a custom TypeScript AST transformers, one can take a look at [the one](https://github.com/kulshekhar/ts-jest/tree/master/src/transformers) that `ts-jest` is using. diff --git a/e2e/__tests__/__snapshots__/logger.test.ts.snap b/e2e/__tests__/__snapshots__/logger.test.ts.snap index c4035da845..3c918d0ce9 100644 --- a/e2e/__tests__/__snapshots__/logger.test.ts.snap +++ b/e2e/__tests__/__snapshots__/logger.test.ts.snap @@ -124,6 +124,117 @@ Array [ ] `; +exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7-string-config" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7-string-config" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers + PASS ./Hello.spec.ts + Hello Class + √ should create a new Hello + + Test Suites: 1 passed, 1 total + Tests: 1 passed, 1 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + exports[`ts-jest logging with unsupported version test with TS_JEST_DISABLE_VER_CHECKER is not set in process.env should pass using template "with-unsupported-version" 1`] = ` √ jest ↳ exit code: 0 diff --git a/e2e/__tests__/logger.test.ts b/e2e/__tests__/logger.test.ts index 04c25bab78..9a82a97e67 100644 --- a/e2e/__tests__/logger.test.ts +++ b/e2e/__tests__/logger.test.ts @@ -47,7 +47,7 @@ describe('ts-jest logging', () => { const filteredEntries = result.logFileEntries // keep only debug and above .filter(m => (m.context[LogContexts.logLevel] || 0) >= LogLevels.debug) - // simplify entires + // simplify entries // eslint-disable-next-line @typescript-eslint/restrict-template-expressions .map(e => result.normalize(`[level:${e.context[LogContexts.logLevel]}] ${e.message}`)) expect(filteredEntries).toMatchSnapshot() @@ -90,4 +90,38 @@ describe('ts-jest logging', () => { }) }) } + + describe('deprecation warning', () => { + describe('with astTransformers config as string array', () => { + const testCase = configureTestCase('simple', { + tsJestConfig: { + astTransformers: [] + } + }) + + testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('with astTransformers config as an object', () => { + const testCase = configureTestCase('simple', { + tsJestConfig: { + astTransformers: {} + } + }) + + testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + }) }) diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts index 9f49caaa99..a1606918be 100644 --- a/src/__helpers__/fakers.ts +++ b/src/__helpers__/fakers.ts @@ -16,7 +16,7 @@ export function tsJestConfig(options?: Partial): TsJestConfig { return { isolatedModules: false, compiler: 'typescript', - transformers: [], + transformers: options?.transformers ?? Object.create(null), babelConfig: undefined, tsConfig: undefined, packageJson: undefined, diff --git a/src/__mocks__/dummy-transformer.js b/src/__mocks__/dummy-transformer.js new file mode 100644 index 0000000000..e84abdace0 --- /dev/null +++ b/src/__mocks__/dummy-transformer.js @@ -0,0 +1,17 @@ +const { LogContexts, LogLevels } = require('bs-logger') + +function factory(cs) { + const logger = cs.logger.child({ namespace: 'dummy-transformer' }) + const ts = cs.compilerModule + + function createVisitor(_ctx, _) { + return (node) => node + } + + return (ctx) => + logger.wrap({ [LogContexts.logLevel]: LogLevels.debug, call: null }, 'visitSourceFileNode(): dummy', (sf) => + ts.visitNode(sf, createVisitor(ctx, sf)) + ) +} + +exports.factory = factory diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index 748fa2b01c..3620e7eb03 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -15,7 +15,7 @@ const SOURCE_MAPPING_PREFIX = 'sourceMappingURL=' /** * Update the output remapping the source map. */ -function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string) { +function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string): string { const base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64') const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}` @@ -45,7 +45,7 @@ const compileAndUpdateOutput = (compileFn: CompileFn, logger: Logger) => ( code: string, fileName: string, lineOffset?: number, -) => { +): string => { logger.debug({ fileName }, 'compileAndUpdateOutput(): get compile output') const [value, sourceMap] = compileFn(code, fileName, lineOffset) diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index e5f934d79e..357b7fa513 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -7,12 +7,26 @@ import * as _ts from 'typescript' import type { ConfigSet } from '../config/config-set' import { LINE_FEED } from '../constants' -import { CompilerInstance, MemoryCache, SourceOutput, TSFile } from '../types' +import { CompilerInstance, SourceOutput } from '../types' import { Errors, interpolate } from '../util/messages' import { parse, stringify } from '../util/json' import { sha1 } from '../util/sha1' +/** where key is filepath */ +type TSFiles = Map + +interface TSFile { + text?: string + output?: string + version: number +} + +interface MemoryCache { + resolvedModules: Map + files: TSFiles +} + function doTypeChecking( configs: ConfigSet, diagnosedFiles: string[], diff --git a/src/config/__snapshots__/config-set.spec.ts.snap b/src/config/__snapshots__/config-set.spec.ts.snap index 44a72c7738..9de5e78a18 100644 --- a/src/config/__snapshots__/config-set.spec.ts.snap +++ b/src/config/__snapshots__/config-set.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`cacheKey should be a string 1`] = `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":[],\\"tsConfig\\":{\\"kind\\":\\"file\\",\\"value\\":\\"\\"}},\\"tsconfig\\":{\\"options\\":{\\"configFilePath\\":\\"\\",\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1,\\"types\\":[]},\\"raw\\":{\\"compileOnSave\\":false,\\"compilerOptions\\":{\\"composite\\":true,\\"declaration\\":true,\\"types\\":[]},\\"exclude\\":[\\"foo/**/*\\"],\\"include\\":[\\"bar/**/*\\"]}}}"`; +exports[`cacheKey should be a string 1`] = `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":{},\\"tsConfig\\":{\\"kind\\":\\"file\\",\\"value\\":\\"\\"}},\\"tsconfig\\":{\\"options\\":{\\"configFilePath\\":\\"\\",\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1,\\"types\\":[]},\\"raw\\":{\\"compileOnSave\\":false,\\"compilerOptions\\":{\\"composite\\":true,\\"declaration\\":true,\\"types\\":[]},\\"exclude\\":[\\"foo/**/*\\"],\\"include\\":[\\"bar/**/*\\"]}}}"`; exports[`isTestFile should return a boolean value whether the file matches test pattern 1`] = `true`; @@ -67,7 +67,7 @@ Object { "value": undefined, }, "stringifyContentPathRegex": undefined, - "transformers": Array [], + "transformers": Object {}, "tsConfig": Object { "kind": "file", "value": "", @@ -156,6 +156,45 @@ Array [ ] `; +exports[`tsCustomTransformers should return an object containing all resolved transformers 1`] = ` +Object { + "before": Array [ + [Function], + ], +} +`; + +exports[`tsCustomTransformers should return an object containing all resolved transformers 2`] = ` +Object { + "before": Array [ + [Function], + [Function], + ], +} +`; + +exports[`tsCustomTransformers should return an object containing all resolved transformers 3`] = ` +Object { + "after": Array [ + [Function], + ], + "before": Array [ + [Function], + ], +} +`; + +exports[`tsCustomTransformers should return an object containing all resolved transformers 4`] = ` +Object { + "afterDeclarations": Array [ + [Function], + ], + "before": Array [ + [Function], + ], +} +`; + exports[`tsJest should return correct defaults 1`] = ` Object { "babelConfig": undefined, @@ -175,10 +214,15 @@ Object { "value": undefined, }, "stringifyContentPathRegex": undefined, - "transformers": Array [], + "transformers": Object {}, "tsConfig": Object { "kind": "file", "value": undefined, }, } `; + +exports[`tsJest transformers should display deprecation warning message when config transformers is string array 1`] = ` +"[level:40] The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers +" +`; diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts index eed844839c..a644b0cd61 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -18,6 +18,7 @@ import { mocked } from '../util/testing' import { IGNORE_DIAGNOSTIC_CODES, MATCH_NOTHING, TS_JEST_OUT_DIR } from './config-set' // eslint-disable-next-line no-duplicate-imports import type { ConfigSet } from './config-set' +import { Deprecations } from '../util/messages' jest.mock('../util/backports') jest.mock('../index') @@ -206,6 +207,61 @@ describe('tsJest', () => { }) }) + describe('transformers', () => { + const logger = testing.createLoggerMock() + + it('should display deprecation warning message when config transformers is string array', () => { + const cs = createConfigSet({ + jestConfig: { + rootDir: 'src', + cwd: 'src', + globals: { + 'ts-jest': { + astTransformers: ['dummy-transformer'], + }, + }, + } as any, + logger, + resolve: null, + }) + logger.target.clear() + + expect(Object.keys(cs.tsJest.transformers)).toHaveLength(1) + expect(logger.target.lines[1]).toMatchSnapshot() + }) + + it.each([ + {}, + { + before: ['dummy-transformer'], + }, + { + after: ['dummy-transformer'], + }, + { + afterDeclarations: ['dummy-transformer'], + }, + ])('should not display deprecation warning message when config transformers is an object', (data) => { + const cs = createConfigSet({ + jestConfig: { + rootDir: 'src', + cwd: 'src', + globals: { + 'ts-jest': { + astTransformers: data, + }, + }, + } as any, + logger, + resolve: null, + }) + logger.target.clear() + + expect(Object.keys(cs.tsJest.transformers)).toHaveLength(Object.keys(data).length) + expect(logger.target.lines[1]).not.toContain(Deprecations.AstTransformerArrayConfig) + }) + }) // custom AST transformers + describe('babelConfig', () => { const logger = testing.createLoggerMock() @@ -417,7 +473,7 @@ describe('tsJest', () => { }) // compiler }) // tsJest -describe('typescript', () => { +describe('parsedTsConfig', () => { const get = (tsJest?: TsJestGlobalOptions, parentConfig?: TsJestGlobalOptions) => createConfigSet({ tsJestConfig: tsJest, parentConfig }).parsedTsConfig @@ -497,7 +553,7 @@ describe('typescript', () => { expect(cs.parsedTsConfig.options.allowSyntheticDefaultImports).toBeFalsy() expect(target.lines.warn).toHaveLength(0) }) -}) // typescript +}) // parsedTsConfig describe('resolvePath', () => { it('should resolve paths', () => { @@ -960,6 +1016,36 @@ describe('tsCompiler', () => { }) }) // tsCompiler +describe('tsCustomTransformers', () => { + it.each([ + {}, + { + before: ['dummy-transformer'], + }, + { + after: ['dummy-transformer'], + }, + { + afterDeclarations: ['dummy-transformer'], + }, + ])('should return an object containing all resolved transformers', (data) => { + const cs = createConfigSet({ + jestConfig: { + rootDir: 'src', + cwd: 'src', + globals: { + 'ts-jest': { + astTransformers: data, + }, + }, + } as any, + resolve: null, + }) + + expect(cs.tsCustomTransformers).toMatchSnapshot() + }) +}) + describe('hooks', () => { it('should return empty object when environment variable TS_JEST_HOOKS is undefined', () => { expect(createConfigSet().hooks).toEqual({}) diff --git a/src/config/config-set.ts b/src/config/config-set.ts index e9c9c3c37d..36182d7c52 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -15,6 +15,7 @@ import { globsToMatcher } from 'jest-util' import json5 = require('json5') import { dirname, extname, isAbsolute, join, normalize, resolve } from 'path' import { + Bundle, CompilerOptions, CustomTransformers, Diagnostic, @@ -23,6 +24,7 @@ import { ParsedCommandLine, ScriptTarget, SourceFile, + TransformerFactory, } from 'typescript' import { digest as MY_DIGEST, version as MY_VERSION } from '..' @@ -33,6 +35,7 @@ import { AstTransformerDesc, BabelConfig, BabelJestTransformer, + ConfigCustomTransformer, TsCompiler, TsJestConfig, TsJestGlobalOptions, @@ -46,13 +49,19 @@ import { stringify } from '../util/json' import { JsonableValue } from '../util/jsonable-value' import { rootLogger } from '../util/logger' import { Memoize } from '../util/memoize' -import { Errors, ImportReasons, interpolate } from '../util/messages' +import { Deprecations, Errors, ImportReasons, interpolate } from '../util/messages' import { normalizeSlashes } from '../util/normalize-slashes' import { sha1 } from '../util/sha1' import { TSError } from '../util/ts-error' const logger = rootLogger.child({ namespace: 'config' }) +interface AstTransformer { + before: AstTransformerDesc[] + after?: AstTransformerDesc[] + afterDeclarations?: AstTransformerDesc[] +} + /** * @internal */ @@ -260,7 +269,41 @@ export class ConfigSet { } // transformers - const transformers = (options.astTransformers || []).map((mod) => this.resolvePath(mod, { nodeResolve: true })) + let transformers: ConfigCustomTransformer = Object.create(null) + const { astTransformers } = options + if (astTransformers) { + if (Array.isArray(astTransformers)) { + this.logger.warn(Deprecations.AstTransformerArrayConfig) + + transformers = { + before: astTransformers.map((transformerPath) => this.resolvePath(transformerPath, { nodeResolve: true })), + } + } else { + if (astTransformers.before) { + transformers = { + before: astTransformers.before.map((transformerPath: string) => + this.resolvePath(transformerPath, { nodeResolve: true }), + ), + } + } + if (astTransformers.after) { + transformers = { + ...transformers, + after: astTransformers.after.map((transformerPath: string) => + this.resolvePath(transformerPath, { nodeResolve: true }), + ), + } + } + if (astTransformers.afterDeclarations) { + transformers = { + ...transformers, + afterDeclarations: astTransformers.afterDeclarations.map((transformerPath: string) => + this.resolvePath(transformerPath, { nodeResolve: true }), + ), + } + } + } + } // babel jest const { babelConfig: babelConfigOpt } = options @@ -467,8 +510,35 @@ export class ConfigSet { * @internal */ @Memoize() - private get astTransformers(): AstTransformerDesc[] { - return [...internalAstTransformers, ...this.tsJest.transformers.map((m) => require(m))] + private get astTransformers(): AstTransformer { + let astTransformers: AstTransformer = { + before: [...internalAstTransformers], + } + const { transformers } = this.tsJest + if (transformers.before) { + astTransformers = { + before: [ + ...astTransformers.before, + ...transformers.before.map((transformerFilePath: string) => require(transformerFilePath)), + ], + } + } + if (transformers.after) { + astTransformers = { + ...astTransformers, + after: transformers.after.map((transformerFilePath: string) => require(transformerFilePath)), + } + } + if (transformers.afterDeclarations) { + astTransformers = { + ...astTransformers, + afterDeclarations: transformers.afterDeclarations.map((transformerFilePath: string) => + require(transformerFilePath), + ), + } + } + + return astTransformers } /** @@ -476,9 +546,25 @@ export class ConfigSet { */ @Memoize() get tsCustomTransformers(): CustomTransformers { - return { - before: this.astTransformers.map((t) => t.factory(this)), + let customTransformers: CustomTransformers = { + before: this.astTransformers.before.map((t) => t.factory(this)) as TransformerFactory[], + } + if (this.astTransformers.after) { + customTransformers = { + ...customTransformers, + after: this.astTransformers.after.map((t) => t.factory(this)) as TransformerFactory[], + } } + if (this.astTransformers.afterDeclarations) { + customTransformers = { + ...customTransformers, + afterDeclarations: this.astTransformers.afterDeclarations.map((t) => t.factory(this)) as TransformerFactory< + Bundle | SourceFile + >[], + } + } + + return customTransformers } /** @@ -685,7 +771,9 @@ export class ConfigSet { versions: this.versions, projectDepVersions: this.projectDependencies, digest: this.tsJestDigest, - transformers: this.astTransformers.map((t) => `${t.name}@${t.version}`), + transformers: Object.values(this.astTransformers) + .reduce((acc, val) => acc.concat(val), []) + .map((t: AstTransformerDesc) => `${t.name}@${t.version}`), jest, tsJest: this.tsJest, babel: this.babel, diff --git a/src/index.ts b/src/index.ts index 9082940c3a..7139251e02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { pathsToModuleNameMapper as pathsToModuleNameMapperCore } from './config import { TsJestTransformer } from './ts-jest-transformer' import { TsJestGlobalOptions } from './types' import { rootLogger } from './util/logger' -import { Deprecateds, interpolate } from './util/messages' +import { Deprecations, interpolate } from './util/messages' import { mocked as mockedCore } from './util/testing' import { VersionCheckers } from './util/version-checkers' @@ -23,7 +23,7 @@ declare module '@jest/types' { // deprecate helpers const warn = rootLogger.child({ [LogContexts.logLevel]: LogLevels.warn }) const helperMoved = any>(name: string, helper: T) => - warn.wrap(interpolate(Deprecateds.HelperMovedToUtils, { helper: name }), helper) + warn.wrap(interpolate(Deprecations.HelperMovedToUtils, { helper: name }), helper) /** @deprecated */ export const mocked = helperMoved('mocked', mockedCore) diff --git a/src/types.ts b/src/types.ts index 1635e7c33e..d8184e5a58 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ import { TransformedSource, Transformer } from '@jest/transform' import * as _babel from 'babel__core' -import * as _ts from 'typescript' +import type * as _ts from 'typescript' import { ConfigSet } from './config/config-set' @@ -24,6 +24,12 @@ export type BabelJestTransformer = { */ export type BabelConfig = _babel.TransformOptions +export interface ConfigCustomTransformer { + before?: string[] + after?: string[] + afterDeclarations?: string[] +} + export interface TsJestGlobalOptions { /** * Compiler options. It can be: @@ -76,7 +82,7 @@ export interface TsJestGlobalOptions { /** * Custom transformers (mostly used by jest presets) */ - astTransformers?: string[] + astTransformers?: string[] | ConfigCustomTransformer /** * TS diagnostics - less to be reported if `isolatedModules` is `true`. It can be: @@ -179,7 +185,7 @@ export interface TsJestConfig { compiler: string diagnostics: TsJestConfig$diagnostics babelConfig: TsJestConfig$babelConfig - transformers: string[] + transformers: ConfigCustomTransformer // to deprecate / deprecated === === === stringifyContentPathRegex: TsJestConfig$stringifyContentPathRegex } @@ -190,11 +196,6 @@ export interface TsJestHooksMap { afterProcess?(args: any[], result: string | TransformedSource): string | TransformedSource | void } -/** - * @internal - */ -export type ModulePatcher = (module: T) => T - export interface TsCompiler { /** * @internal @@ -206,33 +207,12 @@ export interface TsCompiler { compile(code: string, fileName: string, lineOffset?: number): string program: _ts.Program | undefined } - /** * Internal source output. * * @internal */ export type SourceOutput = [string, string] - -/** where key is filepath */ -type TSFiles = Map -/** - * @internal - */ -export interface TSFile { - text?: string - output?: string - version: number -} -/** - * Track the project information. - * - * @internal - */ -export interface MemoryCache { - resolvedModules: Map - files: TSFiles -} /** * @internal */ @@ -250,5 +230,5 @@ export interface CompilerInstance { export interface AstTransformerDesc { name: string version: number - factory(cs: ConfigSet): _ts.TransformerFactory<_ts.SourceFile> + factory(cs: ConfigSet): _ts.TransformerFactory<_ts.SourceFile> | _ts.TransformerFactory<_ts.Bundle | _ts.SourceFile> } diff --git a/src/util/backports.ts b/src/util/backports.ts index d4ebb0de46..8c3a355f91 100644 --- a/src/util/backports.ts +++ b/src/util/backports.ts @@ -1,7 +1,7 @@ import { Config } from '@jest/types' import { LogContexts, Logger } from 'bs-logger' -import { Deprecateds, Helps, interpolate } from './messages' +import { Deprecations, Helps, interpolate } from './messages' const context = { [LogContexts.namespace]: 'backports' } @@ -22,7 +22,7 @@ export const backportJestConfig = { } logger.warn( context, - interpolate(Deprecateds.EnvVar, { + interpolate(Deprecations.EnvVar, { old: 'TS_JEST_DEBUG', new: 'TS_JEST_LOG', }), diff --git a/src/util/importer.ts b/src/util/importer.ts index f351f52335..866399f4a2 100644 --- a/src/util/importer.ts +++ b/src/util/importer.ts @@ -1,17 +1,18 @@ -import { ModulePatcher, TBabelCore, TBabelJest, TTypeScript } from '../types' +import { TBabelCore, TBabelJest, TTypeScript } from '../types' import { rootLogger } from './logger' import { Memoize } from './memoize' import { Errors, Helps, ImportReasons, interpolate } from './messages' import { VersionCheckers } from './version-checkers' +type ModulePatcher = (module: T) => T + const logger = rootLogger.child({ namespace: 'Importer' }) // When adding an optional dependency which has another reason, add the reason in ImportReasons, and // create a new method in Importer. Thus uses the importer.yourMethod(ImportReasons.TheReason) // in the relevant code, so that the user knows why it needs it and how to install it in the // case it can't import. - interface ImportOptions { alternatives?: string[] installTip?: string | { module: string; label: string }[] diff --git a/src/util/messages.ts b/src/util/messages.ts index b62fe8b8f8..8b60e98080 100644 --- a/src/util/messages.ts +++ b/src/util/messages.ts @@ -31,12 +31,13 @@ export const enum Helps { /** * @internal */ -export const enum Deprecateds { +export const enum Deprecations { EnvVar = 'Using env. var "{{old}}" is deprecated, use "{{new}}" instead.', ConfigOption = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.', ConfigOptionWithNote = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.\n ↳ {{note}}', ConfigOptionUseBabelRcNote = 'See `babel-jest` related issue: https://github.com/facebook/jest/issues/3845', HelperMovedToUtils = "The `{{helper}}` helper has been moved to `ts-jest/utils`. Use `import { {{helper}} } from 'ts-jest/utils'` instead.", + AstTransformerArrayConfig = 'The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers', } /**