Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(config): expose several typings as public apis #2054

Merged
merged 1 commit into from Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/instance.ts
Expand Up @@ -15,7 +15,7 @@ export const SOURCE_MAPPING_PREFIX = 'sourceMappingURL='
/**
* Update the output remapping the source map.
*/
function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string): string {
export 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}`

Expand Down
142 changes: 74 additions & 68 deletions src/config/config-set.ts
Expand Up @@ -112,18 +112,36 @@ const toDiagnosticCodeList = (items: (string | number)[], into: number[] = []):

export class ConfigSet {
readonly logger: Logger
private readonly _cwd: string
private readonly _rootDir: string
readonly compilerModule: TTypeScript
readonly isolatedModules: boolean
readonly cwd: string
tsCacheDir: string | undefined
parsedTsConfig!: ParsedCommandLine
customTransformers: CustomTransformers = Object.create(null)
readonly rootDir: string
/**
* @internal
*/
private _jestCfg!: Config.ProjectConfig
private _isolatedModules!: boolean
private _parsedTsConfig!: ParsedCommandLine
private _customTransformers: CustomTransformers = Object.create(null)
/**
* @internal
*/
private _babelConfig: BabelConfig | undefined
/**
* @internal
*/
private _babelJestTransformers: BabelJestTransformer | undefined
/**
* @internal
*/
private _diagnostics!: TsJestDiagnosticsCfg
/**
* @internal
*/
private _stringifyContentRegExp: RegExp | undefined
private readonly _compilerModule!: TTypeScript
private _tsCacheDir: string | undefined
/**
* @internal
*/
private _overriddenCompilerOptions: Partial<CompilerOptions> = {
// we handle sourcemaps this way and not another
sourceMap: true,
Expand All @@ -146,27 +164,39 @@ export class ConfigSet {
}

constructor(
/**
* @internal
*/
private readonly jestConfig: Config.ProjectConfig,
// mainly for testing logging
/**
* Mainly for testing logging
*
* @internal
*/
private readonly parentLogger?: Logger,
) {
this.logger = this.parentLogger
? this.parentLogger.child({ [LogContexts.namespace]: 'config' })
: rootLogger.child({ namespace: 'config' })
this._cwd = normalize(this.jestConfig.cwd ?? process.cwd())
this._rootDir = normalize(this.jestConfig.rootDir ?? this._cwd)
this.cwd = normalize(this.jestConfig.cwd ?? process.cwd())
this.rootDir = normalize(this.jestConfig.rootDir ?? this.cwd)
const tsJestCfg = this.jestConfig.globals && this.jestConfig.globals['ts-jest']
const options: TsJestGlobalOptions = tsJestCfg ?? Object.create(null)
// compiler module
this._compilerModule = importer.typescript(ImportReasons.TsJest, options.compiler ?? 'typescript')
this.compilerModule = importer.typescript(ImportReasons.TsJest, options.compiler ?? 'typescript')
// isolatedModules
this.isolatedModules = options.isolatedModules ?? false

this.logger.debug({ compilerModule: this._compilerModule }, 'normalized compiler module config via ts-jest option')
this.logger.debug({ compilerModule: this.compilerModule }, 'normalized compiler module config via ts-jest option')

this._backportJestCfg()
this._setupTsJestCfg(options)
this._resolveTsCacheDir()
}

/**
* @internal
*/
private _backportJestCfg(): void {
const config = backportJestConfig(this.logger, this.jestConfig)

Expand All @@ -175,10 +205,10 @@ export class ConfigSet {
this._jestCfg = config
}

/**
* @internal
*/
private _setupTsJestCfg(options: TsJestGlobalOptions): void {
// isolatedModules
this._isolatedModules = options.isolatedModules ?? false

if (options.packageJson) {
this.logger.warn(Deprecations.PackageJson)
}
Expand All @@ -187,7 +217,7 @@ export class ConfigSet {
if (!options.babelConfig) {
this.logger.debug('babel is disabled')
} else {
const baseBabelCfg = { cwd: this._cwd }
const baseBabelCfg = { cwd: this.cwd }
if (typeof options.babelConfig === 'string') {
if (extname(options.babelConfig) === '.js') {
this._babelConfig = {
Expand Down Expand Up @@ -251,24 +281,24 @@ export class ConfigSet {
}
const tsconfigOpt = options.tsConfig ?? options.tsconfig
const configFilePath = typeof tsconfigOpt === 'string' ? this.resolvePath(tsconfigOpt) : undefined
this._parsedTsConfig = this._readTsConfig(typeof tsconfigOpt === 'object' ? tsconfigOpt : undefined, configFilePath)
this.parsedTsConfig = this._readTsConfig(typeof tsconfigOpt === 'object' ? tsconfigOpt : undefined, configFilePath)
// throw errors if any matching wanted diagnostics
this.raiseDiagnostics(this._parsedTsConfig.errors, configFilePath)
this.raiseDiagnostics(this.parsedTsConfig.errors, configFilePath)

this.logger.debug({ tsconfig: this._parsedTsConfig }, 'normalized typescript config via ts-jest option')
this.logger.debug({ tsconfig: this.parsedTsConfig }, 'normalized typescript config via ts-jest option')

// transformers
const { astTransformers } = options
this._customTransformers = {
this.customTransformers = {
before: [hoisting(this)],
}
if (astTransformers) {
if (Array.isArray(astTransformers)) {
this.logger.warn(Deprecations.AstTransformerArrayConfig)

this._customTransformers = {
this.customTransformers = {
before: [
...this._customTransformers.before,
...this.customTransformers.before,
...astTransformers.map((transformer) => {
const transformerPath = this.resolvePath(transformer, { nodeResolve: true })

Expand All @@ -291,27 +321,27 @@ export class ConfigSet {
}
})
if (astTransformers.before) {
this._customTransformers = {
before: [...this._customTransformers.before, ...resolveTransformers(astTransformers.before)],
this.customTransformers = {
before: [...this.customTransformers.before, ...resolveTransformers(astTransformers.before)],
}
}
if (astTransformers.after) {
this._customTransformers = {
...this._customTransformers,
this.customTransformers = {
...this.customTransformers,
after: resolveTransformers(astTransformers.after),
}
}
if (astTransformers.afterDeclarations) {
this._customTransformers = {
...this._customTransformers,
this.customTransformers = {
...this.customTransformers,
afterDeclarations: resolveTransformers(astTransformers.afterDeclarations),
}
}
}
}

this.logger.debug(
{ customTransformers: this._customTransformers },
{ customTransformers: this.customTransformers },
'normalized custom AST transformers via ts-jest option',
)

Expand All @@ -329,6 +359,9 @@ export class ConfigSet {
}
}

/**
* @internal
*/
private _resolveTsCacheDir(): void {
if (!this._jestCfg.cache) {
this.logger.debug('file caching disabled')
Expand All @@ -337,19 +370,19 @@ export class ConfigSet {
}
const cacheSuffix = sha1(
stringify({
version: this._compilerModule.version,
version: this.compilerModule.version,
digest: this.tsJestDigest,
compilerModule: this._compilerModule,
compilerOptions: this._parsedTsConfig.options,
isolatedModules: this._isolatedModules,
compilerModule: this.compilerModule,
compilerOptions: this.parsedTsConfig.options,
isolatedModules: this.isolatedModules,
diagnostics: this._diagnostics,
}),
)
const res = join(this._jestCfg.cacheDirectory, 'ts-jest', cacheSuffix.substr(0, 2), cacheSuffix.substr(2))

this.logger.debug({ cacheDirectory: res }, 'will use file caching')

this._tsCacheDir = res
this.tsCacheDir = res
}

/**
Expand All @@ -360,12 +393,12 @@ export class ConfigSet {
*/
private _readTsConfig(compilerOptions?: CompilerOptions, resolvedConfigFile?: string): ParsedCommandLine {
let config = { compilerOptions: Object.create(null) }
let basePath = normalizeSlashes(this._rootDir)
const ts = this._compilerModule
let basePath = normalizeSlashes(this.rootDir)
const ts = this.compilerModule
// Read project configuration when available.
const configFileName: string | undefined = resolvedConfigFile
? normalizeSlashes(resolvedConfigFile)
: ts.findConfigFile(normalizeSlashes(this._rootDir), ts.sys.fileExists)
: ts.findConfigFile(normalizeSlashes(this.rootDir), ts.sys.fileExists)
if (configFileName) {
this.logger.debug({ tsConfigFileName: configFileName }, 'readTsConfig(): reading', configFileName)
const result = ts.readConfigFile(configFileName, ts.sys.readFile)
Expand Down Expand Up @@ -456,25 +489,9 @@ export class ConfigSet {
return result
}

get parsedTsConfig(): ParsedCommandLine {
return this._parsedTsConfig
}

get isolatedModules(): boolean {
return this._isolatedModules
}

/**
* This API can be used by custom transformers
* @internal
*/
get compilerModule(): TTypeScript {
return this._compilerModule
}

get customTransformers(): CustomTransformers {
return this._customTransformers
}

@Memoize()
get tsCompiler(): TsCompiler {
return createCompilerInstance(this)
Expand All @@ -494,14 +511,6 @@ export class ConfigSet {
return this._babelJestTransformers
}

get cwd(): string {
return this._cwd
}

get tsCacheDir(): string | undefined {
return this._tsCacheDir
}

/**
* Use by e2e, don't mark as internal
*/
Expand All @@ -518,7 +527,7 @@ export class ConfigSet {
get hooks(): TsJestHooksMap {
let hooksFile = process.env.TS_JEST_HOOKS
if (hooksFile) {
hooksFile = resolve(this._cwd, hooksFile)
hooksFile = resolve(this.cwd, hooksFile)

return importer.tryTheseOr(hooksFile, {})
}
Expand Down Expand Up @@ -546,16 +555,13 @@ export class ConfigSet {
matchablePatterns.some((pattern) => (typeof pattern === 'string' ? isMatch(fileName) : pattern.test(fileName)))
}

/**
* @internal
*/
shouldStringifyContent(filePath: string): boolean {
return this._stringifyContentRegExp ? this._stringifyContentRegExp.test(filePath) : false
}

raiseDiagnostics(diagnostics: Diagnostic[], filePath?: string, logger?: Logger): void {
const { ignoreCodes } = this._diagnostics
const { DiagnosticCategory } = this._compilerModule
const { DiagnosticCategory } = this.compilerModule
const filteredDiagnostics =
filePath && !this.shouldReportDiagnostics(filePath)
? []
Expand Down Expand Up @@ -614,7 +620,7 @@ export class ConfigSet {
let path: string = inputPath
let nodeResolved = false
if (path.startsWith('<rootDir>')) {
path = resolve(join(this._rootDir, path.substr(9)))
path = resolve(join(this.rootDir, path.substr(9)))
} else if (!isAbsolute(path)) {
if (!path.startsWith('.') && nodeResolve) {
try {
Expand Down
8 changes: 8 additions & 0 deletions src/ts-jest-transformer.ts
Expand Up @@ -19,10 +19,18 @@ interface CachedConfigSet {
export class TsJestTransformer implements Transformer {
/**
* cache ConfigSet between test runs
*
* @internal
*/
private static readonly _cachedConfigSets: CachedConfigSet[] = []
protected readonly logger: Logger
/**
* @internal
*/
private _transformCfgStr!: string
/**
* @internal
*/
private _tsJestCfgSet!: ConfigSet

constructor() {
Expand Down
6 changes: 0 additions & 6 deletions src/utils/json.ts
Expand Up @@ -3,16 +3,10 @@ import stableStringify = require('fast-json-stable-stringify')

const UNDEFINED = 'undefined'

/**
* @internal
*/
export function stringify(input: unknown): string {
return input === undefined ? UNDEFINED : stableStringify(input)
}

/**
* @internal
*/
export function parse(input: string): any {
return input === UNDEFINED ? undefined : JSON.parse(input)
}
Expand Down
3 changes: 0 additions & 3 deletions src/utils/jsonable-value.ts
@@ -1,8 +1,5 @@
import { stringify } from './json'

/**
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class JsonableValue<V = Record<string, any>> {
private _serialized!: string
Expand Down