-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add auto register feature module providers,imports
- Loading branch information
Showing
48 changed files
with
1,074 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { FeatureModuleDiscoverer } from '../../Util/FeatureModuleDiscoverer'; | ||
import type { AsyncTransformer, TransformedSource } from '@jest/transform'; | ||
import { hash } from 'node:crypto'; | ||
import { TsJestTransformer, type TsJestTransformerOptions, type TsJestTransformOptions } from 'ts-jest'; | ||
|
||
export type HcJestTransformerOptions = TsJestTransformerOptions & { rootDir: string; }; | ||
export const HC_TYPESCRIPT_TRANSFORMER_MODULE_PATH = '@hexancore/core/compiler/transformer'; | ||
|
||
export class HcJestTransformer implements AsyncTransformer<HcJestTransformerOptions> { | ||
private sourceRoot!: string; | ||
private tsJestTransformer: TsJestTransformer; | ||
|
||
private featureModuleDiscoveryHashMap: Map<string, string>; | ||
|
||
protected constructor(options: HcJestTransformerOptions) { | ||
this.processOptions(options); | ||
this.tsJestTransformer = new TsJestTransformer(options); | ||
this.featureModuleDiscoveryHashMap = new Map(); | ||
} | ||
|
||
private processOptions(options: HcJestTransformerOptions) { | ||
options.rootDir = options.rootDir.replaceAll("\\", "/"); | ||
this.sourceRoot = options.rootDir + "/src"; | ||
options.tsconfig = options.tsconfig ?? `${options.rootDir}/tsconfig.test.json`; | ||
options.astTransformers = options.astTransformers ?? ({}); | ||
options.astTransformers.before = options.astTransformers.before ?? []; | ||
|
||
if (!options.astTransformers.before.find((t) => typeof t !== 'string' && (t.path === HC_TYPESCRIPT_TRANSFORMER_MODULE_PATH || t.path === './lib/Compiler/transformer'))) { | ||
options.astTransformers.before.push({ | ||
path: HC_TYPESCRIPT_TRANSFORMER_MODULE_PATH, | ||
options: { | ||
sourceRoot: this.sourceRoot | ||
} | ||
}); | ||
} | ||
} | ||
|
||
public static async create(options: HcJestTransformerOptions): Promise<HcJestTransformer> { | ||
const transformer = new this(options); | ||
await transformer.loadFeatureMap(); | ||
return transformer; | ||
} | ||
|
||
private async loadFeatureMap(): Promise<void> { | ||
const discoverer = new FeatureModuleDiscoverer(this.sourceRoot); | ||
const features = await discoverer.discoverAll(); | ||
for (const [name, discovery] of features.entries()) { | ||
this.featureModuleDiscoveryHashMap.set(name, discovery.cacheKey); | ||
} | ||
} | ||
|
||
public get canInstrument(): boolean { | ||
return false; | ||
} | ||
|
||
public process(sourceText: string, sourcePath: string, options: TsJestTransformOptions): TransformedSource { | ||
return this.tsJestTransformer.process(sourceText, sourcePath, options); | ||
} | ||
|
||
public processAsync( | ||
sourceText: string, | ||
sourcePath: string, | ||
options: TsJestTransformOptions, | ||
): Promise<TransformedSource> { | ||
return this.tsJestTransformer.processAsync(sourceText, sourcePath, options as any) as any; | ||
} | ||
|
||
public getCacheKey(sourceText: string, sourcePath: string, transformOptions: TsJestTransformOptions): string { | ||
const extraCacheKey = this.getExtraCacheKey(sourcePath); | ||
const tsJestCacheKey = this.tsJestTransformer.getCacheKey(sourceText, sourcePath, transformOptions); | ||
if (extraCacheKey) { | ||
const combinedCacheKey = hash("sha1", tsJestCacheKey + extraCacheKey, "hex"); | ||
return combinedCacheKey; | ||
} | ||
|
||
return tsJestCacheKey; | ||
} | ||
|
||
public async getCacheKeyAsync(sourceText: string, sourcePath: string, transformOptions: TsJestTransformOptions): Promise<string> { | ||
return this.getCacheKey(sourceText, sourcePath, transformOptions); | ||
} | ||
|
||
private getExtraCacheKey(sourcePath: string,): string | null { | ||
sourcePath = sourcePath.replaceAll("\\", "/"); | ||
const extracted = FeatureModuleDiscoverer.extractFeatureNameFromPath(this.sourceRoot, sourcePath); | ||
if (extracted) { | ||
return this.featureModuleDiscoveryHashMap.get(extracted)!; | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { TsJestTransformerOptions } from "ts-jest"; | ||
import { HcJestTransformer, type HcJestTransformerOptions } from "./HcJestTransformer"; | ||
import type { AsyncTransformer } from '@jest/transform'; | ||
|
||
let cachedTransformer; | ||
|
||
export default { | ||
async createTransformer(options: HcJestTransformerOptions): Promise<AsyncTransformer<TsJestTransformerOptions>> { | ||
if (!cachedTransformer) { | ||
if (!options.rootDir) { | ||
throw new Error("Undefined rootDir in jest.config.ts `transform`"); | ||
} | ||
|
||
const t = await HcJestTransformer.create(options); | ||
cachedTransformer = { | ||
process: t.process.bind(t), | ||
processAsync: t.processAsync.bind(t), | ||
getCacheKey: t.getCacheKey.bind(t), | ||
getCacheKeyAsync: t.getCacheKeyAsync.bind(t) | ||
}; | ||
} | ||
|
||
return cachedTransformer; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { readFileSync } from "node:fs"; | ||
import path from "node:path"; | ||
import * as ts from "typescript"; | ||
export class TsTransformerTestHelper { | ||
public constructor(private compilerOptions: ts.CompilerOptions) { | ||
|
||
} | ||
|
||
public static createFromTsConfig(tsConfigFilePath: string): TsTransformerTestHelper { | ||
const tsConfig = this.loadTsConfig(tsConfigFilePath); | ||
return new this(tsConfig.options); | ||
} | ||
|
||
private static loadTsConfig(tsConfigFilePath: string): ts.ParsedCommandLine { | ||
const configFile = ts.readConfigFile(tsConfigFilePath, ts.sys.readFile); | ||
if (configFile.error) { | ||
throw new Error(`Error reading tsconfig.json: ${configFile.error.messageText}`); | ||
} | ||
const parsedConfig = ts.parseJsonConfigFileContent( | ||
configFile.config, | ||
ts.sys, | ||
path.dirname(tsConfigFilePath) | ||
); | ||
|
||
return parsedConfig; | ||
} | ||
|
||
public createSourceFileFromExisting(existingFilePath: string, filePath?: string): ts.SourceFile { | ||
const code = readFileSync(existingFilePath).toString(); | ||
return this.createSourceFile(filePath ?? existingFilePath, code); | ||
} | ||
|
||
public createSourceFile(filePath: string, code: string): ts.SourceFile { | ||
return ts.createSourceFile( | ||
filePath, | ||
code, | ||
this.compilerOptions.target ?? ts.ScriptTarget.Latest | ||
); | ||
} | ||
|
||
public createTransformerFactory(transformer: (sourceFile: ts.SourceFile) => ts.SourceFile): ts.TransformerFactory<ts.SourceFile> { | ||
return (context: ts.TransformationContext) => transformer; | ||
} | ||
|
||
public transformAndReturnAsString(sourceFile: ts.SourceFile, transformers: ts.TransformerFactory<ts.SourceFile>[]): string { | ||
const transformResult = ts.transform(sourceFile, transformers, this.compilerOptions); | ||
|
||
const transformedSourceFile = transformResult.transformed[0]; | ||
const printer = ts.createPrinter(); | ||
|
||
const result = printer.printNode( | ||
ts.EmitHint.SourceFile, | ||
transformedSourceFile, | ||
sourceFile | ||
); | ||
|
||
return result; | ||
} | ||
} |
Oops, something went wrong.