From ad2a5ee984939ea5836fef5ed494eda061ccd164 Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Mon, 16 May 2022 18:29:44 +0800 Subject: [PATCH 1/8] feat(core): add inversify and moke container for core packages --- package.json | 2 + packages/core/src/containers/container.ts | 21 +++++++ packages/core/src/containers/index.ts | 3 + .../src/containers/modules/artifactBuilder.ts | 52 ++++++++++++++++ .../core/src/containers/modules/executor.ts | 13 ++++ packages/core/src/containers/modules/index.ts | 3 + .../src/containers/modules/templateEngine.ts | 62 +++++++++++++++++++ packages/core/src/containers/types.ts | 21 +++++++ .../localFilePersistentStore.ts | 10 ++- .../serializers/jsonSerializer.ts | 2 + .../artifact-builder/vulcanArtifactBuilder.ts | 24 ++++--- .../extensions/filters/unique.ts | 2 + .../template-engine/extensions/tags/error.ts | 2 + .../template-engine/extensions/tags/req.ts | 5 +- .../lib/template-engine/inMemoryCodeLoader.ts | 2 + .../lib/template-engine/nunjucksCompiler.ts | 15 ++--- .../fileTemplateProvider.ts | 20 +++--- .../src/lib/template-engine/templateEngine.ts | 51 ++++----------- .../core/src/models/artifactBuilderOptions.ts | 13 ++++ packages/core/src/models/globalOptions.ts | 7 +++ packages/core/src/models/index.ts | 3 + .../core/src/models/templateEngineOptions.ts | 8 +++ packages/core/src/options/artifactBuilder.ts | 21 +++++++ packages/core/src/options/index.ts | 2 + packages/core/src/options/templateEngine.ts | 16 +++++ .../core/test/containers/continer.spec.ts | 37 +++++++++++ packages/core/test/containers/result.json | 1 + .../test/containers/test-template/group.sql | 1 + packages/core/tsconfig.json | 4 +- tsconfig.base.json | 1 + yarn.lock | 10 +++ 31 files changed, 363 insertions(+), 71 deletions(-) create mode 100644 packages/core/src/containers/container.ts create mode 100644 packages/core/src/containers/index.ts create mode 100644 packages/core/src/containers/modules/artifactBuilder.ts create mode 100644 packages/core/src/containers/modules/executor.ts create mode 100644 packages/core/src/containers/modules/index.ts create mode 100644 packages/core/src/containers/modules/templateEngine.ts create mode 100644 packages/core/src/containers/types.ts create mode 100644 packages/core/src/models/artifactBuilderOptions.ts create mode 100644 packages/core/src/models/globalOptions.ts create mode 100644 packages/core/src/models/templateEngineOptions.ts create mode 100644 packages/core/src/options/artifactBuilder.ts create mode 100644 packages/core/src/options/index.ts create mode 100644 packages/core/src/options/templateEngine.ts create mode 100644 packages/core/test/containers/continer.spec.ts create mode 100644 packages/core/test/containers/result.json create mode 100644 packages/core/test/containers/test-template/group.sql diff --git a/package.json b/package.json index 508dc5e8..cff69b4a 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,12 @@ "private": true, "dependencies": { "glob": "^8.0.1", + "inversify": "^6.0.1", "js-yaml": "^4.1.0", "koa-compose": "^4.1.0", "lodash": "^4.17.21", "nunjucks": "^3.2.3", + "reflect-metadata": "^0.1.13", "tslib": "^2.3.0" }, "devDependencies": { diff --git a/packages/core/src/containers/container.ts b/packages/core/src/containers/container.ts new file mode 100644 index 00000000..78fb2ffa --- /dev/null +++ b/packages/core/src/containers/container.ts @@ -0,0 +1,21 @@ +import { IGlobalOptions } from '@models'; +import { Container as InversifyContainer } from 'inversify'; +import { + artifactBuilderModule, + executorModule, + templateEngineModule, +} from './modules'; + +export class Container { + private inversifyContainer = new InversifyContainer(); + + public get(type: symbol) { + return this.inversifyContainer.get(type); + } + + public load(options: IGlobalOptions) { + this.inversifyContainer.load(artifactBuilderModule(options.artifact)); + this.inversifyContainer.load(executorModule()); + this.inversifyContainer.load(templateEngineModule(options.template)); + } +} diff --git a/packages/core/src/containers/index.ts b/packages/core/src/containers/index.ts new file mode 100644 index 00000000..2f90771a --- /dev/null +++ b/packages/core/src/containers/index.ts @@ -0,0 +1,3 @@ +import 'reflect-metadata'; +export * from './types'; +export * from './container'; diff --git a/packages/core/src/containers/modules/artifactBuilder.ts b/packages/core/src/containers/modules/artifactBuilder.ts new file mode 100644 index 00000000..7e86b66b --- /dev/null +++ b/packages/core/src/containers/modules/artifactBuilder.ts @@ -0,0 +1,52 @@ +import { ContainerModule, interfaces } from 'inversify'; +import { + PersistentStore, + LocalFilePersistentStore, + Serializer, + JSONSerializer, + ArtifactBuilder, + VulcanArtifactBuilder, +} from '@artifact-builder'; +import { TYPES } from '../types'; +import { + SerializerType, + PersistentStoreType, + IArtifactBuilderOptions, +} from '@models'; +import { ArtifactBuilderOptions } from '../../options'; + +export const artifactBuilderModule = (options: IArtifactBuilderOptions) => + new ContainerModule((bind) => { + // Options + bind( + TYPES.ArtifactBuilderInputOptions + ).toConstantValue(options); + bind(TYPES.ArtifactBuilderOptions) + .to(ArtifactBuilderOptions) + .inSingletonScope(); + + // PersistentStore + bind(TYPES.PersistentStore) + .to(LocalFilePersistentStore) + .inSingletonScope() + .whenTargetNamed(PersistentStoreType.LocalFile); + + bind>( + TYPES.Factory_PersistentStore + ).toAutoNamedFactory(TYPES.PersistentStore); + + // Serializer + bind>(TYPES.Serializer) + .to(JSONSerializer) + .inSingletonScope() + .whenTargetNamed(SerializerType.JSON); + + bind>>( + TYPES.Factory_Serializer + ).toAutoNamedFactory>(TYPES.Serializer); + + // ArtifactBuilder + bind(TYPES.ArtifactBuilder) + .to(VulcanArtifactBuilder) + .inSingletonScope(); + }); diff --git a/packages/core/src/containers/modules/executor.ts b/packages/core/src/containers/modules/executor.ts new file mode 100644 index 00000000..30b1c9ac --- /dev/null +++ b/packages/core/src/containers/modules/executor.ts @@ -0,0 +1,13 @@ +import { ContainerModule } from 'inversify'; +import { Executor } from '@template-engine'; +import { TYPES } from '../types'; + +export const executorModule = () => + new ContainerModule((bind) => { + bind(TYPES.Executor).toConstantValue({ + // TODO: Mock value + executeQuery: async () => { + return []; + }, + }); + }); diff --git a/packages/core/src/containers/modules/index.ts b/packages/core/src/containers/modules/index.ts new file mode 100644 index 00000000..5c33aeae --- /dev/null +++ b/packages/core/src/containers/modules/index.ts @@ -0,0 +1,3 @@ +export * from './artifactBuilder'; +export * from './executor'; +export * from './templateEngine'; diff --git a/packages/core/src/containers/modules/templateEngine.ts b/packages/core/src/containers/modules/templateEngine.ts new file mode 100644 index 00000000..7d9ea788 --- /dev/null +++ b/packages/core/src/containers/modules/templateEngine.ts @@ -0,0 +1,62 @@ +import { TYPES } from '@containers'; +import { ITemplateEngineOptions, TemplateProviderType } from '@models'; +import { + ErrorExtension, + FileTemplateProvider, + NunjucksCompilerExtension, + ReqExtension, + TemplateProvider, + UniqueExtension, + InMemoryCodeLoader, + NunjucksCompiler, + Compiler, + TemplateEngine, +} from '@template-engine'; +import { ContainerModule, interfaces } from 'inversify'; +import { TemplateEngineOptions } from '../../options'; +import * as nunjucks from 'nunjucks'; + +export const templateEngineModule = (options: ITemplateEngineOptions) => + new ContainerModule((bind) => { + // Options + bind( + TYPES.TemplateEngineInputOptions + ).toConstantValue(options); + bind(TYPES.TemplateEngineOptions) + .to(TemplateEngineOptions) + .inSingletonScope(); + + // TemplateProvider + bind(TYPES.TemplateProvider) + .to(FileTemplateProvider) + .inSingletonScope() + .whenTargetNamed(TemplateProviderType.LocalFile); + + bind>( + TYPES.Factory_TemplateProvider + ).toAutoNamedFactory(TYPES.TemplateProvider); + + // Extensions + bind(TYPES.CompilerExtension) + .to(UniqueExtension) + .inSingletonScope(); + bind(TYPES.CompilerExtension) + .to(ErrorExtension) + .inSingletonScope(); + bind(TYPES.CompilerExtension) + .to(ReqExtension) + .inSingletonScope(); + + // Loader + bind(TYPES.CompilerLoader) + .to(InMemoryCodeLoader) + .inSingletonScope(); + + // Compiler + bind(TYPES.Compiler).to(NunjucksCompiler).inSingletonScope(); + + // Template Engine + bind(TYPES.TemplateEngine) + .to(TemplateEngine) + .inSingletonScope(); + }); diff --git a/packages/core/src/containers/types.ts b/packages/core/src/containers/types.ts new file mode 100644 index 00000000..777aa377 --- /dev/null +++ b/packages/core/src/containers/types.ts @@ -0,0 +1,21 @@ +export const TYPES = { + // Artifact builder + PersistentStore: Symbol.for('PersistentStore'), + Factory_PersistentStore: Symbol.for('Factory_PersistentStore'), + Serializer: Symbol.for('Serializer'), + Factory_Serializer: Symbol.for('Factory_Serializer'), + ArtifactBuilderOptions: Symbol.for('ArtifactBuilderOptions'), + ArtifactBuilderInputOptions: Symbol.for('ArtifactBuilderInputOptions'), + ArtifactBuilder: Symbol.for('ArtifactBuilder'), + // Template engine + TemplateProvider: Symbol.for('TemplateProvider'), + Factory_TemplateProvider: Symbol.for('Factory_TemplateProvider'), + CompilerExtension: Symbol.for('CompilerExtension'), + CompilerLoader: Symbol.for('CompilerLoader'), + Compiler: Symbol.for('Compiler'), + TemplateEngine: Symbol.for('TemplateEngine'), + TemplateEngineOptions: Symbol.for('TemplateEngineOptions'), + TemplateEngineInputOptions: Symbol.for('TemplateEngineInputOptions'), + // Executor + Executor: Symbol.for('Executor'), +}; diff --git a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts index ace397c9..5c669538 100644 --- a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts +++ b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts @@ -1,11 +1,17 @@ import { PersistentStore } from './persistentStore'; import { promises as fs } from 'fs'; +import { injectable, inject } from 'inversify'; +import { TYPES } from '@containers'; +import { IArtifactBuilderOptions } from '@models'; +@injectable() export class LocalFilePersistentStore implements PersistentStore { private filePath: string; - constructor({ filePath }: { filePath: string }) { - this.filePath = filePath; + constructor( + @inject(TYPES.ArtifactBuilderOptions) options: IArtifactBuilderOptions + ) { + this.filePath = options.path; } public async save(data: Buffer): Promise { diff --git a/packages/core/src/lib/artifact-builder/serializers/jsonSerializer.ts b/packages/core/src/lib/artifact-builder/serializers/jsonSerializer.ts index cdf0a90a..17b86116 100644 --- a/packages/core/src/lib/artifact-builder/serializers/jsonSerializer.ts +++ b/packages/core/src/lib/artifact-builder/serializers/jsonSerializer.ts @@ -1,5 +1,7 @@ import { Serializer } from './serializer'; +import { injectable } from 'inversify'; +@injectable() export class JSONSerializer implements Serializer { public serialize(data: T): Buffer { return Buffer.from(JSON.stringify(data), 'utf-8'); diff --git a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts index bd84ff89..6a66c876 100644 --- a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts +++ b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts @@ -1,20 +1,24 @@ import { Artifact, ArtifactBuilder } from './artifactBuilder'; import { PersistentStore } from './persistent-stores'; -import { JSONSerializer, Serializer } from './serializers'; +import { Serializer } from './serializers'; +import { inject, injectable, interfaces } from 'inversify'; +import { TYPES } from '@containers'; +import { IArtifactBuilderOptions } from '../../models/artifactBuilderOptions'; +@injectable() export class VulcanArtifactBuilder implements ArtifactBuilder { private serializer: Serializer; private persistentStore: PersistentStore; - constructor({ - serializer, - persistentStore, - }: { - serializer?: Serializer; - persistentStore: PersistentStore; - }) { - this.serializer = serializer || new JSONSerializer(); - this.persistentStore = persistentStore; + constructor( + @inject(TYPES.Factory_PersistentStore) + persistentStoreFactory: interfaces.AutoNamedFactory, + @inject(TYPES.Factory_Serializer) + serializerFactory: interfaces.AutoNamedFactory>, + @inject(TYPES.ArtifactBuilderOptions) options: IArtifactBuilderOptions + ) { + this.serializer = serializerFactory(options.serializerType); + this.persistentStore = persistentStoreFactory(options.storageType); } public async build(artifact: Artifact): Promise { diff --git a/packages/core/src/lib/template-engine/extensions/filters/unique.ts b/packages/core/src/lib/template-engine/extensions/filters/unique.ts index 0d52ea7f..06637b43 100644 --- a/packages/core/src/lib/template-engine/extensions/filters/unique.ts +++ b/packages/core/src/lib/template-engine/extensions/filters/unique.ts @@ -1,6 +1,8 @@ import { NunjucksFilterExtension } from '../extension'; import { uniq, uniqBy } from 'lodash'; +import { injectable } from 'inversify'; +@injectable() export class UniqueExtension implements NunjucksFilterExtension { public name = 'unique'; public async transform({ diff --git a/packages/core/src/lib/template-engine/extensions/tags/error.ts b/packages/core/src/lib/template-engine/extensions/tags/error.ts index f9511fa4..3d914e19 100644 --- a/packages/core/src/lib/template-engine/extensions/tags/error.ts +++ b/packages/core/src/lib/template-engine/extensions/tags/error.ts @@ -4,7 +4,9 @@ import { NunjucksTagExtensionRunOptions, } from '../extension'; import * as nunjucks from 'nunjucks'; +import { injectable } from 'inversify'; +@injectable() export class ErrorExtension implements NunjucksTagExtension { public name = 'built-in-error'; public tags = ['error']; diff --git a/packages/core/src/lib/template-engine/extensions/tags/req.ts b/packages/core/src/lib/template-engine/extensions/tags/req.ts index a2d7e887..0fdfc604 100644 --- a/packages/core/src/lib/template-engine/extensions/tags/req.ts +++ b/packages/core/src/lib/template-engine/extensions/tags/req.ts @@ -4,18 +4,21 @@ import { NunjucksTagExtensionRunOptions, } from '../extension'; import * as nunjucks from 'nunjucks'; +import { injectable, inject } from 'inversify'; +import { TYPES } from '@containers'; // TODO: temporary interface export interface Executor { executeQuery(query: string): Promise; } +@injectable() export class ReqExtension implements NunjucksTagExtension { public name = 'built-in-req'; public tags = ['req']; private executor: Executor; - constructor({ executor }: { executor: Executor }) { + constructor(@inject(TYPES.Executor) executor: Executor) { this.executor = executor; } diff --git a/packages/core/src/lib/template-engine/inMemoryCodeLoader.ts b/packages/core/src/lib/template-engine/inMemoryCodeLoader.ts index 9eb13f4a..4c662828 100644 --- a/packages/core/src/lib/template-engine/inMemoryCodeLoader.ts +++ b/packages/core/src/lib/template-engine/inMemoryCodeLoader.ts @@ -1,5 +1,7 @@ import * as nunjucks from 'nunjucks'; +import { injectable } from 'inversify'; +@injectable() export class InMemoryCodeLoader implements nunjucks.ILoader { private source = new Map(); diff --git a/packages/core/src/lib/template-engine/nunjucksCompiler.ts b/packages/core/src/lib/template-engine/nunjucksCompiler.ts index ba79e183..ab56c214 100644 --- a/packages/core/src/lib/template-engine/nunjucksCompiler.ts +++ b/packages/core/src/lib/template-engine/nunjucksCompiler.ts @@ -10,19 +10,20 @@ import { import * as transformer from 'nunjucks/src/transformer'; import { walkAst } from './visitors/astWalker'; import { ParametersVisitor, ErrorsVisitor, FiltersVisitor } from './visitors'; +import { inject, injectable, multiInject } from 'inversify'; +import { TYPES } from '@containers'; +@injectable() export class NunjucksCompiler implements Compiler { public name = 'nunjucks'; private env: nunjucks.Environment; private extensions: NunjucksCompilerExtension[]; - constructor({ - loader, - extensions = [], - }: { - loader: nunjucks.ILoader; - extensions?: NunjucksCompilerExtension[]; - }) { + constructor( + @inject(TYPES.CompilerLoader) loader: nunjucks.ILoader, + @multiInject(TYPES.CompilerExtension) + extensions: NunjucksCompilerExtension[] + ) { this.env = new nunjucks.Environment(loader); this.extensions = extensions; this.loadAllExtensions(); diff --git a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts index 624b2d39..7de40942 100644 --- a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts +++ b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts @@ -2,15 +2,17 @@ import { Template, TemplateProvider } from './templateProvider'; import * as glob from 'glob'; import { promises as fs } from 'fs'; import * as path from 'path'; +import { inject, injectable } from 'inversify'; +import { TYPES } from '@containers'; +import { ITemplateEngineOptions } from '@models'; -export interface FileTemplateProviderOptions { - folderPath: string; -} - +@injectable() export class FileTemplateProvider implements TemplateProvider { - private options: FileTemplateProviderOptions; + private options: ITemplateEngineOptions; - constructor(options: FileTemplateProviderOptions) { + constructor( + @inject(TYPES.TemplateEngineOptions) options: ITemplateEngineOptions + ) { this.options = options; } @@ -19,9 +21,7 @@ export class FileTemplateProvider implements TemplateProvider { for (const file of files) { yield { - name: path - .relative(this.options.folderPath, file) - .replace(/\.sql$/, ''), + name: path.relative(this.options.path, file).replace(/\.sql$/, ''), statement: await fs.readFile(file, 'utf8'), }; } @@ -30,7 +30,7 @@ export class FileTemplateProvider implements TemplateProvider { private async getTemplateFilePaths(): Promise { return new Promise((resolve, reject) => { glob( - path.resolve(this.options.folderPath, '**', '*.sql'), + path.resolve(this.options.path, '**', '*.sql'), { nodir: true }, (err, files) => { if (err) return reject(err); diff --git a/packages/core/src/lib/template-engine/templateEngine.ts b/packages/core/src/lib/template-engine/templateEngine.ts index 10e727ce..8cd71ed3 100644 --- a/packages/core/src/lib/template-engine/templateEngine.ts +++ b/packages/core/src/lib/template-engine/templateEngine.ts @@ -1,8 +1,8 @@ import { Compiler, TemplateMetadata } from './compiler'; -import { ErrorExtension, ReqExtension, UniqueExtension } from './extensions'; -import { InMemoryCodeLoader } from './inMemoryCodeLoader'; -import { NunjucksCompiler } from './nunjucksCompiler'; import { TemplateProvider } from './template-providers'; +import { injectable, inject, interfaces } from 'inversify'; +import { TYPES } from '@containers'; +import { TemplateEngineOptions } from '../../options'; export type AllTemplateMetadata = Record; @@ -13,48 +13,19 @@ export interface PreCompiledResult { metadata?: AllTemplateMetadata; } +@injectable() export class TemplateEngine { private compiler: Compiler; private templateProvider?: TemplateProvider; - constructor({ - compiler, - templateProvider, - }: { - compiler: Compiler; - templateProvider?: TemplateProvider; - }) { + constructor( + @inject(TYPES.Compiler) compiler: Compiler, + @inject(TYPES.Factory_TemplateProvider) + templateProviderFactory: interfaces.AutoNamedFactory, + @inject(TYPES.TemplateEngineOptions) options: TemplateEngineOptions + ) { this.compiler = compiler; - this.templateProvider = templateProvider; - } - - public static useDefaultLoader({ - compiledResult, - templateProvider, - }: { - compiledResult?: PreCompiledResult; - templateProvider?: TemplateProvider; - } = {}): TemplateEngine { - const loader = new InMemoryCodeLoader(); - // Put compiled templates into loader - if (compiledResult) { - Object.keys(compiledResult.templates).forEach((templateName) => { - loader.setSource(templateName, compiledResult.templates[templateName]); - }); - } - const executor = { - // TODO: replace with real executor - executeQuery: async () => [], - }; - const compiler = new NunjucksCompiler({ - loader, - extensions: [ - new ErrorExtension(), - new ReqExtension({ executor }), - new UniqueExtension(), - ], - }); - return new TemplateEngine({ compiler, templateProvider }); + this.templateProvider = templateProviderFactory(options.provider); } public async compile(): Promise> { diff --git a/packages/core/src/models/artifactBuilderOptions.ts b/packages/core/src/models/artifactBuilderOptions.ts new file mode 100644 index 00000000..11b5bf7b --- /dev/null +++ b/packages/core/src/models/artifactBuilderOptions.ts @@ -0,0 +1,13 @@ +export enum PersistentStoreType { + LocalFile = 'LocalFile', +} + +export enum SerializerType { + JSON = 'JSON', +} + +export interface IArtifactBuilderOptions { + storageType: PersistentStoreType; + path: string; + serializerType: SerializerType; +} diff --git a/packages/core/src/models/globalOptions.ts b/packages/core/src/models/globalOptions.ts new file mode 100644 index 00000000..7a767a28 --- /dev/null +++ b/packages/core/src/models/globalOptions.ts @@ -0,0 +1,7 @@ +import { IArtifactBuilderOptions } from './artifactBuilderOptions'; +import { ITemplateEngineOptions } from './templateEngineOptions'; + +export interface IGlobalOptions { + artifact: IArtifactBuilderOptions; + template: ITemplateEngineOptions; +} diff --git a/packages/core/src/models/index.ts b/packages/core/src/models/index.ts index eca8d074..95f9e24d 100644 --- a/packages/core/src/models/index.ts +++ b/packages/core/src/models/index.ts @@ -1 +1,4 @@ export * from './artifact'; +export * from './artifactBuilderOptions'; +export * from './globalOptions'; +export * from './templateEngineOptions'; diff --git a/packages/core/src/models/templateEngineOptions.ts b/packages/core/src/models/templateEngineOptions.ts new file mode 100644 index 00000000..1d5a8554 --- /dev/null +++ b/packages/core/src/models/templateEngineOptions.ts @@ -0,0 +1,8 @@ +export enum TemplateProviderType { + LocalFile = 'LocalFile', +} + +export interface ITemplateEngineOptions { + provider: TemplateProviderType; + path: string; +} diff --git a/packages/core/src/options/artifactBuilder.ts b/packages/core/src/options/artifactBuilder.ts new file mode 100644 index 00000000..334dd161 --- /dev/null +++ b/packages/core/src/options/artifactBuilder.ts @@ -0,0 +1,21 @@ +import { injectable, inject } from 'inversify'; +import { TYPES } from '@containers'; +import { + IArtifactBuilderOptions, + PersistentStoreType, + SerializerType, +} from '@models'; + +@injectable() +export class ArtifactBuilderOptions implements IArtifactBuilderOptions { + public readonly storageType!: PersistentStoreType; + public readonly serializerType!: SerializerType; + public readonly path!: string; + + constructor( + @inject(TYPES.ArtifactBuilderInputOptions) + options: IArtifactBuilderOptions + ) { + Object.assign(this, options); + } +} diff --git a/packages/core/src/options/index.ts b/packages/core/src/options/index.ts new file mode 100644 index 00000000..b1bd7351 --- /dev/null +++ b/packages/core/src/options/index.ts @@ -0,0 +1,2 @@ +export * from './artifactBuilder'; +export * from './templateEngine'; diff --git a/packages/core/src/options/templateEngine.ts b/packages/core/src/options/templateEngine.ts new file mode 100644 index 00000000..2a461bed --- /dev/null +++ b/packages/core/src/options/templateEngine.ts @@ -0,0 +1,16 @@ +import { injectable, inject } from 'inversify'; +import { TYPES } from '@containers'; +import { ITemplateEngineOptions, TemplateProviderType } from '@models'; + +@injectable() +export class TemplateEngineOptions implements ITemplateEngineOptions { + public readonly provider!: TemplateProviderType; + public readonly path!: string; + + constructor( + @inject(TYPES.TemplateEngineInputOptions) + options: ITemplateEngineOptions + ) { + Object.assign(this, options); + } +} diff --git a/packages/core/test/containers/continer.spec.ts b/packages/core/test/containers/continer.spec.ts new file mode 100644 index 00000000..d729755c --- /dev/null +++ b/packages/core/test/containers/continer.spec.ts @@ -0,0 +1,37 @@ +import { ArtifactBuilder } from '@artifact-builder'; +import { Container, TYPES } from '@containers'; +import { + PersistentStoreType, + SerializerType, + TemplateProviderType, +} from '@models'; +import { TemplateEngine } from '@template-engine'; +import * as path from 'path'; +import * as fs from 'fs'; + +it('Container should load options and resolve all dependencies', async () => { + // Arrange + const resultPath = path.resolve(__dirname, 'result.json'); + if (fs.existsSync(resultPath)) { + fs.unlinkSync(resultPath); + } + const container = new Container(); + container.load({ + artifact: { + storageType: PersistentStoreType.LocalFile, + path: resultPath, + serializerType: SerializerType.JSON, + }, + template: { + provider: TemplateProviderType.LocalFile, + path: path.resolve(__dirname, 'test-template'), + }, + }); + // Act + const templateEngine = container.get(TYPES.TemplateEngine); + const artifactBuilder = container.get(TYPES.ArtifactBuilder); + const { templates } = await templateEngine.compile(); + await artifactBuilder.build({ templates, schemas: [] }); + // Assert + expect(fs.existsSync(resultPath)).toBeTruthy(); +}); diff --git a/packages/core/test/containers/result.json b/packages/core/test/containers/result.json new file mode 100644 index 00000000..747ef950 --- /dev/null +++ b/packages/core/test/containers/result.json @@ -0,0 +1 @@ +{"templates":{"group":"(() => {function root(env, context, frame, runtime, cb) {\nvar lineno = 0;\nvar colno = 0;\nvar output = \"\";\ntry {\nvar parentTemplate = null;\noutput += \"select * from public.group where id = \";\noutput += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, \"id\"), env.opts.autoescape);\nif(parentTemplate) {\nparentTemplate.rootRenderFunc(env, context, frame, runtime, cb);\n} else {\ncb(null, output);\n}\n;\n} catch (e) {\n cb(runtime.handleError(e, lineno, colno));\n}\n}\nreturn {\nroot: root\n};\n})()"},"compiler":"nunjucks","schemas":[]} \ No newline at end of file diff --git a/packages/core/test/containers/test-template/group.sql b/packages/core/test/containers/test-template/group.sql new file mode 100644 index 00000000..d7e2fcd3 --- /dev/null +++ b/packages/core/test/containers/test-template/group.sql @@ -0,0 +1 @@ +select * from public.group where id = {{ id }} \ No newline at end of file diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 0cb0c07a..ead942e1 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -13,7 +13,9 @@ "@artifact-builder": ["packages/core/src/lib/artifact-builder/index"], "@artifact-builder/*": ["packages/core/src/lib/artifact-builder/*"], "@template-engine": ["packages/core/src/lib/template-engine/index"], - "@template-engine/*": ["packages/core/src/lib/template-engine/*"] + "@template-engine/*": ["packages/core/src/lib/template-engine/*"], + "@containers": ["packages/core/src/containers/index"], + "@models": ["packages/core/src/models/index"] } }, "references": [ diff --git a/tsconfig.base.json b/tsconfig.base.json index ccf6316b..d669804a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -14,6 +14,7 @@ "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", + "types": ["reflect-metadata"], "paths": { "@vulcan/build": ["packages/build/src/index.ts"], "@vulcan/core": ["packages/core/src/index.ts"] diff --git a/yarn.lock b/yarn.lock index 6b122db4..4271771b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2684,6 +2684,11 @@ inquirer@6.5.2: strip-ansi "^5.1.0" through "^2.3.6" +inversify@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-6.0.1.tgz#b20d35425d5d8c5cd156120237aad0008d969f02" + integrity sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3863,6 +3868,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +reflect-metadata@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" + integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" From 9145f4abea1cbe4909f0c7cfa4e988170732929a Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Tue, 17 May 2022 12:16:22 +0800 Subject: [PATCH 2/8] fix(core): update test cases of core package to used container --- .../lib/template-engine/nunjucksCompiler.ts | 5 +- .../src/lib/template-engine/templateEngine.ts | 4 +- .../localFilePersistentStore.spec.ts | 25 ++++-- .../vulcanArtifactBuilder.spec.ts | 70 ++++++++++------- packages/core/test/containers/.gitignore | 1 + packages/core/test/containers/result.json | 1 - .../extensions/filters/unique.spec.ts | 40 ++++++---- .../extensions/tags/error.spec.ts | 26 +++++-- .../extensions/tags/req.spec.ts | 44 ++++++----- .../template-engine/nunjuckCompiler.spec.ts | 28 +++++-- .../fileTemplateProvider.spec.ts | 23 +++++- .../fileTemplateProviderError.spec.ts | 23 +++++- .../template-engine/templateEngine.spec.ts | 78 ++++++++----------- 13 files changed, 232 insertions(+), 136 deletions(-) create mode 100644 packages/core/test/containers/.gitignore delete mode 100644 packages/core/test/containers/result.json diff --git a/packages/core/src/lib/template-engine/nunjucksCompiler.ts b/packages/core/src/lib/template-engine/nunjucksCompiler.ts index ab56c214..44bfef43 100644 --- a/packages/core/src/lib/template-engine/nunjucksCompiler.ts +++ b/packages/core/src/lib/template-engine/nunjucksCompiler.ts @@ -10,7 +10,7 @@ import { import * as transformer from 'nunjucks/src/transformer'; import { walkAst } from './visitors/astWalker'; import { ParametersVisitor, ErrorsVisitor, FiltersVisitor } from './visitors'; -import { inject, injectable, multiInject } from 'inversify'; +import { inject, injectable, multiInject, optional } from 'inversify'; import { TYPES } from '@containers'; @injectable() @@ -22,7 +22,8 @@ export class NunjucksCompiler implements Compiler { constructor( @inject(TYPES.CompilerLoader) loader: nunjucks.ILoader, @multiInject(TYPES.CompilerExtension) - extensions: NunjucksCompilerExtension[] + @optional() + extensions: NunjucksCompilerExtension[] = [] ) { this.env = new nunjucks.Environment(loader); this.extensions = extensions; diff --git a/packages/core/src/lib/template-engine/templateEngine.ts b/packages/core/src/lib/template-engine/templateEngine.ts index 8cd71ed3..f6aa769f 100644 --- a/packages/core/src/lib/template-engine/templateEngine.ts +++ b/packages/core/src/lib/template-engine/templateEngine.ts @@ -16,7 +16,7 @@ export interface PreCompiledResult { @injectable() export class TemplateEngine { private compiler: Compiler; - private templateProvider?: TemplateProvider; + private templateProvider: TemplateProvider; constructor( @inject(TYPES.Compiler) compiler: Compiler, @@ -29,8 +29,6 @@ export class TemplateEngine { } public async compile(): Promise> { - if (!this.templateProvider) throw new Error('Template provider is not set'); - const templateResult: Record = {}; const metadataResult: Record = {}; diff --git a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts index 060780e0..c651fc79 100644 --- a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts +++ b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts @@ -1,11 +1,24 @@ import * as path from 'path'; -import { LocalFilePersistentStore } from '@artifact-builder'; +import { LocalFilePersistentStore, PersistentStore } from '@artifact-builder'; +import { TYPES } from '@containers'; +import { Container } from 'inversify'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.ArtifactBuilderOptions) + .toConstantValue({ path: path.resolve(__dirname, 'test.json') }); + container + .bind(TYPES.PersistentStore) + .to(LocalFilePersistentStore) + .inSingletonScope(); +}); it('Should persist data to file', async () => { // Arrange - const ps = new LocalFilePersistentStore({ - filePath: path.resolve(__dirname, 'test.json'), - }); + const ps = container.get(TYPES.PersistentStore); const data = Buffer.from('Hello World'); // Act, Assert await expect(ps.save(data)).resolves.not.toThrow(); @@ -13,9 +26,7 @@ it('Should persist data to file', async () => { it('Should load persisted data from file with correct data', async () => { // Arrange - const ps = new LocalFilePersistentStore({ - filePath: path.resolve(__dirname, 'test.json'), - }); + const ps = container.get(TYPES.PersistentStore); const data = Buffer.from('Hello World'); await ps.save(data); // Act diff --git a/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts b/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts index 1c6782f8..f509aba5 100644 --- a/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts +++ b/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts @@ -1,41 +1,55 @@ -import * as path from 'path'; import { Artifact, + JSONSerializer, LocalFilePersistentStore, VulcanArtifactBuilder, } from '@artifact-builder'; +import { Container } from 'inversify'; +import { TYPES } from '@containers'; +import * as sinon from 'ts-sinon'; -it('Should persist artifacts to file', async () => { +let container: Container; +let mockPersistentStore: sinon.StubbedInstance; + +const mockArtifact: Artifact = { + schemas: [], + templates: {}, +}; + +beforeEach(() => { + container = new Container(); + mockPersistentStore = sinon.stubInterface(); + + container + .bind(TYPES.Factory_PersistentStore) + .toConstantValue(() => mockPersistentStore); + container + .bind(TYPES.Factory_Serializer) + .toConstantValue(() => new JSONSerializer()); + + container.bind(TYPES.ArtifactBuilderOptions).toConstantValue({}); + container.bind(TYPES.ArtifactBuilder).to(VulcanArtifactBuilder); +}); + +it('Should pass serialized data to store while building', async () => { // Arrange - const ps = new LocalFilePersistentStore({ - filePath: path.resolve(__dirname, 'test.json'), - }); - const build = new VulcanArtifactBuilder({ - persistentStore: ps, - }); - const data: Artifact = { - schemas: [], - templates: {}, - }; - // Act, Assert - await expect(build.build(data)).resolves.not.toThrow(); + const builder = container.get(TYPES.ArtifactBuilder); + + // Act + await builder.build(mockArtifact); + + // Assert + expect(mockPersistentStore.save.calledOnce).toBe(true); }); -it('Should load persisted artifacts from file with correct data', async () => { +it('Should load deserialized data while loading', async () => { // Arrange - const ps = new LocalFilePersistentStore({ - filePath: path.resolve(__dirname, 'test.json'), - }); - const build = new VulcanArtifactBuilder({ - persistentStore: ps, - }); - const data: Artifact = { - schemas: [], - templates: {}, - }; - await build.build(data); + const builder = container.get(TYPES.ArtifactBuilder); + mockPersistentStore.load.resolves(Buffer.from(JSON.stringify(mockArtifact))); + // Act - const loadedData = await build.load(); + const artifact = await builder.load(); + // Assert - expect(loadedData).toEqual(data); + expect(artifact).toEqual(mockArtifact); }); diff --git a/packages/core/test/containers/.gitignore b/packages/core/test/containers/.gitignore new file mode 100644 index 00000000..49850731 --- /dev/null +++ b/packages/core/test/containers/.gitignore @@ -0,0 +1 @@ +result.json \ No newline at end of file diff --git a/packages/core/test/containers/result.json b/packages/core/test/containers/result.json deleted file mode 100644 index 747ef950..00000000 --- a/packages/core/test/containers/result.json +++ /dev/null @@ -1 +0,0 @@ -{"templates":{"group":"(() => {function root(env, context, frame, runtime, cb) {\nvar lineno = 0;\nvar colno = 0;\nvar output = \"\";\ntry {\nvar parentTemplate = null;\noutput += \"select * from public.group where id = \";\noutput += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, \"id\"), env.opts.autoescape);\nif(parentTemplate) {\nparentTemplate.rootRenderFunc(env, context, frame, runtime, cb);\n} else {\ncb(null, output);\n}\n;\n} catch (e) {\n cb(runtime.handleError(e, lineno, colno));\n}\n}\nreturn {\nroot: root\n};\n})()"},"compiler":"nunjucks","schemas":[]} \ No newline at end of file diff --git a/packages/core/test/template-engine/extensions/filters/unique.spec.ts b/packages/core/test/template-engine/extensions/filters/unique.spec.ts index fcd48e68..25b6a3db 100644 --- a/packages/core/test/template-engine/extensions/filters/unique.spec.ts +++ b/packages/core/test/template-engine/extensions/filters/unique.spec.ts @@ -1,16 +1,32 @@ +import { TYPES } from '@containers'; import { NunjucksCompiler, InMemoryCodeLoader, UniqueExtension, + Compiler, } from '@template-engine'; +import { Container } from 'inversify'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.CompilerLoader) + .to(InMemoryCodeLoader) + .inSingletonScope(); + container.bind(TYPES.Compiler).to(NunjucksCompiler).inSingletonScope(); + container.bind(TYPES.CompilerExtension).to(UniqueExtension); +}); + +afterEach(() => { + container.unbindAll(); +}); it('Extension should return correct values without unique by argument', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new UniqueExtension()], - }); + const compiler = container.get(TYPES.Compiler); + const loader = container.get(TYPES.CompilerLoader); const { compiledData } = compiler.compile( ` {% set array = [1,2,3,4,4] %} @@ -28,11 +44,8 @@ it('Extension should return correct values without unique by argument', async () it('Extension should return correct values with unique by keyword argument', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new UniqueExtension()], - }); + const compiler = container.get(TYPES.Compiler); + const loader = container.get(TYPES.CompilerLoader); const { compiledData } = compiler.compile( ` {% set array = [{name: "Tom"}, {name: "Tom"}, {name: "Joy"}] %} @@ -50,11 +63,8 @@ it('Extension should return correct values with unique by keyword argument', asy it('Extension should return correct values with unique by argument', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new UniqueExtension()], - }); + const compiler = container.get(TYPES.Compiler); + const loader = container.get(TYPES.CompilerLoader); const { compiledData } = compiler.compile( ` {% set array = [{name: "Tom"}, {name: "Tom"}, {name: "Joy"}] %} diff --git a/packages/core/test/template-engine/extensions/tags/error.spec.ts b/packages/core/test/template-engine/extensions/tags/error.spec.ts index 7806569b..069de795 100644 --- a/packages/core/test/template-engine/extensions/tags/error.spec.ts +++ b/packages/core/test/template-engine/extensions/tags/error.spec.ts @@ -1,16 +1,32 @@ +import { TYPES } from '@containers'; import { NunjucksCompiler, InMemoryCodeLoader, ErrorExtension, + Compiler, } from '@template-engine'; +import { Container } from 'inversify'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.CompilerLoader) + .to(InMemoryCodeLoader) + .inSingletonScope(); + container.bind(TYPES.Compiler).to(NunjucksCompiler).inSingletonScope(); + container.bind(TYPES.CompilerExtension).to(ErrorExtension); +}); + +afterEach(() => { + container.unbindAll(); +}); it('Error extension should throw error with error code and the position while rendering', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new ErrorExtension()], - }); + const compiler = container.get(TYPES.Compiler); + const loader = container.get(TYPES.CompilerLoader); const { compiledData } = compiler.compile(` {% error "This is an error" %} `); diff --git a/packages/core/test/template-engine/extensions/tags/req.spec.ts b/packages/core/test/template-engine/extensions/tags/req.spec.ts index a1566ca0..cb50d78f 100644 --- a/packages/core/test/template-engine/extensions/tags/req.spec.ts +++ b/packages/core/test/template-engine/extensions/tags/req.spec.ts @@ -1,19 +1,37 @@ +import { TYPES } from '@containers'; import { NunjucksCompiler, InMemoryCodeLoader, Executor, ReqExtension, + Compiler, } from '@template-engine'; +import { Container } from 'inversify'; import * as sinon from 'ts-sinon'; +let container: Container; +let mockExecutor: sinon.StubbedInstance; + +beforeEach(() => { + container = new Container(); + mockExecutor = sinon.stubInterface(); + container + .bind(TYPES.CompilerLoader) + .to(InMemoryCodeLoader) + .inSingletonScope(); + container.bind(TYPES.Executor).toConstantValue(mockExecutor); + container.bind(TYPES.Compiler).to(NunjucksCompiler).inSingletonScope(); + container.bind(TYPES.CompilerExtension).to(ReqExtension).inSingletonScope(); +}); + +afterEach(() => { + container.unbindAll(); +}); + it('req extension should execute correct query and set variable', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const mockExecutor = sinon.stubInterface(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new ReqExtension({ executor: mockExecutor })], - }); + const compiler = container.get(TYPES.Compiler); + const loader = container.get(TYPES.CompilerLoader); const { compiledData } = compiler.compile(` {% req userCount %} select count(*) as count from user where user.id = '{{ params.userId }}'; @@ -36,12 +54,7 @@ select count(*) as count from user where user.id = '{{ params.userId }}'; it('if argument is not a symbol, extension should throw', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const mockExecutor = sinon.stubInterface(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new ReqExtension({ executor: mockExecutor })], - }); + const compiler = container.get(TYPES.Compiler); // Action, Assert expect(() => @@ -55,12 +68,7 @@ select count(*) as count from user where user.id = '{{ params.userId }}'; it('if argument is missing, extension should throw', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const mockExecutor = sinon.stubInterface(); - const compiler = new NunjucksCompiler({ - loader, - extensions: [new ReqExtension({ executor: mockExecutor })], - }); + const compiler = container.get(TYPES.Compiler); // Action, Assert expect(() => diff --git a/packages/core/test/template-engine/nunjuckCompiler.spec.ts b/packages/core/test/template-engine/nunjuckCompiler.spec.ts index 6105bbdf..4e1f716f 100644 --- a/packages/core/test/template-engine/nunjuckCompiler.spec.ts +++ b/packages/core/test/template-engine/nunjuckCompiler.spec.ts @@ -1,13 +1,30 @@ +import { TYPES } from '@containers'; import { NunjucksCompiler, InMemoryCodeLoader, NunjucksCompilerExtension, + Compiler, } from '@template-engine'; +import { Container } from 'inversify'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.CompilerLoader) + .to(InMemoryCodeLoader) + .inSingletonScope(); + container.bind(TYPES.Compiler).to(NunjucksCompiler).inSingletonScope(); +}); + +afterEach(() => { + container.unbindAll(); +}); it('Nunjucks compiler should compile template without error.', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ loader }); + const compiler = container.get(TYPES.Compiler); // Action const compilerCode = compiler.compile('Hello {{ name }}'); @@ -18,8 +35,8 @@ it('Nunjucks compiler should compile template without error.', async () => { it('Nunjucks compiler should load compiled code and render template with it', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ loader }); + const loader = container.get(TYPES.CompilerLoader); + const compiler = container.get(TYPES.Compiler); const { compiledData } = compiler.compile('Hello {{ name }}!'); // Action @@ -32,8 +49,7 @@ it('Nunjucks compiler should load compiled code and render template with it', as it('Nunjucks compiler should reject unsupported extensions', async () => { // Arrange - const loader = new InMemoryCodeLoader(); - const compiler = new NunjucksCompiler({ loader }); + const compiler = container.get(TYPES.Compiler); // Action, Assert // extension should have parse and name property expect(() => diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts index 907264e6..c0eee3c0 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts @@ -1,10 +1,29 @@ +import { TYPES } from '@containers'; +import { ITemplateEngineOptions, TemplateProviderType } from '@models'; import { FileTemplateProvider, Template } from '@template-engine'; +import { Container } from 'inversify'; import * as path from 'path'; +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.TemplateEngineOptions) + .toConstantValue({ + provider: TemplateProviderType.LocalFile, + path: path.resolve(__dirname, '../test-templates'), + }); + container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); +}); + +afterEach(() => { + container.unbindAll(); +}); + it('File template provider should provide correct files and contents', async () => { // Arrange - const filePath = path.resolve(__dirname, '../test-templates'); - const provider = new FileTemplateProvider({ folderPath: filePath }); + const provider = container.get(TYPES.TemplateProvider); const templates: Template[] = []; // Act diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts index 4be0ba68..65163932 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts @@ -1,4 +1,7 @@ +import { TYPES } from '@containers'; +import { ITemplateEngineOptions, TemplateProviderType } from '@models'; import { FileTemplateProvider } from '@template-engine'; +import { Container } from 'inversify'; jest.mock('glob', () => { return ( @@ -10,10 +13,26 @@ jest.mock('glob', () => { }; }); +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.TemplateEngineOptions) + .toConstantValue({ + provider: TemplateProviderType.LocalFile, + path: '.', + }); + container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); +}); + +afterEach(() => { + container.unbindAll(); +}); + it('File template provider should throw error with file search errors', async () => { // Arrange - const filePath = '.'; - const provider = new FileTemplateProvider({ folderPath: filePath }); + const provider = container.get(TYPES.TemplateProvider); // Act, Assert const iter = provider.getTemplates(); await expect(iter.next()).rejects.toThrow('mock error'); diff --git a/packages/core/test/template-engine/templateEngine.spec.ts b/packages/core/test/template-engine/templateEngine.spec.ts index bd987893..3d2a098f 100644 --- a/packages/core/test/template-engine/templateEngine.spec.ts +++ b/packages/core/test/template-engine/templateEngine.spec.ts @@ -1,15 +1,24 @@ -import { - TemplateEngine, - Compiler, - TemplateProvider, - FileTemplateProvider, -} from '@template-engine'; +import { TemplateEngine, Compiler, TemplateProvider } from '@template-engine'; import * as sinon from 'ts-sinon'; -import * as path from 'path'; +import { TYPES } from '@containers'; +import { Container } from 'inversify'; + +let container: Container; +let stubCompiler: sinon.StubbedInstance; +let stubTemplateProvider: sinon.StubbedInstance; + +beforeEach(() => { + container = new Container(); + stubCompiler = sinon.stubInterface(); + stubTemplateProvider = sinon.stubInterface(); + + container.bind(TYPES.Compiler).toConstantValue(stubCompiler); + container + .bind(TYPES.Factory_TemplateProvider) + .toConstantValue(() => stubTemplateProvider); + container.bind(TYPES.TemplateEngine).to(TemplateEngine).inSingletonScope(); + container.bind(TYPES.TemplateEngineOptions).toConstantValue({}); -it('Template engine compile function should wrap correct result', async () => { - // Assert - const stubCompiler = sinon.stubInterface(); stubCompiler.name = 'stub-compiler'; stubCompiler.compile.returns({ compiledData: 'compiled-template', @@ -18,7 +27,8 @@ it('Template engine compile function should wrap correct result', async () => { errors: [], }, }); - const stubTemplateProvider = sinon.stubInterface(); + stubCompiler.render.resolves('sql-statement'); + const generator = async function* () { yield { name: 'template-name', @@ -26,10 +36,15 @@ it('Template engine compile function should wrap correct result', async () => { }; }; stubTemplateProvider.getTemplates.returns(generator()); - const templateEngine = new TemplateEngine({ - compiler: stubCompiler, - templateProvider: stubTemplateProvider, - }); +}); + +afterEach(() => { + container.unbindAll(); +}); + +it('Template engine compile function should wrap correct result', async () => { + // Assert + const templateEngine = container.get(TYPES.TemplateEngine); // Act const result = await templateEngine.compile(); @@ -51,9 +66,7 @@ it('Template engine compile function should wrap correct result', async () => { it('Template engine render function should forward correct data to compiler', async () => { // Assert - const stubCompiler = sinon.stubInterface(); - stubCompiler.render.resolves('sql-statement'); - const templateEngine = new TemplateEngine({ compiler: stubCompiler }); + const templateEngine = container.get(TYPES.TemplateEngine); const context = { name: 'name', }; @@ -65,32 +78,3 @@ it('Template engine render function should forward correct data to compiler', as expect(stubCompiler.render.calledWith('template-name', context)).toBe(true); expect(result).toBe('sql-statement'); }); - -it('Template engine useDefaultLoader function should return a fully functional instance', async () => { - // Assert - const templateProvider = new FileTemplateProvider({ - folderPath: path.resolve(__dirname, './test-templates'), - }); - const templateEngine = TemplateEngine.useDefaultLoader({ templateProvider }); - const compiledResult = await templateEngine.compile(); - - // Act - const defaultTemplateEngine = TemplateEngine.useDefaultLoader({ - compiledResult, - }); - const userStatement = await defaultTemplateEngine.render('user', { - id: 1, - }); - - // Assert - expect(userStatement).toBe('select * from public.user where id = 1'); -}); - -it('Should throw error when compiling without template provider', async () => { - // Assert - const templateEngine = TemplateEngine.useDefaultLoader(); - // Act, Assert - await expect(templateEngine.compile()).rejects.toThrow( - 'Template provider is not set' - ); -}); From 5583574f08156548d1e76d2d78600a9b05d69626 Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Tue, 17 May 2022 16:57:23 +0800 Subject: [PATCH 3/8] fix: fix path alias and add container for build package - Fix path alias conflict issue - Add IoC container for build package - Use a root file as the entry point instead of pipeline folder --- packages/build/src/containers/container.ts | 28 +++++++ packages/build/src/containers/index.ts | 3 + .../build/src/containers/modules/index.ts | 1 + .../src/containers/modules/schemaParser.ts | 33 ++++++++ packages/build/src/containers/types.ts | 7 ++ packages/build/src/index.ts | 2 +- packages/build/src/lib/pipelline/index.ts | 1 - packages/build/src/lib/pipelline/pipeline.ts | 75 ------------------- .../middleware/checkValidator.ts | 3 +- .../schema-reader/fileSchemaReader.ts | 15 ++-- .../schema-reader/schemaReader.ts | 4 +- .../src/lib/schema-parser/schemaParser.ts | 35 ++++----- packages/build/src/lib/vulcanBuilder.ts | 29 +++++++ packages/build/src/models/buildOptions.ts | 6 ++ packages/build/src/models/index.ts | 2 + .../build/src/models/schemaParserOptions.ts | 8 ++ packages/build/src/options/index.ts | 1 + packages/build/src/options/schemaParser.ts | 17 +++++ .../test/{pipeline => builder}/.gitignore | 0 packages/build/test/builder/builder.spec.ts | 31 ++++++++ .../source/detail/role.sql | 0 .../source/detail/role.yaml | 0 .../{pipeline => builder}/source/user.sql | 0 .../{pipeline => builder}/source/user.yaml | 0 packages/build/test/pipeline/pipeline.spec.ts | 44 ----------- .../middleware/checkValidator.spec.ts | 5 +- .../middleware/generateTemplateSource.spec.ts | 4 +- .../middleware/generateUrl.spec.ts | 4 +- .../middleware/transformValidator.spec.ts | 4 +- .../schema-reader/fileSchemaReader.spec.ts | 30 +++++++- .../fileSchemaReaderError.spec.ts | 30 +++++++- .../test/schema-parser/schemaParser.spec.ts | 54 +++++++++---- packages/build/tsconfig.json | 6 +- packages/core/src/containers/container.ts | 10 ++- .../src/containers/modules/artifactBuilder.ts | 4 +- .../core/src/containers/modules/executor.ts | 2 +- packages/core/src/containers/modules/index.ts | 1 + .../src/containers/modules/templateEngine.ts | 9 ++- .../core/src/containers/modules/validator.ts | 17 +++++ packages/core/src/containers/types.ts | 2 + packages/core/src/index.ts | 1 + .../localFilePersistentStore.ts | 4 +- .../artifact-builder/vulcanArtifactBuilder.ts | 2 +- .../template-engine/extensions/tags/req.ts | 2 +- .../lib/template-engine/nunjucksCompiler.ts | 2 +- .../fileTemplateProvider.ts | 4 +- .../src/lib/template-engine/templateEngine.ts | 2 +- .../{globalOptions.ts => coreOptions.ts} | 2 +- packages/core/src/models/index.ts | 2 +- packages/core/src/options/artifactBuilder.ts | 4 +- packages/core/src/options/templateEngine.ts | 7 +- packages/core/src/validators/index.ts | 1 + .../core/src/validators/validatorLoader.ts | 5 ++ .../localFilePersistentStore.spec.ts | 7 +- .../vulcanArtifactBuilder.spec.ts | 4 +- .../core/test/containers/continer.spec.ts | 8 +- .../extensions/filters/unique.spec.ts | 4 +- .../extensions/tags/error.spec.ts | 4 +- .../extensions/tags/req.spec.ts | 4 +- .../inMemoryCodeLoader.spec.ts | 2 +- .../template-engine/nunjuckCompiler.spec.ts | 4 +- .../fileTemplateProvider.spec.ts | 9 ++- .../fileTemplateProviderError.spec.ts | 9 ++- .../template-engine/templateEngine.spec.ts | 8 +- .../visitors/astWalker.spec.ts | 2 +- .../template-engine/visitors/errors.spec.ts | 4 +- .../template-engine/visitors/filter.spec.ts | 2 +- .../visitors/parameters.spec.ts | 2 +- packages/core/tsconfig.json | 10 +-- tsconfig.base.json | 25 ++++++- 70 files changed, 430 insertions(+), 243 deletions(-) create mode 100644 packages/build/src/containers/container.ts create mode 100644 packages/build/src/containers/index.ts create mode 100644 packages/build/src/containers/modules/index.ts create mode 100644 packages/build/src/containers/modules/schemaParser.ts create mode 100644 packages/build/src/containers/types.ts delete mode 100644 packages/build/src/lib/pipelline/index.ts delete mode 100644 packages/build/src/lib/pipelline/pipeline.ts create mode 100644 packages/build/src/lib/vulcanBuilder.ts create mode 100644 packages/build/src/models/buildOptions.ts create mode 100644 packages/build/src/models/index.ts create mode 100644 packages/build/src/models/schemaParserOptions.ts create mode 100644 packages/build/src/options/index.ts create mode 100644 packages/build/src/options/schemaParser.ts rename packages/build/test/{pipeline => builder}/.gitignore (100%) create mode 100644 packages/build/test/builder/builder.spec.ts rename packages/build/test/{pipeline => builder}/source/detail/role.sql (100%) rename packages/build/test/{pipeline => builder}/source/detail/role.yaml (100%) rename packages/build/test/{pipeline => builder}/source/user.sql (100%) rename packages/build/test/{pipeline => builder}/source/user.yaml (100%) delete mode 100644 packages/build/test/pipeline/pipeline.spec.ts create mode 100644 packages/core/src/containers/modules/validator.ts rename packages/core/src/models/{globalOptions.ts => coreOptions.ts} (86%) create mode 100644 packages/core/src/validators/validatorLoader.ts diff --git a/packages/build/src/containers/container.ts b/packages/build/src/containers/container.ts new file mode 100644 index 00000000..219b0073 --- /dev/null +++ b/packages/build/src/containers/container.ts @@ -0,0 +1,28 @@ +import { Container as InversifyContainer } from 'inversify'; +import { Container as CoreContainer } from '@vulcan/core'; +import { IBuildOptions } from '@vulcan/build/models'; +import { schemaParserModule } from './modules'; + +export class Container { + private inversifyContainer = new InversifyContainer(); + + public get(type: symbol) { + return this.inversifyContainer.get(type); + } + + public load(options: IBuildOptions) { + const coreContainer = new CoreContainer(); + coreContainer.load(options); + this.inversifyContainer.parent = coreContainer.getInversifyContainer(); + this.inversifyContainer.load(schemaParserModule(options.schemaParser)); + } + + public unload() { + this.inversifyContainer.parent?.unbindAll(); + this.inversifyContainer.unbindAll(); + } + + public getInversifyContainer() { + return this.inversifyContainer; + } +} diff --git a/packages/build/src/containers/index.ts b/packages/build/src/containers/index.ts new file mode 100644 index 00000000..2f90771a --- /dev/null +++ b/packages/build/src/containers/index.ts @@ -0,0 +1,3 @@ +import 'reflect-metadata'; +export * from './types'; +export * from './container'; diff --git a/packages/build/src/containers/modules/index.ts b/packages/build/src/containers/modules/index.ts new file mode 100644 index 00000000..1084ca58 --- /dev/null +++ b/packages/build/src/containers/modules/index.ts @@ -0,0 +1 @@ +export * from './schemaParser'; diff --git a/packages/build/src/containers/modules/schemaParser.ts b/packages/build/src/containers/modules/schemaParser.ts new file mode 100644 index 00000000..a98cecff --- /dev/null +++ b/packages/build/src/containers/modules/schemaParser.ts @@ -0,0 +1,33 @@ +import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; +import { + FileSchemaReader, + SchemaParser, + SchemaReader, +} from '@vulcan/build/schema-parser'; +import { ContainerModule, interfaces } from 'inversify'; +import { SchemaParserOptions } from '../../options/schemaParser'; +import { TYPES } from '../types'; + +export const schemaParserModule = (options: ISchemaParserOptions) => + new ContainerModule((bind) => { + // Options + bind(TYPES.SchemaParserInputOptions).toConstantValue( + options + ); + bind(TYPES.SchemaParserOptions) + .to(SchemaParserOptions) + .inSingletonScope(); + + // Schema reader + bind(TYPES.SchemaReader) + .to(FileSchemaReader) + .inSingletonScope() + .whenTargetNamed(SchemaReaderType.LocalFile); + + bind>( + TYPES.Factory_SchemaReader + ).toAutoNamedFactory(TYPES.SchemaReader); + + // Schema parser + bind(TYPES.SchemaParser).to(SchemaParser).inSingletonScope(); + }); diff --git a/packages/build/src/containers/types.ts b/packages/build/src/containers/types.ts new file mode 100644 index 00000000..b8ca77d3 --- /dev/null +++ b/packages/build/src/containers/types.ts @@ -0,0 +1,7 @@ +export const TYPES = { + SchemaParserInputOptions: Symbol.for('SchemaParserInputOptions'), + SchemaParserOptions: Symbol.for('SchemaParserOptions'), + SchemaReader: Symbol.for('SchemaReader'), + Factory_SchemaReader: Symbol.for('Factory_SchemaReader'), + SchemaParser: Symbol.for('SchemaParser'), +}; diff --git a/packages/build/src/index.ts b/packages/build/src/index.ts index 2a9da3a1..a9e794e3 100644 --- a/packages/build/src/index.ts +++ b/packages/build/src/index.ts @@ -1,2 +1,2 @@ export * from './lib/schema-parser'; -export * from './lib/pipelline'; +export * from './lib/vulcanBuilder'; diff --git a/packages/build/src/lib/pipelline/index.ts b/packages/build/src/lib/pipelline/index.ts deleted file mode 100644 index ef24fea4..00000000 --- a/packages/build/src/lib/pipelline/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './pipeline'; diff --git a/packages/build/src/lib/pipelline/pipeline.ts b/packages/build/src/lib/pipelline/pipeline.ts deleted file mode 100644 index 2b5a6005..00000000 --- a/packages/build/src/lib/pipelline/pipeline.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - ArtifactBuilder, - FileTemplateProvider, - LocalFilePersistentStore, - TemplateEngine, - VulcanArtifactBuilder, -} from '@vulcan/core'; -import { FileSchemaReader, SchemaParser } from '../schema-parser'; - -export class BuildPipeline { - private schemaParser: SchemaParser; - private templateEngine: TemplateEngine; - private artifactBuilder: ArtifactBuilder; - - constructor({ - schemaParser, - templateEngine, - artifactBuilder, - }: { - schemaParser: SchemaParser; - templateEngine: TemplateEngine; - artifactBuilder: ArtifactBuilder; - }) { - this.schemaParser = schemaParser; - this.templateEngine = templateEngine; - this.artifactBuilder = artifactBuilder; - } - - static default({ - sourceFolderPath, - destinationFilePath, - }: { - sourceFolderPath: string; - destinationFilePath: string; - }): BuildPipeline { - const schemaReader = new FileSchemaReader({ - folderPath: sourceFolderPath, - }); - const schemaParser = new SchemaParser({ - schemaReader, - // TODO: mock loader, should be replaced with real loader from core package - validatorLoader: { - getLoader: () => ({ - name: '', - validateSchema: () => true, - validateData: () => true, - }), - }, - }); - const templateProvider = new FileTemplateProvider({ - folderPath: sourceFolderPath, - }); - const templateEngine = TemplateEngine.useDefaultLoader({ - templateProvider, - }); - const persistentStore = new LocalFilePersistentStore({ - filePath: destinationFilePath, - }); - const artifactBuilder = new VulcanArtifactBuilder({ persistentStore }); - return new BuildPipeline({ - schemaParser, - templateEngine, - artifactBuilder, - }); - } - - public async build() { - const { templates, metadata } = await this.templateEngine.compile(); - const { schemas } = await this.schemaParser.parse({ metadata }); - await this.artifactBuilder.build({ - schemas, - templates, - }); - } -} diff --git a/packages/build/src/lib/schema-parser/middleware/checkValidator.ts b/packages/build/src/lib/schema-parser/middleware/checkValidator.ts index 9ed02c07..7e5d569e 100644 --- a/packages/build/src/lib/schema-parser/middleware/checkValidator.ts +++ b/packages/build/src/lib/schema-parser/middleware/checkValidator.ts @@ -1,7 +1,6 @@ -import { ValidatorLoader } from '../schemaParser'; import { SchemaParserMiddleware } from './middleware'; import { chain } from 'lodash'; -import { APISchema } from '@vulcan/core'; +import { APISchema, ValidatorLoader } from '@vulcan/core'; export const checkValidator = (loader: ValidatorLoader): SchemaParserMiddleware => diff --git a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts index cd06e869..68f6fc43 100644 --- a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts +++ b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts @@ -2,16 +2,19 @@ import { SchemaFormat, SchemaData, SchemaReader } from './schemaReader'; import * as glob from 'glob'; import { promises as fs } from 'fs'; import * as path from 'path'; +import { inject, injectable } from 'inversify'; +import { TYPES } from '@vulcan/build/containers'; +import { SchemaParserOptions } from '@vulcan/build/options'; export interface FileSchemaReaderOptions { folderPath: string; } -export class FileSchemaReader extends SchemaReader { - private options: FileSchemaReaderOptions; +@injectable() +export class FileSchemaReader implements SchemaReader { + private options: SchemaParserOptions; - constructor(options: FileSchemaReaderOptions) { - super(); + constructor(@inject(TYPES.SchemaParserOptions) options: SchemaParserOptions) { this.options = options; } @@ -19,7 +22,7 @@ export class FileSchemaReader extends SchemaReader { const files = await this.getSchemaFilePaths(); for (const file of files) { - const fileName = path.relative(this.options.folderPath, file); + const fileName = path.relative(this.options.schemaPath, file); const { ext } = path.parse(fileName); const name = fileName.replace(new RegExp(`\\${ext}$`), ''); yield { @@ -33,7 +36,7 @@ export class FileSchemaReader extends SchemaReader { private async getSchemaFilePaths(): Promise { return new Promise((resolve, reject) => { glob( - path.resolve(this.options.folderPath, '**', '*.yaml'), + path.resolve(this.options.schemaPath, '**', '*.yaml'), { nodir: true }, (err, files) => { if (err) return reject(err); diff --git a/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts b/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts index bd2f1c9c..20d7fc24 100644 --- a/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts +++ b/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts @@ -8,6 +8,6 @@ export interface SchemaData { type: SchemaFormat; } -export abstract class SchemaReader { - abstract readSchema(): AsyncGenerator; +export interface SchemaReader { + readSchema(): AsyncGenerator; } diff --git a/packages/build/src/lib/schema-parser/schemaParser.ts b/packages/build/src/lib/schema-parser/schemaParser.ts index 18118b6d..e73932da 100644 --- a/packages/build/src/lib/schema-parser/schemaParser.ts +++ b/packages/build/src/lib/schema-parser/schemaParser.ts @@ -1,4 +1,9 @@ -import { APISchema, IValidator, TemplateMetadata } from '@vulcan/core'; +import { + APISchema, + TemplateMetadata, + TYPES as CORE_TYPES, + ValidatorLoader, +} from '@vulcan/core'; import { SchemaData, SchemaFormat, SchemaReader } from './schema-reader'; import * as yaml from 'js-yaml'; import { @@ -13,31 +18,27 @@ import { addMissingErrors, } from './middleware'; import * as compose from 'koa-compose'; - -/** - * Temporary interface - * @deprecated - */ -export interface ValidatorLoader { - getLoader(name: string): IValidator; -} +import { inject, injectable, interfaces } from 'inversify'; +import { TYPES } from '@vulcan/build/containers'; +import { SchemaParserOptions } from '@vulcan/build/options'; export interface SchemaParseResult { schemas: APISchema[]; } +@injectable() export class SchemaParser { private schemaReader: SchemaReader; private middleware: SchemaParserMiddleware[] = []; - constructor({ - schemaReader, - validatorLoader, - }: { - schemaReader: SchemaReader; - validatorLoader: ValidatorLoader; - }) { - this.schemaReader = schemaReader; + constructor( + @inject(TYPES.Factory_SchemaReader) + schemaReaderFactory: interfaces.AutoNamedFactory, + @inject(TYPES.SchemaParserOptions) schemaParserOptions: SchemaParserOptions, + @inject(CORE_TYPES.ValidatorLoader) validatorLoader: ValidatorLoader + ) { + this.schemaReader = schemaReaderFactory(schemaParserOptions.reader); + // Global middleware this.use(generateUrl()); this.use(generateTemplateSource()); diff --git a/packages/build/src/lib/vulcanBuilder.ts b/packages/build/src/lib/vulcanBuilder.ts new file mode 100644 index 00000000..1972de4d --- /dev/null +++ b/packages/build/src/lib/vulcanBuilder.ts @@ -0,0 +1,29 @@ +import { IBuildOptions } from '@vulcan/build/models'; +import { Container, TYPES } from '@vulcan/build/containers'; +import { SchemaParser } from '@vulcan/build/schema-parser'; +import { + TemplateEngine, + TYPES as CORE_TYPES, + VulcanArtifactBuilder, +} from '@vulcan/core'; + +export class VulcanBuilder { + public async build(options: IBuildOptions) { + const container = new Container(); + container.load(options); + const schemaParser = container.get(TYPES.SchemaParser); + const templateEngine = container.get( + CORE_TYPES.TemplateEngine + ); + const artifactBuilder = container.get( + CORE_TYPES.ArtifactBuilder + ); + + const { metadata, templates } = await templateEngine.compile(); + const { schemas } = await schemaParser.parse({ metadata }); + + await artifactBuilder.build({ schemas, templates }); + + container.unload(); + } +} diff --git a/packages/build/src/models/buildOptions.ts b/packages/build/src/models/buildOptions.ts new file mode 100644 index 00000000..745c551e --- /dev/null +++ b/packages/build/src/models/buildOptions.ts @@ -0,0 +1,6 @@ +import { ICoreOptions } from '@vulcan/core'; +import { ISchemaParserOptions } from './schemaParserOptions'; + +export interface IBuildOptions extends ICoreOptions { + schemaParser: ISchemaParserOptions; +} diff --git a/packages/build/src/models/index.ts b/packages/build/src/models/index.ts new file mode 100644 index 00000000..dddb9211 --- /dev/null +++ b/packages/build/src/models/index.ts @@ -0,0 +1,2 @@ +export * from './buildOptions'; +export * from './schemaParserOptions'; diff --git a/packages/build/src/models/schemaParserOptions.ts b/packages/build/src/models/schemaParserOptions.ts new file mode 100644 index 00000000..64186994 --- /dev/null +++ b/packages/build/src/models/schemaParserOptions.ts @@ -0,0 +1,8 @@ +export interface ISchemaParserOptions { + reader: SchemaReaderType; + schemaPath: string; +} + +export enum SchemaReaderType { + LocalFile = 'LocalFile', +} diff --git a/packages/build/src/options/index.ts b/packages/build/src/options/index.ts new file mode 100644 index 00000000..1084ca58 --- /dev/null +++ b/packages/build/src/options/index.ts @@ -0,0 +1 @@ +export * from './schemaParser'; diff --git a/packages/build/src/options/schemaParser.ts b/packages/build/src/options/schemaParser.ts new file mode 100644 index 00000000..423a4dfc --- /dev/null +++ b/packages/build/src/options/schemaParser.ts @@ -0,0 +1,17 @@ +import { injectable, inject, optional } from 'inversify'; +import { TYPES } from '@vulcan/build/containers'; +import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; + +@injectable() +export class SchemaParserOptions implements ISchemaParserOptions { + public readonly reader!: SchemaReaderType; + public readonly schemaPath!: string; + + constructor( + @inject(TYPES.SchemaParserInputOptions) + @optional() + options: Partial = {} + ) { + Object.assign(this, options); + } +} diff --git a/packages/build/test/pipeline/.gitignore b/packages/build/test/builder/.gitignore similarity index 100% rename from packages/build/test/pipeline/.gitignore rename to packages/build/test/builder/.gitignore diff --git a/packages/build/test/builder/builder.spec.ts b/packages/build/test/builder/builder.spec.ts new file mode 100644 index 00000000..a94b83a5 --- /dev/null +++ b/packages/build/test/builder/builder.spec.ts @@ -0,0 +1,31 @@ +import { VulcanBuilder } from '../../src'; +import * as path from 'path'; +import { IBuildOptions, SchemaReaderType } from '@vulcan/build/models'; +import { + PersistentStoreType, + SerializerType, + TemplateProviderType, +} from '@vulcan/core'; + +it('Builder.build should work', async () => { + // Arrange + const builder = new VulcanBuilder(); + const options: IBuildOptions = { + schemaParser: { + reader: SchemaReaderType.LocalFile, + schemaPath: path.resolve(__dirname, 'source'), + }, + artifact: { + storageType: PersistentStoreType.LocalFile, + serializerType: SerializerType.JSON, + path: path.resolve(__dirname, 'result.json'), + }, + template: { + provider: TemplateProviderType.LocalFile, + path: path.resolve(__dirname, 'source'), + }, + }; + + // Act, Assert + await expect(builder.build(options)).resolves.not.toThrow(); +}); diff --git a/packages/build/test/pipeline/source/detail/role.sql b/packages/build/test/builder/source/detail/role.sql similarity index 100% rename from packages/build/test/pipeline/source/detail/role.sql rename to packages/build/test/builder/source/detail/role.sql diff --git a/packages/build/test/pipeline/source/detail/role.yaml b/packages/build/test/builder/source/detail/role.yaml similarity index 100% rename from packages/build/test/pipeline/source/detail/role.yaml rename to packages/build/test/builder/source/detail/role.yaml diff --git a/packages/build/test/pipeline/source/user.sql b/packages/build/test/builder/source/user.sql similarity index 100% rename from packages/build/test/pipeline/source/user.sql rename to packages/build/test/builder/source/user.sql diff --git a/packages/build/test/pipeline/source/user.yaml b/packages/build/test/builder/source/user.yaml similarity index 100% rename from packages/build/test/pipeline/source/user.yaml rename to packages/build/test/builder/source/user.yaml diff --git a/packages/build/test/pipeline/pipeline.spec.ts b/packages/build/test/pipeline/pipeline.spec.ts deleted file mode 100644 index def3d385..00000000 --- a/packages/build/test/pipeline/pipeline.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BuildPipeline } from '../../src'; -import * as path from 'path'; -import { - LocalFilePersistentStore, - TemplateEngine, - VulcanArtifactBuilder, -} from '@vulcan/core'; - -it('Default pipeline should build artifacts correctly', async () => { - // Arrange - const pipeline = BuildPipeline.default({ - sourceFolderPath: path.resolve(__dirname, 'source'), - destinationFilePath: path.resolve(__dirname, 'result.json'), - }); - // Act, Assert - await expect(pipeline.build()).resolves.not.toThrow(); -}); - -// TODO: this test should be moved to serve package -// TODO: Wait for correct context format -it('Default pipeline should load the built artifacts correctly', async () => { - // Arrange - const pipeline = BuildPipeline.default({ - sourceFolderPath: path.resolve(__dirname, 'source'), - destinationFilePath: path.resolve(__dirname, 'result.json'), - }); - await pipeline.build(); - // Act, Assert - const ps = new LocalFilePersistentStore({ - filePath: path.resolve(__dirname, 'result.json'), - }); - const artifactBuilder = new VulcanArtifactBuilder({ persistentStore: ps }); - const { templates } = await artifactBuilder.load(); - const templateEngine = TemplateEngine.useDefaultLoader({ - compiledResult: { templates }, - }); - const query = await templateEngine.render('user', { - context: { params: { id: '7c245513-823e-4225-9833-b88c7652b996' } }, - }); - // Assert - expect(query).toBe( - `select * from public.user where id = '7c245513-823e-4225-9833-b88c7652b996';` - ); -}); diff --git a/packages/build/test/schema-parser/middleware/checkValidator.spec.ts b/packages/build/test/schema-parser/middleware/checkValidator.spec.ts index e9eb6024..67f07bd2 100644 --- a/packages/build/test/schema-parser/middleware/checkValidator.spec.ts +++ b/packages/build/test/schema-parser/middleware/checkValidator.spec.ts @@ -1,5 +1,6 @@ -import { RawAPISchema, ValidatorLoader } from '@schema-parser/.'; -import { checkValidator } from '@schema-parser/middleware/checkValidator'; +import { RawAPISchema } from '@vulcan/build/schema-parser'; +import { checkValidator } from '@vulcan/build/schema-parser/middleware/checkValidator'; +import { ValidatorLoader } from '@vulcan/core'; import * as sinon from 'ts-sinon'; it('Should pass if there is no error', async () => { diff --git a/packages/build/test/schema-parser/middleware/generateTemplateSource.spec.ts b/packages/build/test/schema-parser/middleware/generateTemplateSource.spec.ts index 6e1c4304..245c554b 100644 --- a/packages/build/test/schema-parser/middleware/generateTemplateSource.spec.ts +++ b/packages/build/test/schema-parser/middleware/generateTemplateSource.spec.ts @@ -1,5 +1,5 @@ -import { RawAPISchema } from '@schema-parser/.'; -import { generateTemplateSource } from '@schema-parser/middleware/generateTemplateSource'; +import { RawAPISchema } from '@vulcan/build/schema-parser/.'; +import { generateTemplateSource } from '@vulcan/build/schema-parser/middleware/generateTemplateSource'; it('Should keep templateSource in schema', async () => { // Arrange diff --git a/packages/build/test/schema-parser/middleware/generateUrl.spec.ts b/packages/build/test/schema-parser/middleware/generateUrl.spec.ts index eb5fefdb..1a84b397 100644 --- a/packages/build/test/schema-parser/middleware/generateUrl.spec.ts +++ b/packages/build/test/schema-parser/middleware/generateUrl.spec.ts @@ -1,5 +1,5 @@ -import { RawAPISchema } from '@schema-parser/.'; -import { generateUrl } from '@schema-parser/middleware/generateUrl'; +import { RawAPISchema } from '@vulcan/build/schema-parser/.'; +import { generateUrl } from '@vulcan/build/schema-parser/middleware/generateUrl'; it('Should keep url in schema', async () => { // Arrange diff --git a/packages/build/test/schema-parser/middleware/transformValidator.spec.ts b/packages/build/test/schema-parser/middleware/transformValidator.spec.ts index 56fc4e55..f6a6c58e 100644 --- a/packages/build/test/schema-parser/middleware/transformValidator.spec.ts +++ b/packages/build/test/schema-parser/middleware/transformValidator.spec.ts @@ -1,5 +1,5 @@ -import { RawAPISchema } from '@schema-parser/.'; -import { transformValidator } from '@schema-parser/middleware/transformValidator'; +import { RawAPISchema } from '@vulcan/build/schema-parser/.'; +import { transformValidator } from '@vulcan/build/schema-parser/middleware/transformValidator'; it('Should convert string validator to proper format', async () => { // Arrange diff --git a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts index 554580cd..b4223d7a 100644 --- a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts +++ b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts @@ -1,10 +1,34 @@ -import { FileSchemaReader, SchemaData } from '../../../src'; +import { FileSchemaReader, SchemaData } from '@vulcan/build/schema-parser'; import * as path from 'path'; +import { Container } from 'inversify'; +import { TYPES } from '@vulcan/build/containers'; +import { SchemaParserOptions } from '@vulcan/build/options'; +import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind>(TYPES.SchemaParserInputOptions) + .toConstantValue({ + schemaPath: path.resolve(__dirname, '../test-schema'), + reader: SchemaReaderType.LocalFile, + }); + container + .bind(TYPES.SchemaParserOptions) + .to(SchemaParserOptions) + .inSingletonScope(); + container.bind(TYPES.SchemaReader).to(FileSchemaReader).inSingletonScope(); +}); + +afterEach(() => { + container.unbindAll(); +}); it('File schema reader should provide correct files and contents', async () => { // Arrange - const filePath = path.resolve(__dirname, '../test-schema'); - const schemaReader = new FileSchemaReader({ folderPath: filePath }); + const schemaReader = container.get(TYPES.SchemaReader); const schemas: SchemaData[] = []; // Act diff --git a/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts b/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts index 46353bcf..fd2c3256 100644 --- a/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts +++ b/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts @@ -1,5 +1,30 @@ -import { FileSchemaReader } from '../../../src'; +import { FileSchemaReader } from '@vulcan/build/schema-parser'; import * as path from 'path'; +import { SchemaParserOptions } from '@vulcan/build/options'; +import { TYPES } from '@vulcan/build/containers'; +import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; +import { Container } from 'inversify'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind>(TYPES.SchemaParserInputOptions) + .toConstantValue({ + schemaPath: path.resolve(__dirname, '../test-schema'), + reader: SchemaReaderType.LocalFile, + }); + container + .bind(TYPES.SchemaParserOptions) + .to(SchemaParserOptions) + .inSingletonScope(); + container.bind(TYPES.SchemaReader).to(FileSchemaReader).inSingletonScope(); +}); + +afterEach(() => { + container.unbindAll(); +}); jest.mock('glob', () => { return ( @@ -13,8 +38,7 @@ jest.mock('glob', () => { it('File schema reader should throw error with file search errors', async () => { // Arrange - const filePath = path.resolve('.'); - const schemaReader = new FileSchemaReader({ folderPath: filePath }); + const schemaReader = container.get(TYPES.SchemaReader); // Act, Assert const iter = schemaReader.readSchema(); await expect(iter.next()).rejects.toThrow('mock error'); diff --git a/packages/build/test/schema-parser/schemaParser.spec.ts b/packages/build/test/schema-parser/schemaParser.spec.ts index 1e2cc3f9..7fdd6f78 100644 --- a/packages/build/test/schema-parser/schemaParser.spec.ts +++ b/packages/build/test/schema-parser/schemaParser.spec.ts @@ -1,14 +1,49 @@ +import { TYPES } from '@vulcan/build/containers'; +import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; +import { SchemaParserOptions } from '@vulcan/build/options'; import { SchemaFormat, SchemaParser, SchemaReader, - ValidatorLoader, -} from '../../src'; +} from '@vulcan/build/schema-parser'; +import { ValidatorLoader, TYPES as CORE_TYPES } from '@vulcan/core'; +import { Container } from 'inversify'; import * as sinon from 'ts-sinon'; +let container: Container; +let stubSchemaReader: sinon.StubbedInstance; +let stubValidatorLoader: sinon.StubbedInstance; + +beforeEach(() => { + container = new Container(); + stubSchemaReader = sinon.stubInterface(); + stubValidatorLoader = sinon.stubInterface(); + + container + .bind(TYPES.Factory_SchemaReader) + .toConstantValue(() => stubSchemaReader); + container + .bind>(TYPES.SchemaParserInputOptions) + .toConstantValue({ + schemaPath: '', + reader: SchemaReaderType.LocalFile, + }); + container + .bind(TYPES.SchemaParserOptions) + .to(SchemaParserOptions) + .inSingletonScope(); + container + .bind(CORE_TYPES.ValidatorLoader) + .toConstantValue(stubValidatorLoader); + container.bind(TYPES.SchemaParser).to(SchemaParser).inSingletonScope(); +}); + +afterEach(() => { + container.unbindAll(); +}); + it('Schema parser parse should return correct result', async () => { // Assert - const stubSchemaReader = sinon.stubInterface(); const generator = async function* () { yield { name: 'detail/role', @@ -24,16 +59,12 @@ request: }; }; stubSchemaReader.readSchema.returns(generator()); - const stubValidatorLoader = sinon.stubInterface(); stubValidatorLoader.getLoader.returns({ name: 'validator1', validateSchema: () => true, validateData: () => true, }); - const schemaParser = new SchemaParser({ - schemaReader: stubSchemaReader, - validatorLoader: stubValidatorLoader, - }); + const schemaParser = container.get(TYPES.SchemaParser); // Act const result = await schemaParser.parse(); @@ -45,7 +76,6 @@ request: it('Schema parser parse should throw with unsupported schema type', async () => { // Assert - const stubSchemaReader = sinon.stubInterface(); const generator = async function* () { yield { name: 'detail/role', @@ -54,11 +84,7 @@ it('Schema parser parse should throw with unsupported schema type', async () => }; }; stubSchemaReader.readSchema.returns(generator()); - const stubValidatorLoader = sinon.stubInterface(); - const schemaParser = new SchemaParser({ - schemaReader: stubSchemaReader, - validatorLoader: stubValidatorLoader, - }); + const schemaParser = container.get(TYPES.SchemaParser); // Act, Assert await expect(schemaParser.parse()).rejects.toThrow( diff --git a/packages/build/tsconfig.json b/packages/build/tsconfig.json index 099c4c05..a2cee4b6 100644 --- a/packages/build/tsconfig.json +++ b/packages/build/tsconfig.json @@ -7,11 +7,7 @@ "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "paths": { - "@vulcan/core": ["packages/core/src/index.ts"], - "@schema-parser/*": ["packages/build/src/lib/schema-parser/*"] - } + "noFallthroughCasesInSwitch": true }, "references": [ { diff --git a/packages/core/src/containers/container.ts b/packages/core/src/containers/container.ts index 78fb2ffa..e464c1d5 100644 --- a/packages/core/src/containers/container.ts +++ b/packages/core/src/containers/container.ts @@ -1,9 +1,10 @@ -import { IGlobalOptions } from '@models'; +import { ICoreOptions } from '@vulcan/core/models'; import { Container as InversifyContainer } from 'inversify'; import { artifactBuilderModule, executorModule, templateEngineModule, + validatorModule, } from './modules'; export class Container { @@ -13,9 +14,14 @@ export class Container { return this.inversifyContainer.get(type); } - public load(options: IGlobalOptions) { + public load(options: ICoreOptions) { this.inversifyContainer.load(artifactBuilderModule(options.artifact)); this.inversifyContainer.load(executorModule()); this.inversifyContainer.load(templateEngineModule(options.template)); + this.inversifyContainer.load(validatorModule()); + } + + public getInversifyContainer() { + return this.inversifyContainer; } } diff --git a/packages/core/src/containers/modules/artifactBuilder.ts b/packages/core/src/containers/modules/artifactBuilder.ts index 7e86b66b..060efe64 100644 --- a/packages/core/src/containers/modules/artifactBuilder.ts +++ b/packages/core/src/containers/modules/artifactBuilder.ts @@ -6,13 +6,13 @@ import { JSONSerializer, ArtifactBuilder, VulcanArtifactBuilder, -} from '@artifact-builder'; +} from '@vulcan/core/artifact-builder'; import { TYPES } from '../types'; import { SerializerType, PersistentStoreType, IArtifactBuilderOptions, -} from '@models'; +} from '@vulcan/core/models'; import { ArtifactBuilderOptions } from '../../options'; export const artifactBuilderModule = (options: IArtifactBuilderOptions) => diff --git a/packages/core/src/containers/modules/executor.ts b/packages/core/src/containers/modules/executor.ts index 30b1c9ac..0d0dfe90 100644 --- a/packages/core/src/containers/modules/executor.ts +++ b/packages/core/src/containers/modules/executor.ts @@ -1,5 +1,5 @@ import { ContainerModule } from 'inversify'; -import { Executor } from '@template-engine'; +import { Executor } from '@vulcan/core/template-engine'; import { TYPES } from '../types'; export const executorModule = () => diff --git a/packages/core/src/containers/modules/index.ts b/packages/core/src/containers/modules/index.ts index 5c33aeae..4d7f5884 100644 --- a/packages/core/src/containers/modules/index.ts +++ b/packages/core/src/containers/modules/index.ts @@ -1,3 +1,4 @@ export * from './artifactBuilder'; export * from './executor'; export * from './templateEngine'; +export * from './validator'; diff --git a/packages/core/src/containers/modules/templateEngine.ts b/packages/core/src/containers/modules/templateEngine.ts index 7d9ea788..d34871e9 100644 --- a/packages/core/src/containers/modules/templateEngine.ts +++ b/packages/core/src/containers/modules/templateEngine.ts @@ -1,5 +1,8 @@ -import { TYPES } from '@containers'; -import { ITemplateEngineOptions, TemplateProviderType } from '@models'; +import { TYPES } from '@vulcan/core/containers'; +import { + ITemplateEngineOptions, + TemplateProviderType, +} from '@vulcan/core/models'; import { ErrorExtension, FileTemplateProvider, @@ -11,7 +14,7 @@ import { NunjucksCompiler, Compiler, TemplateEngine, -} from '@template-engine'; +} from '@vulcan/core/template-engine'; import { ContainerModule, interfaces } from 'inversify'; import { TemplateEngineOptions } from '../../options'; import * as nunjucks from 'nunjucks'; diff --git a/packages/core/src/containers/modules/validator.ts b/packages/core/src/containers/modules/validator.ts new file mode 100644 index 00000000..2b1a7e2a --- /dev/null +++ b/packages/core/src/containers/modules/validator.ts @@ -0,0 +1,17 @@ +import { ContainerModule } from 'inversify'; +import { ValidatorLoader } from '../../validators/validatorLoader'; +import { TYPES } from '../types'; + +export const validatorModule = () => + new ContainerModule((bind) => { + bind(TYPES.ValidatorLoader).toConstantValue({ + // TODO: Mock value + getLoader: (name: string) => { + return { + name, + validateSchema: () => true, + validateData: () => true, + }; + }, + }); + }); diff --git a/packages/core/src/containers/types.ts b/packages/core/src/containers/types.ts index 777aa377..492f581b 100644 --- a/packages/core/src/containers/types.ts +++ b/packages/core/src/containers/types.ts @@ -18,4 +18,6 @@ export const TYPES = { TemplateEngineInputOptions: Symbol.for('TemplateEngineInputOptions'), // Executor Executor: Symbol.for('Executor'), + // Validator + ValidatorLoader: Symbol.for('ValidatorLoader'), }; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 56c81439..fd7e964f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,3 +2,4 @@ export * from './lib/template-engine'; export * from './models'; export * from './validators'; export * from './lib/artifact-builder'; +export * from './containers'; diff --git a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts index 5c669538..54fbf839 100644 --- a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts +++ b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts @@ -1,8 +1,8 @@ import { PersistentStore } from './persistentStore'; import { promises as fs } from 'fs'; import { injectable, inject } from 'inversify'; -import { TYPES } from '@containers'; -import { IArtifactBuilderOptions } from '@models'; +import { TYPES } from '@vulcan/core/containers'; +import { IArtifactBuilderOptions } from '@vulcan/core/models'; @injectable() export class LocalFilePersistentStore implements PersistentStore { diff --git a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts index 6a66c876..de158a1e 100644 --- a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts +++ b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts @@ -2,7 +2,7 @@ import { Artifact, ArtifactBuilder } from './artifactBuilder'; import { PersistentStore } from './persistent-stores'; import { Serializer } from './serializers'; import { inject, injectable, interfaces } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { IArtifactBuilderOptions } from '../../models/artifactBuilderOptions'; @injectable() diff --git a/packages/core/src/lib/template-engine/extensions/tags/req.ts b/packages/core/src/lib/template-engine/extensions/tags/req.ts index 0fdfc604..466f6a59 100644 --- a/packages/core/src/lib/template-engine/extensions/tags/req.ts +++ b/packages/core/src/lib/template-engine/extensions/tags/req.ts @@ -5,7 +5,7 @@ import { } from '../extension'; import * as nunjucks from 'nunjucks'; import { injectable, inject } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; // TODO: temporary interface export interface Executor { diff --git a/packages/core/src/lib/template-engine/nunjucksCompiler.ts b/packages/core/src/lib/template-engine/nunjucksCompiler.ts index 44bfef43..e41ccd93 100644 --- a/packages/core/src/lib/template-engine/nunjucksCompiler.ts +++ b/packages/core/src/lib/template-engine/nunjucksCompiler.ts @@ -11,7 +11,7 @@ import * as transformer from 'nunjucks/src/transformer'; import { walkAst } from './visitors/astWalker'; import { ParametersVisitor, ErrorsVisitor, FiltersVisitor } from './visitors'; import { inject, injectable, multiInject, optional } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; @injectable() export class NunjucksCompiler implements Compiler { diff --git a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts index 7de40942..fde8e243 100644 --- a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts +++ b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts @@ -3,8 +3,8 @@ import * as glob from 'glob'; import { promises as fs } from 'fs'; import * as path from 'path'; import { inject, injectable } from 'inversify'; -import { TYPES } from '@containers'; -import { ITemplateEngineOptions } from '@models'; +import { TYPES } from '@vulcan/core/containers'; +import { ITemplateEngineOptions } from '@vulcan/core/models'; @injectable() export class FileTemplateProvider implements TemplateProvider { diff --git a/packages/core/src/lib/template-engine/templateEngine.ts b/packages/core/src/lib/template-engine/templateEngine.ts index f6aa769f..eb6bbc78 100644 --- a/packages/core/src/lib/template-engine/templateEngine.ts +++ b/packages/core/src/lib/template-engine/templateEngine.ts @@ -1,7 +1,7 @@ import { Compiler, TemplateMetadata } from './compiler'; import { TemplateProvider } from './template-providers'; import { injectable, inject, interfaces } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { TemplateEngineOptions } from '../../options'; export type AllTemplateMetadata = Record; diff --git a/packages/core/src/models/globalOptions.ts b/packages/core/src/models/coreOptions.ts similarity index 86% rename from packages/core/src/models/globalOptions.ts rename to packages/core/src/models/coreOptions.ts index 7a767a28..861915f5 100644 --- a/packages/core/src/models/globalOptions.ts +++ b/packages/core/src/models/coreOptions.ts @@ -1,7 +1,7 @@ import { IArtifactBuilderOptions } from './artifactBuilderOptions'; import { ITemplateEngineOptions } from './templateEngineOptions'; -export interface IGlobalOptions { +export interface ICoreOptions { artifact: IArtifactBuilderOptions; template: ITemplateEngineOptions; } diff --git a/packages/core/src/models/index.ts b/packages/core/src/models/index.ts index 95f9e24d..689d071a 100644 --- a/packages/core/src/models/index.ts +++ b/packages/core/src/models/index.ts @@ -1,4 +1,4 @@ export * from './artifact'; export * from './artifactBuilderOptions'; -export * from './globalOptions'; +export * from './coreOptions'; export * from './templateEngineOptions'; diff --git a/packages/core/src/options/artifactBuilder.ts b/packages/core/src/options/artifactBuilder.ts index 334dd161..596e333a 100644 --- a/packages/core/src/options/artifactBuilder.ts +++ b/packages/core/src/options/artifactBuilder.ts @@ -1,10 +1,10 @@ import { injectable, inject } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { IArtifactBuilderOptions, PersistentStoreType, SerializerType, -} from '@models'; +} from '@vulcan/core/models'; @injectable() export class ArtifactBuilderOptions implements IArtifactBuilderOptions { diff --git a/packages/core/src/options/templateEngine.ts b/packages/core/src/options/templateEngine.ts index 2a461bed..25c03976 100644 --- a/packages/core/src/options/templateEngine.ts +++ b/packages/core/src/options/templateEngine.ts @@ -1,6 +1,9 @@ import { injectable, inject } from 'inversify'; -import { TYPES } from '@containers'; -import { ITemplateEngineOptions, TemplateProviderType } from '@models'; +import { TYPES } from '@vulcan/core/containers'; +import { + ITemplateEngineOptions, + TemplateProviderType, +} from '@vulcan/core/models'; @injectable() export class TemplateEngineOptions implements ITemplateEngineOptions { diff --git a/packages/core/src/validators/index.ts b/packages/core/src/validators/index.ts index fc141f79..535749a7 100644 --- a/packages/core/src/validators/index.ts +++ b/packages/core/src/validators/index.ts @@ -1 +1,2 @@ export * from './interface'; +export * from './validatorLoader'; diff --git a/packages/core/src/validators/validatorLoader.ts b/packages/core/src/validators/validatorLoader.ts new file mode 100644 index 00000000..a919add7 --- /dev/null +++ b/packages/core/src/validators/validatorLoader.ts @@ -0,0 +1,5 @@ +import { IValidator } from '.'; + +export interface ValidatorLoader { + getLoader(name: string): IValidator; +} diff --git a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts index c651fc79..8c22d289 100644 --- a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts +++ b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts @@ -1,6 +1,9 @@ import * as path from 'path'; -import { LocalFilePersistentStore, PersistentStore } from '@artifact-builder'; -import { TYPES } from '@containers'; +import { + LocalFilePersistentStore, + PersistentStore, +} from '@vulcan/core/artifact-builder'; +import { TYPES } from '@vulcan/core/containers'; import { Container } from 'inversify'; let container: Container; diff --git a/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts b/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts index f509aba5..2c22ecfe 100644 --- a/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts +++ b/packages/core/test/artifact-builder/vulcanArtifactBuilder.spec.ts @@ -3,9 +3,9 @@ import { JSONSerializer, LocalFilePersistentStore, VulcanArtifactBuilder, -} from '@artifact-builder'; +} from '@vulcan/core/artifact-builder'; import { Container } from 'inversify'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import * as sinon from 'ts-sinon'; let container: Container; diff --git a/packages/core/test/containers/continer.spec.ts b/packages/core/test/containers/continer.spec.ts index d729755c..07203c14 100644 --- a/packages/core/test/containers/continer.spec.ts +++ b/packages/core/test/containers/continer.spec.ts @@ -1,11 +1,11 @@ -import { ArtifactBuilder } from '@artifact-builder'; -import { Container, TYPES } from '@containers'; +import { ArtifactBuilder } from '@vulcan/core/artifact-builder'; +import { Container, TYPES } from '@vulcan/core/containers'; import { PersistentStoreType, SerializerType, TemplateProviderType, -} from '@models'; -import { TemplateEngine } from '@template-engine'; +} from '@vulcan/core/models'; +import { TemplateEngine } from '@vulcan/core/template-engine'; import * as path from 'path'; import * as fs from 'fs'; diff --git a/packages/core/test/template-engine/extensions/filters/unique.spec.ts b/packages/core/test/template-engine/extensions/filters/unique.spec.ts index 25b6a3db..38baec3e 100644 --- a/packages/core/test/template-engine/extensions/filters/unique.spec.ts +++ b/packages/core/test/template-engine/extensions/filters/unique.spec.ts @@ -1,10 +1,10 @@ -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { NunjucksCompiler, InMemoryCodeLoader, UniqueExtension, Compiler, -} from '@template-engine'; +} from '@vulcan/core/template-engine'; import { Container } from 'inversify'; let container: Container; diff --git a/packages/core/test/template-engine/extensions/tags/error.spec.ts b/packages/core/test/template-engine/extensions/tags/error.spec.ts index 069de795..8f2f30e3 100644 --- a/packages/core/test/template-engine/extensions/tags/error.spec.ts +++ b/packages/core/test/template-engine/extensions/tags/error.spec.ts @@ -1,10 +1,10 @@ -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { NunjucksCompiler, InMemoryCodeLoader, ErrorExtension, Compiler, -} from '@template-engine'; +} from '@vulcan/core/template-engine'; import { Container } from 'inversify'; let container: Container; diff --git a/packages/core/test/template-engine/extensions/tags/req.spec.ts b/packages/core/test/template-engine/extensions/tags/req.spec.ts index cb50d78f..0c71a0c0 100644 --- a/packages/core/test/template-engine/extensions/tags/req.spec.ts +++ b/packages/core/test/template-engine/extensions/tags/req.spec.ts @@ -1,11 +1,11 @@ -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { NunjucksCompiler, InMemoryCodeLoader, Executor, ReqExtension, Compiler, -} from '@template-engine'; +} from '@vulcan/core/template-engine'; import { Container } from 'inversify'; import * as sinon from 'ts-sinon'; diff --git a/packages/core/test/template-engine/inMemoryCodeLoader.spec.ts b/packages/core/test/template-engine/inMemoryCodeLoader.spec.ts index 0edb18dd..d1456e3f 100644 --- a/packages/core/test/template-engine/inMemoryCodeLoader.spec.ts +++ b/packages/core/test/template-engine/inMemoryCodeLoader.spec.ts @@ -1,4 +1,4 @@ -import { InMemoryCodeLoader } from '@template-engine'; +import { InMemoryCodeLoader } from '@vulcan/core/template-engine'; import * as nunjucks from 'nunjucks'; it('Should set/load compiled code correctly', async () => { diff --git a/packages/core/test/template-engine/nunjuckCompiler.spec.ts b/packages/core/test/template-engine/nunjuckCompiler.spec.ts index 4e1f716f..17591007 100644 --- a/packages/core/test/template-engine/nunjuckCompiler.spec.ts +++ b/packages/core/test/template-engine/nunjuckCompiler.spec.ts @@ -1,10 +1,10 @@ -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { NunjucksCompiler, InMemoryCodeLoader, NunjucksCompilerExtension, Compiler, -} from '@template-engine'; +} from '@vulcan/core/template-engine'; import { Container } from 'inversify'; let container: Container; diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts index c0eee3c0..6915a71e 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts @@ -1,6 +1,9 @@ -import { TYPES } from '@containers'; -import { ITemplateEngineOptions, TemplateProviderType } from '@models'; -import { FileTemplateProvider, Template } from '@template-engine'; +import { TYPES } from '@vulcan/core/containers'; +import { + ITemplateEngineOptions, + TemplateProviderType, +} from '@vulcan/core/models'; +import { FileTemplateProvider, Template } from '@vulcan/core/template-engine'; import { Container } from 'inversify'; import * as path from 'path'; diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts index 65163932..0d50944e 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts @@ -1,6 +1,9 @@ -import { TYPES } from '@containers'; -import { ITemplateEngineOptions, TemplateProviderType } from '@models'; -import { FileTemplateProvider } from '@template-engine'; +import { TYPES } from '@vulcan/core/containers'; +import { + ITemplateEngineOptions, + TemplateProviderType, +} from '@vulcan/core/models'; +import { FileTemplateProvider } from '@vulcan/core/template-engine'; import { Container } from 'inversify'; jest.mock('glob', () => { diff --git a/packages/core/test/template-engine/templateEngine.spec.ts b/packages/core/test/template-engine/templateEngine.spec.ts index 3d2a098f..5f0fd5b6 100644 --- a/packages/core/test/template-engine/templateEngine.spec.ts +++ b/packages/core/test/template-engine/templateEngine.spec.ts @@ -1,6 +1,10 @@ -import { TemplateEngine, Compiler, TemplateProvider } from '@template-engine'; +import { + TemplateEngine, + Compiler, + TemplateProvider, +} from '@vulcan/core/template-engine'; import * as sinon from 'ts-sinon'; -import { TYPES } from '@containers'; +import { TYPES } from '@vulcan/core/containers'; import { Container } from 'inversify'; let container: Container; diff --git a/packages/core/test/template-engine/visitors/astWalker.spec.ts b/packages/core/test/template-engine/visitors/astWalker.spec.ts index deb24505..2c2a9df7 100644 --- a/packages/core/test/template-engine/visitors/astWalker.spec.ts +++ b/packages/core/test/template-engine/visitors/astWalker.spec.ts @@ -1,4 +1,4 @@ -import { walkAst } from '@template-engine'; +import { walkAst } from '@vulcan/core/template-engine'; import * as nunjucks from 'nunjucks'; it('AST walker should traversal all nodes', async () => { diff --git a/packages/core/test/template-engine/visitors/errors.spec.ts b/packages/core/test/template-engine/visitors/errors.spec.ts index 32da25e9..a2c216bc 100644 --- a/packages/core/test/template-engine/visitors/errors.spec.ts +++ b/packages/core/test/template-engine/visitors/errors.spec.ts @@ -1,9 +1,9 @@ import * as nunjucks from 'nunjucks'; -import { walkAst, ErrorsVisitor } from '@template-engine'; +import { walkAst, ErrorsVisitor } from '@vulcan/core/template-engine'; import { ErrorExtension, NunjucksTagExtensionWrapper, -} from '@template-engine/extensions'; +} from '@vulcan/core/template-engine/extensions'; it('Visitor should return correct error list', async () => { // Arrange diff --git a/packages/core/test/template-engine/visitors/filter.spec.ts b/packages/core/test/template-engine/visitors/filter.spec.ts index 122bd4ca..483ee3de 100644 --- a/packages/core/test/template-engine/visitors/filter.spec.ts +++ b/packages/core/test/template-engine/visitors/filter.spec.ts @@ -1,5 +1,5 @@ import * as nunjucks from 'nunjucks'; -import { walkAst, FiltersVisitor } from '@template-engine'; +import { walkAst, FiltersVisitor } from '@vulcan/core/template-engine'; it('If we try to use an unloaded filter, visitor should throw error', async () => { // Arrange diff --git a/packages/core/test/template-engine/visitors/parameters.spec.ts b/packages/core/test/template-engine/visitors/parameters.spec.ts index 59a62d22..e8a23635 100644 --- a/packages/core/test/template-engine/visitors/parameters.spec.ts +++ b/packages/core/test/template-engine/visitors/parameters.spec.ts @@ -1,5 +1,5 @@ import * as nunjucks from 'nunjucks'; -import { walkAst, ParametersVisitor } from '@template-engine'; +import { walkAst, ParametersVisitor } from '@vulcan/core/template-engine'; it('Visitor should return correct parameter', async () => { // Arrange diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index ead942e1..da2e5228 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -8,15 +8,7 @@ "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "typeRoots": ["../../node_modules/@types"], - "paths": { - "@artifact-builder": ["packages/core/src/lib/artifact-builder/index"], - "@artifact-builder/*": ["packages/core/src/lib/artifact-builder/*"], - "@template-engine": ["packages/core/src/lib/template-engine/index"], - "@template-engine/*": ["packages/core/src/lib/template-engine/*"], - "@containers": ["packages/core/src/containers/index"], - "@models": ["packages/core/src/models/index"] - } + "typeRoots": ["../../node_modules/@types"] }, "references": [ { diff --git a/tsconfig.base.json b/tsconfig.base.json index d669804a..bbd60494 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -17,7 +17,30 @@ "types": ["reflect-metadata"], "paths": { "@vulcan/build": ["packages/build/src/index.ts"], - "@vulcan/core": ["packages/core/src/index.ts"] + "@vulcan/core": ["packages/core/src/index.ts"], + "@vulcan/core/artifact-builder": [ + "packages/core/src/lib/artifact-builder/index" + ], + "@vulcan/core/artifact-builder/*": [ + "packages/core/src/lib/artifact-builder/*" + ], + "@vulcan/core/template-engine": [ + "packages/core/src/lib/template-engine/index" + ], + "@vulcan/core/template-engine/*": [ + "packages/core/src/lib/template-engine/*" + ], + "@vulcan/core/containers": ["packages/core/src/containers/index"], + "@vulcan/core/models": ["packages/core/src/models/index"], + "@vulcan/build/schema-parser": [ + "packages/build/src/lib/schema-parser/index" + ], + "@vulcan/build/schema-parser/*": [ + "packages/build/src/lib/schema-parser/*" + ], + "@vulcan/build/models": ["packages/build/src/models/index"], + "@vulcan/build/containers": ["packages/build/src/containers/index"], + "@vulcan/build/options": ["packages/build/src/options/index"] } }, "exclude": ["node_modules", "tmp"] From def280cb93dcae53aad680616e26a31e4bb6aa22 Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Fri, 20 May 2022 11:21:17 +0800 Subject: [PATCH 4/8] refactor: unify option interface --- packages/build/test/builder/builder.spec.ts | 8 ++++---- .../persistent-stores/localFilePersistentStore.ts | 2 +- .../src/lib/artifact-builder/vulcanArtifactBuilder.ts | 4 ++-- .../template-providers/fileTemplateProvider.ts | 6 ++++-- packages/core/src/models/artifactBuilderOptions.ts | 6 +++--- packages/core/src/models/templateEngineOptions.ts | 2 +- packages/core/src/options/artifactBuilder.ts | 6 +++--- packages/core/src/options/templateEngine.ts | 2 +- .../persistent-stores/localFilePersistentStore.spec.ts | 2 +- packages/core/test/containers/continer.spec.ts | 8 ++++---- .../template-provider/fileTemplateProvider.spec.ts | 2 +- .../template-provider/fileTemplateProviderError.spec.ts | 2 +- 12 files changed, 26 insertions(+), 24 deletions(-) diff --git a/packages/build/test/builder/builder.spec.ts b/packages/build/test/builder/builder.spec.ts index a94b83a5..0adb036d 100644 --- a/packages/build/test/builder/builder.spec.ts +++ b/packages/build/test/builder/builder.spec.ts @@ -16,13 +16,13 @@ it('Builder.build should work', async () => { schemaPath: path.resolve(__dirname, 'source'), }, artifact: { - storageType: PersistentStoreType.LocalFile, - serializerType: SerializerType.JSON, - path: path.resolve(__dirname, 'result.json'), + provider: PersistentStoreType.LocalFile, + serializer: SerializerType.JSON, + filePath: path.resolve(__dirname, 'result.json'), }, template: { provider: TemplateProviderType.LocalFile, - path: path.resolve(__dirname, 'source'), + templatePath: path.resolve(__dirname, 'source'), }, }; diff --git a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts index 54fbf839..a999ec0a 100644 --- a/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts +++ b/packages/core/src/lib/artifact-builder/persistent-stores/localFilePersistentStore.ts @@ -11,7 +11,7 @@ export class LocalFilePersistentStore implements PersistentStore { constructor( @inject(TYPES.ArtifactBuilderOptions) options: IArtifactBuilderOptions ) { - this.filePath = options.path; + this.filePath = options.filePath; } public async save(data: Buffer): Promise { diff --git a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts index de158a1e..5c7c63d3 100644 --- a/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts +++ b/packages/core/src/lib/artifact-builder/vulcanArtifactBuilder.ts @@ -17,8 +17,8 @@ export class VulcanArtifactBuilder implements ArtifactBuilder { serializerFactory: interfaces.AutoNamedFactory>, @inject(TYPES.ArtifactBuilderOptions) options: IArtifactBuilderOptions ) { - this.serializer = serializerFactory(options.serializerType); - this.persistentStore = persistentStoreFactory(options.storageType); + this.serializer = serializerFactory(options.serializer); + this.persistentStore = persistentStoreFactory(options.provider); } public async build(artifact: Artifact): Promise { diff --git a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts index fde8e243..07a8dd71 100644 --- a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts +++ b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts @@ -21,7 +21,9 @@ export class FileTemplateProvider implements TemplateProvider { for (const file of files) { yield { - name: path.relative(this.options.path, file).replace(/\.sql$/, ''), + name: path + .relative(this.options.templatePath, file) + .replace(/\.sql$/, ''), statement: await fs.readFile(file, 'utf8'), }; } @@ -30,7 +32,7 @@ export class FileTemplateProvider implements TemplateProvider { private async getTemplateFilePaths(): Promise { return new Promise((resolve, reject) => { glob( - path.resolve(this.options.path, '**', '*.sql'), + path.resolve(this.options.templatePath, '**', '*.sql'), { nodir: true }, (err, files) => { if (err) return reject(err); diff --git a/packages/core/src/models/artifactBuilderOptions.ts b/packages/core/src/models/artifactBuilderOptions.ts index 11b5bf7b..470dc3a0 100644 --- a/packages/core/src/models/artifactBuilderOptions.ts +++ b/packages/core/src/models/artifactBuilderOptions.ts @@ -7,7 +7,7 @@ export enum SerializerType { } export interface IArtifactBuilderOptions { - storageType: PersistentStoreType; - path: string; - serializerType: SerializerType; + provider: PersistentStoreType; + serializer: SerializerType; + filePath: string; } diff --git a/packages/core/src/models/templateEngineOptions.ts b/packages/core/src/models/templateEngineOptions.ts index 1d5a8554..5dfaa93f 100644 --- a/packages/core/src/models/templateEngineOptions.ts +++ b/packages/core/src/models/templateEngineOptions.ts @@ -4,5 +4,5 @@ export enum TemplateProviderType { export interface ITemplateEngineOptions { provider: TemplateProviderType; - path: string; + templatePath: string; } diff --git a/packages/core/src/options/artifactBuilder.ts b/packages/core/src/options/artifactBuilder.ts index 596e333a..cdcd0086 100644 --- a/packages/core/src/options/artifactBuilder.ts +++ b/packages/core/src/options/artifactBuilder.ts @@ -8,9 +8,9 @@ import { @injectable() export class ArtifactBuilderOptions implements IArtifactBuilderOptions { - public readonly storageType!: PersistentStoreType; - public readonly serializerType!: SerializerType; - public readonly path!: string; + public readonly provider!: PersistentStoreType; + public readonly serializer!: SerializerType; + public readonly filePath!: string; constructor( @inject(TYPES.ArtifactBuilderInputOptions) diff --git a/packages/core/src/options/templateEngine.ts b/packages/core/src/options/templateEngine.ts index 25c03976..2d80fc1c 100644 --- a/packages/core/src/options/templateEngine.ts +++ b/packages/core/src/options/templateEngine.ts @@ -8,7 +8,7 @@ import { @injectable() export class TemplateEngineOptions implements ITemplateEngineOptions { public readonly provider!: TemplateProviderType; - public readonly path!: string; + public readonly templatePath!: string; constructor( @inject(TYPES.TemplateEngineInputOptions) diff --git a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts index 8c22d289..2b0cfc5c 100644 --- a/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts +++ b/packages/core/test/artifact-builder/persistent-stores/localFilePersistentStore.spec.ts @@ -12,7 +12,7 @@ beforeEach(() => { container = new Container(); container .bind(TYPES.ArtifactBuilderOptions) - .toConstantValue({ path: path.resolve(__dirname, 'test.json') }); + .toConstantValue({ filePath: path.resolve(__dirname, 'test.json') }); container .bind(TYPES.PersistentStore) .to(LocalFilePersistentStore) diff --git a/packages/core/test/containers/continer.spec.ts b/packages/core/test/containers/continer.spec.ts index 07203c14..6f818cf0 100644 --- a/packages/core/test/containers/continer.spec.ts +++ b/packages/core/test/containers/continer.spec.ts @@ -18,13 +18,13 @@ it('Container should load options and resolve all dependencies', async () => { const container = new Container(); container.load({ artifact: { - storageType: PersistentStoreType.LocalFile, - path: resultPath, - serializerType: SerializerType.JSON, + provider: PersistentStoreType.LocalFile, + filePath: resultPath, + serializer: SerializerType.JSON, }, template: { provider: TemplateProviderType.LocalFile, - path: path.resolve(__dirname, 'test-template'), + templatePath: path.resolve(__dirname, 'test-template'), }, }); // Act diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts index 6915a71e..541ef416 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts @@ -15,7 +15,7 @@ beforeEach(() => { .bind(TYPES.TemplateEngineOptions) .toConstantValue({ provider: TemplateProviderType.LocalFile, - path: path.resolve(__dirname, '../test-templates'), + templatePath: path.resolve(__dirname, '../test-templates'), }); container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); }); diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts index 0d50944e..41a25dc2 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts @@ -24,7 +24,7 @@ beforeEach(() => { .bind(TYPES.TemplateEngineOptions) .toConstantValue({ provider: TemplateProviderType.LocalFile, - path: '.', + templatePath: '.', }); container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); }); From 1c5e76ff194cc4ad465874fccc2ad3e983ca0847 Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Fri, 20 May 2022 12:08:23 +0800 Subject: [PATCH 5/8] feat: add class validator for all options --- package.json | 1 + packages/build/src/index.ts | 3 ++ packages/build/src/options/schemaParser.ts | 11 +++- .../test/options/schemaParserOptions.spec.ts | 44 +++++++++++++++ packages/core/src/options/artifactBuilder.ts | 20 +++++-- packages/core/src/options/templateEngine.ts | 17 ++++-- .../options/artifactBuilderOptions.spec.ts | 54 +++++++++++++++++++ .../options/templateEngineOptions.spec.ts | 48 +++++++++++++++++ yarn.lock | 18 +++++++ 9 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 packages/build/test/options/schemaParserOptions.spec.ts create mode 100644 packages/core/test/options/artifactBuilderOptions.spec.ts create mode 100644 packages/core/test/options/templateEngineOptions.spec.ts diff --git a/package.json b/package.json index cff69b4a..1dd214bf 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": {}, "private": true, "dependencies": { + "class-validator": "^0.13.2", "glob": "^8.0.1", "inversify": "^6.0.1", "js-yaml": "^4.1.0", diff --git a/packages/build/src/index.ts b/packages/build/src/index.ts index a9e794e3..88eaaa6f 100644 --- a/packages/build/src/index.ts +++ b/packages/build/src/index.ts @@ -1,2 +1,5 @@ export * from './lib/schema-parser'; export * from './lib/vulcanBuilder'; +export * from './containers'; +export * from './options'; +export * from './models'; diff --git a/packages/build/src/options/schemaParser.ts b/packages/build/src/options/schemaParser.ts index 423a4dfc..0536bedf 100644 --- a/packages/build/src/options/schemaParser.ts +++ b/packages/build/src/options/schemaParser.ts @@ -1,10 +1,15 @@ import { injectable, inject, optional } from 'inversify'; import { TYPES } from '@vulcan/build/containers'; import { ISchemaParserOptions, SchemaReaderType } from '@vulcan/build/models'; +import { IsOptional, IsString, validateSync } from 'class-validator'; @injectable() export class SchemaParserOptions implements ISchemaParserOptions { - public readonly reader!: SchemaReaderType; + @IsString() + public readonly reader: SchemaReaderType = SchemaReaderType.LocalFile; + + @IsString() + @IsOptional() public readonly schemaPath!: string; constructor( @@ -13,5 +18,9 @@ export class SchemaParserOptions implements ISchemaParserOptions { options: Partial = {} ) { Object.assign(this, options); + const errors = validateSync(this); + if (errors.length > 0) { + throw new Error('Invalid schema parser options: ' + errors.join(', ')); + } } } diff --git a/packages/build/test/options/schemaParserOptions.spec.ts b/packages/build/test/options/schemaParserOptions.spec.ts new file mode 100644 index 00000000..46775bb9 --- /dev/null +++ b/packages/build/test/options/schemaParserOptions.spec.ts @@ -0,0 +1,44 @@ +import { ISchemaParserOptions, SchemaReaderType, TYPES } from '../../src'; +import { Container } from 'inversify'; +import { SchemaParserOptions } from '../../src/options'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.SchemaParserOptions) + .to(SchemaParserOptions) + .inSingletonScope(); +}); + +it('Should provide correct default option values', async () => { + // Action + const options = container.get(TYPES.SchemaParserOptions); + // Assert + expect(options.reader).toBe(SchemaReaderType.LocalFile); +}); + +it('Can override some option properties', async () => { + // Arrange + container + .bind>(TYPES.SchemaParserInputOptions) + .toConstantValue({ + schemaPath: './test/schemas', + }); + const options = container.get(TYPES.SchemaParserOptions); + // Assert + expect(options.reader).toBe(SchemaReaderType.LocalFile); + expect(options.schemaPath).toBe('./test/schemas'); +}); + +it('Schema validation should work', async () => { + // Arrange + container.bind(TYPES.SchemaParserInputOptions).toConstantValue({ + reader: null, + }); + // Act. Assert + expect(() => + container.get(TYPES.SchemaParserOptions) + ).toThrow(); +}); diff --git a/packages/core/src/options/artifactBuilder.ts b/packages/core/src/options/artifactBuilder.ts index cdcd0086..ef5aa250 100644 --- a/packages/core/src/options/artifactBuilder.ts +++ b/packages/core/src/options/artifactBuilder.ts @@ -1,21 +1,33 @@ -import { injectable, inject } from 'inversify'; +import { injectable, inject, optional } from 'inversify'; import { TYPES } from '@vulcan/core/containers'; import { IArtifactBuilderOptions, PersistentStoreType, SerializerType, } from '@vulcan/core/models'; +import { IsString, validateSync, IsOptional } from 'class-validator'; @injectable() export class ArtifactBuilderOptions implements IArtifactBuilderOptions { - public readonly provider!: PersistentStoreType; - public readonly serializer!: SerializerType; + @IsString() + public readonly provider: PersistentStoreType = PersistentStoreType.LocalFile; + + @IsString() + public readonly serializer: SerializerType = SerializerType.JSON; + + @IsString() + @IsOptional() public readonly filePath!: string; constructor( @inject(TYPES.ArtifactBuilderInputOptions) - options: IArtifactBuilderOptions + @optional() + options: Partial = {} ) { Object.assign(this, options); + const errors = validateSync(this); + if (errors.length > 0) { + throw new Error('Invalid artifact builder options: ' + errors.join(', ')); + } } } diff --git a/packages/core/src/options/templateEngine.ts b/packages/core/src/options/templateEngine.ts index 2d80fc1c..6ef6f9ad 100644 --- a/packages/core/src/options/templateEngine.ts +++ b/packages/core/src/options/templateEngine.ts @@ -1,19 +1,30 @@ -import { injectable, inject } from 'inversify'; +import { injectable, inject, optional } from 'inversify'; import { TYPES } from '@vulcan/core/containers'; import { ITemplateEngineOptions, TemplateProviderType, } from '@vulcan/core/models'; +import { IsOptional, IsString, validateSync } from 'class-validator'; @injectable() export class TemplateEngineOptions implements ITemplateEngineOptions { - public readonly provider!: TemplateProviderType; + @IsString() + public readonly provider: TemplateProviderType = + TemplateProviderType.LocalFile; + + @IsString() + @IsOptional() public readonly templatePath!: string; constructor( @inject(TYPES.TemplateEngineInputOptions) - options: ITemplateEngineOptions + @optional() + options: Partial = {} ) { Object.assign(this, options); + const errors = validateSync(this); + if (errors.length > 0) { + throw new Error('Invalid template engine options: ' + errors.join(', ')); + } } } diff --git a/packages/core/test/options/artifactBuilderOptions.spec.ts b/packages/core/test/options/artifactBuilderOptions.spec.ts new file mode 100644 index 00000000..ceb18016 --- /dev/null +++ b/packages/core/test/options/artifactBuilderOptions.spec.ts @@ -0,0 +1,54 @@ +import { + IArtifactBuilderOptions, + PersistentStoreType, + SerializerType, + TYPES, +} from '../../src'; +import { Container } from 'inversify'; +import { ArtifactBuilderOptions } from '../../src/options'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.ArtifactBuilderOptions) + .to(ArtifactBuilderOptions) + .inSingletonScope(); +}); + +it('Should provide correct default option values', async () => { + // Action + const options = container.get( + TYPES.ArtifactBuilderOptions + ); + // Assert + expect(options.provider).toBe(PersistentStoreType.LocalFile); + expect(options.serializer).toBe(SerializerType.JSON); +}); + +it('Can override some option properties', async () => { + // Arrange + container + .bind>(TYPES.ArtifactBuilderInputOptions) + .toConstantValue({ + filePath: './result.json', + }); + const options = container.get( + TYPES.ArtifactBuilderOptions + ); + // Assert + expect(options.provider).toBe(PersistentStoreType.LocalFile); + expect(options.filePath).toBe('./result.json'); +}); + +it('Schema validation should work', async () => { + // Arrange + container.bind(TYPES.ArtifactBuilderInputOptions).toConstantValue({ + provider: null, + }); + // Act. Assert + expect(() => + container.get(TYPES.ArtifactBuilderOptions) + ).toThrow(); +}); diff --git a/packages/core/test/options/templateEngineOptions.spec.ts b/packages/core/test/options/templateEngineOptions.spec.ts new file mode 100644 index 00000000..afbc67ec --- /dev/null +++ b/packages/core/test/options/templateEngineOptions.spec.ts @@ -0,0 +1,48 @@ +import { ITemplateEngineOptions, TemplateProviderType, TYPES } from '../../src'; +import { Container } from 'inversify'; +import { TemplateEngineOptions } from '../../src/options'; + +let container: Container; + +beforeEach(() => { + container = new Container(); + container + .bind(TYPES.TemplateEngineOptions) + .to(TemplateEngineOptions) + .inSingletonScope(); +}); + +it('Should provide correct default option values', async () => { + // Action + const options = container.get( + TYPES.TemplateEngineOptions + ); + // Assert + expect(options.provider).toBe(TemplateProviderType.LocalFile); +}); + +it('Can override some option properties', async () => { + // Arrange + container + .bind>(TYPES.TemplateEngineInputOptions) + .toConstantValue({ + templatePath: './test/schemas', + }); + const options = container.get( + TYPES.TemplateEngineOptions + ); + // Assert + expect(options.provider).toBe(TemplateProviderType.LocalFile); + expect(options.templatePath).toBe('./test/schemas'); +}); + +it('Schema validation should work', async () => { + // Arrange + container.bind(TYPES.TemplateEngineInputOptions).toConstantValue({ + provider: null, + }); + // Act. Assert + expect(() => + container.get(TYPES.TemplateEngineOptions) + ).toThrow(); +}); diff --git a/yarn.lock b/yarn.lock index 4271771b..fa19e610 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1686,6 +1686,14 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== +class-validator@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.13.2.tgz#64b031e9f3f81a1e1dcd04a5d604734608b24143" + integrity sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw== + dependencies: + libphonenumber-js "^1.9.43" + validator "^13.7.0" + cli-cursor@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -3386,6 +3394,11 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libphonenumber-js@^1.9.43: + version "1.10.4" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.4.tgz#90397f0ed620262570a32244c9fbc389cc417ce4" + integrity sha512-9QWxEk4GW5RDnFzt8UtyRENfFpAN8u7Sbf9wf32tcXY9tdtnz1dKHIBwW2Wnfx8ypXJb9zUnTpK9aQJ/B8AlnA== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -4485,6 +4498,11 @@ v8-to-istanbul@^8.1.0: convert-source-map "^1.6.0" source-map "^0.7.3" +validator@^13.7.0: + version "13.7.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" + integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" From 29f4a2a46abe3d7279635c4bc93e1c5defcd4dc7 Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Thu, 30 Jun 2022 16:02:11 +0800 Subject: [PATCH 6/8] fix(build): update schema name properties and add some comments --- packages/build/src/lib/schema-parser/middleware/middleware.ts | 1 + .../src/lib/schema-parser/schema-reader/fileSchemaReader.ts | 4 ++-- .../build/src/lib/schema-parser/schema-reader/schemaReader.ts | 3 ++- packages/build/src/lib/schema-parser/schemaParser.ts | 2 +- .../test/schema-parser/schema-reader/fileSchemaReader.spec.ts | 4 ++-- packages/build/test/schema-parser/schemaParser.spec.ts | 4 ++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/build/src/lib/schema-parser/middleware/middleware.ts b/packages/build/src/lib/schema-parser/middleware/middleware.ts index 934b351c..08468dcb 100644 --- a/packages/build/src/lib/schema-parser/middleware/middleware.ts +++ b/packages/build/src/lib/schema-parser/middleware/middleware.ts @@ -7,6 +7,7 @@ export interface RawRequestParameter } export interface RawAPISchema extends DeepPartial> { + /** Indicate the identifier of this schema from the source, it might be uuid, file path, url ...etc, depend on the provider */ sourceName: string; request?: DeepPartial; } diff --git a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts index 68f6fc43..234a6215 100644 --- a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts +++ b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts @@ -24,9 +24,9 @@ export class FileSchemaReader implements SchemaReader { for (const file of files) { const fileName = path.relative(this.options.schemaPath, file); const { ext } = path.parse(fileName); - const name = fileName.replace(new RegExp(`\\${ext}$`), ''); + const sourceName = fileName.replace(new RegExp(`\\${ext}$`), ''); yield { - name, + sourceName, content: await fs.readFile(file, 'utf8'), type: SchemaFormat.YAML, }; diff --git a/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts b/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts index 20d7fc24..47b3704c 100644 --- a/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts +++ b/packages/build/src/lib/schema-parser/schema-reader/schemaReader.ts @@ -3,7 +3,8 @@ export enum SchemaFormat { } export interface SchemaData { - name: string; + /** The identifier of this schema, we might use this name to mapping SQL sources. */ + sourceName: string; content: string; type: SchemaFormat; } diff --git a/packages/build/src/lib/schema-parser/schemaParser.ts b/packages/build/src/lib/schema-parser/schemaParser.ts index e73932da..4cc6ccd3 100644 --- a/packages/build/src/lib/schema-parser/schemaParser.ts +++ b/packages/build/src/lib/schema-parser/schemaParser.ts @@ -77,7 +77,7 @@ export class SchemaParser { switch (schemaData.type) { case SchemaFormat.YAML: return { - sourceName: schemaData.name, + sourceName: schemaData.sourceName, ...(yaml.load(schemaData.content) as object), } as RawAPISchema; default: diff --git a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts index b4223d7a..b6acb98c 100644 --- a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts +++ b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts @@ -39,12 +39,12 @@ it('File schema reader should provide correct files and contents', async () => { // Assert expect(schemas.length).toBe(2); expect(schemas).toContainEqual({ - name: 'user', + sourceName: 'user', type: 'YAML', content: expect.stringContaining('url: /user/:id'), }); expect(schemas).toContainEqual({ - name: 'detail/role', + sourceName: 'detail/role', type: 'YAML', content: expect.stringContaining('url: /detail/role/:id'), }); diff --git a/packages/build/test/schema-parser/schemaParser.spec.ts b/packages/build/test/schema-parser/schemaParser.spec.ts index 7fdd6f78..157154a7 100644 --- a/packages/build/test/schema-parser/schemaParser.spec.ts +++ b/packages/build/test/schema-parser/schemaParser.spec.ts @@ -46,7 +46,7 @@ it('Schema parser parse should return correct result', async () => { // Assert const generator = async function* () { yield { - name: 'detail/role', + sourceName: 'detail/role', content: ` request: - fieldName: id @@ -78,7 +78,7 @@ it('Schema parser parse should throw with unsupported schema type', async () => // Assert const generator = async function* () { yield { - name: 'detail/role', + sourceName: 'detail/role', content: ``, type: 'unsupported' as SchemaFormat, }; From d1dd5542947527bc023a5f6992a5561d36aa93eb Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Thu, 30 Jun 2022 16:07:04 +0800 Subject: [PATCH 7/8] fix(build): rename the option property from schemaPath to folderPath --- .../src/lib/schema-parser/schema-reader/fileSchemaReader.ts | 4 ++-- packages/build/src/models/schemaParserOptions.ts | 2 +- packages/build/src/options/schemaParser.ts | 2 +- packages/build/test/builder/builder.spec.ts | 2 +- packages/build/test/options/schemaParserOptions.spec.ts | 4 ++-- .../test/schema-parser/schema-reader/fileSchemaReader.spec.ts | 2 +- .../schema-parser/schema-reader/fileSchemaReaderError.spec.ts | 2 +- packages/build/test/schema-parser/schemaParser.spec.ts | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts index 234a6215..00849138 100644 --- a/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts +++ b/packages/build/src/lib/schema-parser/schema-reader/fileSchemaReader.ts @@ -22,7 +22,7 @@ export class FileSchemaReader implements SchemaReader { const files = await this.getSchemaFilePaths(); for (const file of files) { - const fileName = path.relative(this.options.schemaPath, file); + const fileName = path.relative(this.options.folderPath, file); const { ext } = path.parse(fileName); const sourceName = fileName.replace(new RegExp(`\\${ext}$`), ''); yield { @@ -36,7 +36,7 @@ export class FileSchemaReader implements SchemaReader { private async getSchemaFilePaths(): Promise { return new Promise((resolve, reject) => { glob( - path.resolve(this.options.schemaPath, '**', '*.yaml'), + path.resolve(this.options.folderPath, '**', '*.yaml'), { nodir: true }, (err, files) => { if (err) return reject(err); diff --git a/packages/build/src/models/schemaParserOptions.ts b/packages/build/src/models/schemaParserOptions.ts index 64186994..a88c9d8f 100644 --- a/packages/build/src/models/schemaParserOptions.ts +++ b/packages/build/src/models/schemaParserOptions.ts @@ -1,6 +1,6 @@ export interface ISchemaParserOptions { reader: SchemaReaderType; - schemaPath: string; + folderPath: string; } export enum SchemaReaderType { diff --git a/packages/build/src/options/schemaParser.ts b/packages/build/src/options/schemaParser.ts index 0536bedf..ca1a4fe8 100644 --- a/packages/build/src/options/schemaParser.ts +++ b/packages/build/src/options/schemaParser.ts @@ -10,7 +10,7 @@ export class SchemaParserOptions implements ISchemaParserOptions { @IsString() @IsOptional() - public readonly schemaPath!: string; + public readonly folderPath!: string; constructor( @inject(TYPES.SchemaParserInputOptions) diff --git a/packages/build/test/builder/builder.spec.ts b/packages/build/test/builder/builder.spec.ts index 0adb036d..06d7e3b5 100644 --- a/packages/build/test/builder/builder.spec.ts +++ b/packages/build/test/builder/builder.spec.ts @@ -13,7 +13,7 @@ it('Builder.build should work', async () => { const options: IBuildOptions = { schemaParser: { reader: SchemaReaderType.LocalFile, - schemaPath: path.resolve(__dirname, 'source'), + folderPath: path.resolve(__dirname, 'source'), }, artifact: { provider: PersistentStoreType.LocalFile, diff --git a/packages/build/test/options/schemaParserOptions.spec.ts b/packages/build/test/options/schemaParserOptions.spec.ts index 46775bb9..8444f3b3 100644 --- a/packages/build/test/options/schemaParserOptions.spec.ts +++ b/packages/build/test/options/schemaParserOptions.spec.ts @@ -24,12 +24,12 @@ it('Can override some option properties', async () => { container .bind>(TYPES.SchemaParserInputOptions) .toConstantValue({ - schemaPath: './test/schemas', + folderPath: './test/schemas', }); const options = container.get(TYPES.SchemaParserOptions); // Assert expect(options.reader).toBe(SchemaReaderType.LocalFile); - expect(options.schemaPath).toBe('./test/schemas'); + expect(options.folderPath).toBe('./test/schemas'); }); it('Schema validation should work', async () => { diff --git a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts index b6acb98c..4f908ab2 100644 --- a/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts +++ b/packages/build/test/schema-parser/schema-reader/fileSchemaReader.spec.ts @@ -12,7 +12,7 @@ beforeEach(() => { container .bind>(TYPES.SchemaParserInputOptions) .toConstantValue({ - schemaPath: path.resolve(__dirname, '../test-schema'), + folderPath: path.resolve(__dirname, '../test-schema'), reader: SchemaReaderType.LocalFile, }); container diff --git a/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts b/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts index fd2c3256..593640f8 100644 --- a/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts +++ b/packages/build/test/schema-parser/schema-reader/fileSchemaReaderError.spec.ts @@ -12,7 +12,7 @@ beforeEach(() => { container .bind>(TYPES.SchemaParserInputOptions) .toConstantValue({ - schemaPath: path.resolve(__dirname, '../test-schema'), + folderPath: path.resolve(__dirname, '../test-schema'), reader: SchemaReaderType.LocalFile, }); container diff --git a/packages/build/test/schema-parser/schemaParser.spec.ts b/packages/build/test/schema-parser/schemaParser.spec.ts index 157154a7..83ce5d6a 100644 --- a/packages/build/test/schema-parser/schemaParser.spec.ts +++ b/packages/build/test/schema-parser/schemaParser.spec.ts @@ -25,7 +25,7 @@ beforeEach(() => { container .bind>(TYPES.SchemaParserInputOptions) .toConstantValue({ - schemaPath: '', + folderPath: '', reader: SchemaReaderType.LocalFile, }); container From 3e11bf958f50e5556512d06bc47fb31b212587bd Mon Sep 17 00:00:00 2001 From: Ivan Tsai Date: Thu, 30 Jun 2022 16:08:36 +0800 Subject: [PATCH 8/8] fix(core): rane the option property from templatePath to folderPath --- packages/build/test/builder/builder.spec.ts | 2 +- .../template-providers/fileTemplateProvider.ts | 4 ++-- packages/core/src/models/templateEngineOptions.ts | 2 +- packages/core/src/options/templateEngine.ts | 2 +- packages/core/test/containers/continer.spec.ts | 2 +- packages/core/test/options/templateEngineOptions.spec.ts | 4 ++-- .../template-provider/fileTemplateProvider.spec.ts | 2 +- .../template-provider/fileTemplateProviderError.spec.ts | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/build/test/builder/builder.spec.ts b/packages/build/test/builder/builder.spec.ts index 06d7e3b5..daeb17ac 100644 --- a/packages/build/test/builder/builder.spec.ts +++ b/packages/build/test/builder/builder.spec.ts @@ -22,7 +22,7 @@ it('Builder.build should work', async () => { }, template: { provider: TemplateProviderType.LocalFile, - templatePath: path.resolve(__dirname, 'source'), + folderPath: path.resolve(__dirname, 'source'), }, }; diff --git a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts index 07a8dd71..8c9a37fb 100644 --- a/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts +++ b/packages/core/src/lib/template-engine/template-providers/fileTemplateProvider.ts @@ -22,7 +22,7 @@ export class FileTemplateProvider implements TemplateProvider { for (const file of files) { yield { name: path - .relative(this.options.templatePath, file) + .relative(this.options.folderPath, file) .replace(/\.sql$/, ''), statement: await fs.readFile(file, 'utf8'), }; @@ -32,7 +32,7 @@ export class FileTemplateProvider implements TemplateProvider { private async getTemplateFilePaths(): Promise { return new Promise((resolve, reject) => { glob( - path.resolve(this.options.templatePath, '**', '*.sql'), + path.resolve(this.options.folderPath, '**', '*.sql'), { nodir: true }, (err, files) => { if (err) return reject(err); diff --git a/packages/core/src/models/templateEngineOptions.ts b/packages/core/src/models/templateEngineOptions.ts index 5dfaa93f..e4e9bd65 100644 --- a/packages/core/src/models/templateEngineOptions.ts +++ b/packages/core/src/models/templateEngineOptions.ts @@ -4,5 +4,5 @@ export enum TemplateProviderType { export interface ITemplateEngineOptions { provider: TemplateProviderType; - templatePath: string; + folderPath: string; } diff --git a/packages/core/src/options/templateEngine.ts b/packages/core/src/options/templateEngine.ts index 6ef6f9ad..70915586 100644 --- a/packages/core/src/options/templateEngine.ts +++ b/packages/core/src/options/templateEngine.ts @@ -14,7 +14,7 @@ export class TemplateEngineOptions implements ITemplateEngineOptions { @IsString() @IsOptional() - public readonly templatePath!: string; + public readonly folderPath!: string; constructor( @inject(TYPES.TemplateEngineInputOptions) diff --git a/packages/core/test/containers/continer.spec.ts b/packages/core/test/containers/continer.spec.ts index 6f818cf0..61e0f585 100644 --- a/packages/core/test/containers/continer.spec.ts +++ b/packages/core/test/containers/continer.spec.ts @@ -24,7 +24,7 @@ it('Container should load options and resolve all dependencies', async () => { }, template: { provider: TemplateProviderType.LocalFile, - templatePath: path.resolve(__dirname, 'test-template'), + folderPath: path.resolve(__dirname, 'test-template'), }, }); // Act diff --git a/packages/core/test/options/templateEngineOptions.spec.ts b/packages/core/test/options/templateEngineOptions.spec.ts index afbc67ec..b049d43d 100644 --- a/packages/core/test/options/templateEngineOptions.spec.ts +++ b/packages/core/test/options/templateEngineOptions.spec.ts @@ -26,14 +26,14 @@ it('Can override some option properties', async () => { container .bind>(TYPES.TemplateEngineInputOptions) .toConstantValue({ - templatePath: './test/schemas', + folderPath: './test/schemas', }); const options = container.get( TYPES.TemplateEngineOptions ); // Assert expect(options.provider).toBe(TemplateProviderType.LocalFile); - expect(options.templatePath).toBe('./test/schemas'); + expect(options.folderPath).toBe('./test/schemas'); }); it('Schema validation should work', async () => { diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts index 541ef416..9868dcd1 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProvider.spec.ts @@ -15,7 +15,7 @@ beforeEach(() => { .bind(TYPES.TemplateEngineOptions) .toConstantValue({ provider: TemplateProviderType.LocalFile, - templatePath: path.resolve(__dirname, '../test-templates'), + folderPath: path.resolve(__dirname, '../test-templates'), }); container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); }); diff --git a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts index 41a25dc2..c1b2a868 100644 --- a/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts +++ b/packages/core/test/template-engine/template-provider/fileTemplateProviderError.spec.ts @@ -24,7 +24,7 @@ beforeEach(() => { .bind(TYPES.TemplateEngineOptions) .toConstantValue({ provider: TemplateProviderType.LocalFile, - templatePath: '.', + folderPath: '.', }); container.bind(TYPES.TemplateProvider).to(FileTemplateProvider); });