-
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.
Loading status checks…
feat: add AOT domain discovery
Showing
69 changed files
with
1,194 additions
and
673 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
17 changes: 17 additions & 0 deletions
17
src/Compiler/Transformer/Feature/AbstractFeatureTsTransformer.ts
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,17 @@ | ||
import ts from 'typescript'; | ||
import type { FeatureModuleMeta } from "../../../Util/Feature/FeatureModuleMeta"; | ||
import { ModuleClassTsTransformer } from '../ModuleClassTsTransformer'; | ||
import { type ImportFromMapper } from '../TsTransformerHelper'; | ||
|
||
export abstract class AbstractFeatureTsTransformer { | ||
protected moduleClassTransformer: ModuleClassTsTransformer; | ||
|
||
public constructor(protected importFromMapper: ImportFromMapper, needFixImportAccess = true) { | ||
this.moduleClassTransformer = new ModuleClassTsTransformer(importFromMapper, needFixImportAccess); | ||
} | ||
|
||
public abstract transform(feature: FeatureModuleMeta, source: ts.SourceFile, context: ts.TransformationContext): ts.SourceFile; | ||
|
||
public abstract supports(sourceFilePath: string, feature: FeatureModuleMeta): boolean; | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
src/Compiler/Transformer/Feature/FeatureInfraDomainTsTransformer.ts
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,69 @@ | ||
import ts from 'typescript'; | ||
import type { FeatureModuleMeta } from "../../../Util/Feature/FeatureModuleMeta"; | ||
import { AbstractFeatureTsTransformer } from './AbstractFeatureTsTransformer'; | ||
import { TsTransfromerHelper } from '../TsTransformerHelper'; | ||
import type { AddImportTransformDef } from '../ModuleClassTsTransformer'; | ||
|
||
export class FeatureInfraDomainModuleTsTransformer extends AbstractFeatureTsTransformer { | ||
|
||
public transform(feature: FeatureModuleMeta, source: ts.SourceFile, context: ts.TransformationContext): ts.SourceFile { | ||
const domainErrorsClassName = feature.name + "DomainErrors"; | ||
|
||
const imports: AddImportTransformDef[] = [ | ||
{ name: "DomainInfraModuleHelper", importModuleSpecifier: '@hexancore/core' }, | ||
{ name: domainErrorsClassName, importModuleSpecifier: '../../Domain'} | ||
]; | ||
|
||
const repos: string[] = []; | ||
|
||
for (const r of feature.domain.aggregateRoots) { | ||
repos.push(r.infraRepositoryName); | ||
imports.push( | ||
{ name: r.name, importModuleSpecifier: `../../Domain/${r.name}/${r.name}` }, | ||
{ name: r.infraRepositoryName, importModuleSpecifier: `./${r.name}/${r.infraRepositoryName}` } | ||
); | ||
|
||
for (const e of r.entities) { | ||
repos.push(e.infraRepositoryName); | ||
imports.push({ name: e.infraRepositoryName, importModuleSpecifier: `./${r.name}/${e.infraRepositoryName}` }); | ||
} | ||
} | ||
|
||
return this.moduleClassTransformer.transform({ | ||
imports, | ||
extraStatementProvider(importedIdentifierMapper) { | ||
const classIdentifier = importedIdentifierMapper("DomainInfraModuleHelper"); | ||
const methodIdentifier = ts.factory.createIdentifier("createMeta"); | ||
|
||
const optionsObject = ts.factory.createObjectLiteralExpression([ | ||
ts.factory.createPropertyAssignment("featureName", ts.factory.createStringLiteral(feature.name)), | ||
ts.factory.createPropertyAssignment("aggregateRootCtrs", ts.factory.createArrayLiteralExpression(feature.domain.aggregateRoots.map((r) => ts.factory.createIdentifier(r.name)))), | ||
ts.factory.createPropertyAssignment("domainErrors", ts.factory.createIdentifier(domainErrorsClassName)), | ||
]); | ||
|
||
const createMeta = TsTransfromerHelper.createConstStatement("HcDomainInfraModuleMetaExtra", ts.factory.createCallExpression( | ||
ts.factory.createPropertyAccessExpression(classIdentifier, methodIdentifier), | ||
undefined, | ||
[optionsObject] | ||
)); | ||
|
||
return [ | ||
TsTransfromerHelper.createConstStatement("HcDomainInfraAggrgateRootRepositories", | ||
ts.factory.createArrayLiteralExpression(repos.map((r) => ts.factory.createIdentifier(r))) | ||
), | ||
createMeta | ||
]; | ||
}, | ||
|
||
extraMetaProvider() { | ||
return ts.factory.createIdentifier("HcDomainInfraModuleMetaExtra"); | ||
}, | ||
source, | ||
context | ||
}); | ||
} | ||
|
||
public supports(sourcefilePath: string, feature: FeatureModuleMeta): boolean { | ||
return sourcefilePath.endsWith("DomainInfraModule.ts"); | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
src/Compiler/Transformer/Feature/FeatureModuleTsTransformer.ts
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,64 @@ | ||
import ts from 'typescript'; | ||
import type { FeatureApplicationMessageMeta, FeatureModuleMeta } from "../../../Util/Feature/FeatureModuleMeta"; | ||
import { AbstractFeatureTsTransformer } from "./AbstractFeatureTsTransformer"; | ||
import type { ProviderModuleMetaTransformDef } from '../ModuleClassTsTransformer'; | ||
|
||
/** | ||
* Adding automatic injection of message handlers, services, infra module to `[Feature]Module` source. | ||
* Less write, more fun ! | ||
*/ | ||
export class FeatureModuleTsTransformer extends AbstractFeatureTsTransformer { | ||
|
||
public supports(sourcefilePath: string, feature: FeatureModuleMeta): boolean { | ||
return sourcefilePath.endsWith(feature.name + "Module.ts"); | ||
} | ||
|
||
public transform(feature: FeatureModuleMeta, source: ts.SourceFile, context: ts.TransformationContext): ts.SourceFile { | ||
|
||
const messageHandlersProviders: ProviderModuleMetaTransformDef[] = []; | ||
messageHandlersProviders.push(...this.createMessageHandlerProviders(feature.application.commands)); | ||
messageHandlersProviders.push(...this.createMessageHandlerProviders(feature.application.queries)); | ||
messageHandlersProviders.push(...this.createMessageHandlerProviders(feature.application.events)); | ||
|
||
return this.moduleClassTransformer.transform({ | ||
imports: [], | ||
meta: { | ||
imports: [], | ||
providers: [...messageHandlersProviders, ...this.createServiceProviders(feature)], | ||
}, | ||
source, | ||
context | ||
}); | ||
} | ||
|
||
private createMessageHandlerProviders(messages: FeatureApplicationMessageMeta[]): ProviderModuleMetaTransformDef[] { | ||
const providers: ProviderModuleMetaTransformDef[] = []; | ||
for (const m of messages) { | ||
const importPath = `./${m.path}/${m.handlerClassName}`; | ||
providers.push({ | ||
addToExports: false, | ||
name: m.handlerClassName, | ||
importFrom: importPath | ||
}); | ||
} | ||
|
||
return providers; | ||
} | ||
|
||
private createServiceProviders(feature: FeatureModuleMeta): ProviderModuleMetaTransformDef[] { | ||
const providers: ProviderModuleMetaTransformDef[] = []; | ||
for (const s of feature.application.services) { | ||
if (!s.isInjectable) { | ||
continue; | ||
} | ||
|
||
providers.push({ | ||
addToExports: false, | ||
name: s.className, | ||
importFrom: `./${s.path}` | ||
}); | ||
} | ||
|
||
return providers; | ||
} | ||
} |
Oops, something went wrong.