Skip to content

Commit

Permalink
feat: allow ast transformers to take in addl opts, fix #1942
Browse files Browse the repository at this point in the history
  • Loading branch information
longlho authored and ahnpnl committed Sep 18, 2020
1 parent 05d9b8b commit 798beaa
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 40 deletions.
36 changes: 22 additions & 14 deletions docs/user/config/astTransformers.md
Expand Up @@ -7,8 +7,8 @@ TypeScript AST transformers and provide them to `ts-jest` to include into compil

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` ).
- `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.

Expand All @@ -23,11 +23,17 @@ module.exports = {
globals: {
'ts-jest': {
astTransformers: {
before: ['my-custom-transformer'],
before: [
'my-custom-transformer',
{
path: 'my-custom-transformer-that-needs-extra-opts',
options: {},
},
],
},
}
}
};
},
},
}
```

</div><div class="col-md-6" markdown="block">
Expand All @@ -40,7 +46,10 @@ module.exports = {
"globals": {
"ts-jest": {
astTransformers: {
"before": ["my-custom-transformer"]
"before": ["my-custom-transformer", {
path: 'my-custom-transformer-that-needs-extra-opts',
options: {}
}]
}
}
}
Expand All @@ -55,9 +64,9 @@ module.exports = {
`ts-jest` is able to expose transformers for public usage to provide the possibility to opt-in/out for users. Currently
the exposed transformers are:

- `path-mapping` convert alias import/export to relative import/export path base on `paths` in `tsconfig`.
This transformer works similar to `moduleNameMapper` in `jest.config.js`. When using this transformer, one might not need
`moduleNameMapper` anymore.
- `path-mapping` convert alias import/export to relative import/export path base on `paths` in `tsconfig`.
This transformer works similar to `moduleNameMapper` in `jest.config.js`. When using this transformer, one might not need
`moduleNameMapper` anymore.

#### Example of opt-in transformers

Expand All @@ -72,9 +81,9 @@ module.exports = {
astTransformers: {
before: ['ts-jest/dist/transformers/path-mapping'],
},
}
}
};
},
},
}
```

</div><div class="col-md-6" markdown="block">
Expand All @@ -97,7 +106,6 @@ module.exports = {

</div></div>


### Writing custom TypeScript AST 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.
2 changes: 1 addition & 1 deletion e2e/__tests__/path-mapping.test.ts
Expand Up @@ -13,7 +13,7 @@ function executeTest(rootDirs?: string[]) {
},
astTransformers: {
before: [
'ts-jest/dist/transformers/path-mapping'
{path: 'ts-jest/dist/transformers/path-mapping'}
],
},
},
Expand Down
101 changes: 81 additions & 20 deletions src/config/config-set.ts
Expand Up @@ -56,10 +56,15 @@ import { TSError } from '../utils/ts-error'

const logger = rootLogger.child({ namespace: 'config' })

interface AstTransformerObj<T = Record<string, unknown>> {
module: AstTransformerDesc
options?: T
}

interface AstTransformer {
before: AstTransformerDesc[]
after?: AstTransformerDesc[]
afterDeclarations?: AstTransformerDesc[]
before: AstTransformerObj[]
after?: AstTransformerObj[]
afterDeclarations?: AstTransformerObj[]
}
/**
* @internal
Expand Down Expand Up @@ -184,29 +189,52 @@ export class ConfigSet {
this.logger.warn(Deprecations.AstTransformerArrayConfig)

transformers = {
before: astTransformers.map((transformerPath) => this.resolvePath(transformerPath, { nodeResolve: true })),
before: astTransformers.map((transformerPath) => ({
path: this.resolvePath(transformerPath, { nodeResolve: true }),
})),
}
} else {
if (astTransformers.before) {
transformers = {
before: astTransformers.before.map((transformerPath: string) =>
this.resolvePath(transformerPath, { nodeResolve: true }),
before: astTransformers.before.map((transformer) =>
typeof transformer === 'string'
? {
path: this.resolvePath(transformer, { nodeResolve: true }),
}
: {
...transformer,
path: this.resolvePath(transformer.path, { nodeResolve: true }),
},
),
}
}
if (astTransformers.after) {
transformers = {
...transformers,
after: astTransformers.after.map((transformerPath: string) =>
this.resolvePath(transformerPath, { nodeResolve: true }),
after: astTransformers.after.map((transformer) =>
typeof transformer === 'string'
? {
path: this.resolvePath(transformer, { nodeResolve: true }),
}
: {
...transformer,
path: this.resolvePath(transformer.path, { nodeResolve: true }),
},
),
}
}
if (astTransformers.afterDeclarations) {
transformers = {
...transformers,
afterDeclarations: astTransformers.afterDeclarations.map((transformerPath: string) =>
this.resolvePath(transformerPath, { nodeResolve: true }),
afterDeclarations: astTransformers.afterDeclarations.map((transformer) =>
typeof transformer === 'string'
? {
path: this.resolvePath(transformer, { nodeResolve: true }),
}
: {
...transformer,
path: this.resolvePath(transformer.path, { nodeResolve: true }),
},
),
}
}
Expand Down Expand Up @@ -402,28 +430,57 @@ export class ConfigSet {
@Memoize()
private get astTransformers(): AstTransformer {
let astTransformers: AstTransformer = {
before: [...internalAstTransformers],
before: [
...internalAstTransformers.map((transformer) => ({
module: transformer,
})),
],
}
const { transformers } = this.tsJest
if (transformers.before) {
astTransformers = {
before: [
...astTransformers.before,
...transformers.before.map((transformerFilePath: string) => require(transformerFilePath)),
...transformers.before.map((transformer) =>
typeof transformer === 'string'
? {
module: require(transformer),
}
: {
module: require(transformer.path),
options: transformer.options,
},
),
],
}
}
if (transformers.after) {
astTransformers = {
...astTransformers,
after: transformers.after.map((transformerFilePath: string) => require(transformerFilePath)),
after: transformers.after.map((transformer) =>
typeof transformer === 'string'
? {
module: require(transformer),
}
: {
module: require(transformer.path),
options: transformer.options,
},
),
}
}
if (transformers.afterDeclarations) {
astTransformers = {
...astTransformers,
afterDeclarations: transformers.afterDeclarations.map((transformerFilePath: string) =>
require(transformerFilePath),
afterDeclarations: transformers.afterDeclarations.map((transformer) =>
typeof transformer === 'string'
? {
module: require(transformer),
}
: {
module: require(transformer.path),
options: transformer.options,
},
),
}
}
Expand All @@ -437,20 +494,24 @@ export class ConfigSet {
@Memoize()
get tsCustomTransformers(): CustomTransformers {
let customTransformers: CustomTransformers = {
before: this.astTransformers.before.map((t) => t.factory(this)) as TransformerFactory<SourceFile>[],
before: this.astTransformers.before.map((t) => t.module.factory(this, t.options)) as TransformerFactory<
SourceFile
>[],
}
if (this.astTransformers.after) {
customTransformers = {
...customTransformers,
after: this.astTransformers.after.map((t) => t.factory(this)) as TransformerFactory<SourceFile>[],
after: this.astTransformers.after.map((t) => t.module.factory(this, t.options)) as TransformerFactory<
SourceFile
>[],
}
}
if (this.astTransformers.afterDeclarations) {
customTransformers = {
...customTransformers,
afterDeclarations: this.astTransformers.afterDeclarations.map((t) => t.factory(this)) as TransformerFactory<
Bundle | SourceFile
>[],
afterDeclarations: this.astTransformers.afterDeclarations.map((t) =>
t.module.factory(this, t.options),
) as TransformerFactory<Bundle | SourceFile>[],
}
}

Expand Down
18 changes: 13 additions & 5 deletions src/types.ts
Expand Up @@ -24,10 +24,15 @@ export type BabelJestTransformer = {
*/
export type BabelConfig = _babel.TransformOptions

export interface AstTransformer<T = Record<string, unknown>> {
path: string
options?: T
}

export interface ConfigCustomTransformer {
before?: string[]
after?: string[]
afterDeclarations?: string[]
before?: (string | AstTransformer)[]
after?: (string | AstTransformer)[]
afterDeclarations?: (string | AstTransformer)[]
}

export interface TsJestGlobalOptions {
Expand Down Expand Up @@ -229,8 +234,11 @@ export interface CompilerInstance {
/**
* @internal
*/
export interface AstTransformerDesc {
export interface AstTransformerDesc<T = Record<string, unknown>> {
name: string
version: number
factory(cs: ConfigSet): _ts.TransformerFactory<_ts.SourceFile> | _ts.TransformerFactory<_ts.Bundle | _ts.SourceFile>
factory(
cs: ConfigSet,
opts?: T,
): _ts.TransformerFactory<_ts.SourceFile> | _ts.TransformerFactory<_ts.Bundle | _ts.SourceFile>
}

0 comments on commit 798beaa

Please sign in to comment.