From 57e05d29e79615a7e8f80cc679b2acc1413a92cd Mon Sep 17 00:00:00 2001 From: Christopher Best Date: Wed, 25 Jan 2023 22:02:01 -0500 Subject: [PATCH] feat: generate info object for clients to pass as the DBDataSource type parameter --- src/generator/Generator.ts | 29 ++++++++ src/generator/__tests__/Generator.test.ts | 6 ++ src/generator/__tests__/integration.test.ts | 1 + src/generator/builders/InfoBuilder.ts | 82 +++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 src/generator/builders/InfoBuilder.ts diff --git a/src/generator/Generator.ts b/src/generator/Generator.ts index bf7b431..859579e 100644 --- a/src/generator/Generator.ts +++ b/src/generator/Generator.ts @@ -25,6 +25,7 @@ import { CaseFunction, Transformations } from './types' import UtilityTypesBuilder from './builders/UtilityTypesBuilder' import ZodSchemaBuilder from './builders/ZodSchemaBuilder' import SingleNamedImportBuilder from './builders/SingleNamedImportBuilder' +import InfoBuilder from './builders/InfoBuilder' import UpdateSchemaBuilder from './builders/UpdateSchemaBuilder' export interface GeneratorOptions { @@ -33,6 +34,7 @@ export interface GeneratorOptions { genInsertSchemas?: boolean genUpdateSchemas?: boolean genTableMetadata?: boolean + genInfos?: boolean disableEslint?: boolean /** @deprecated */ genEnums?: boolean @@ -61,6 +63,7 @@ export default class Generator { insertSchemas: boolean updateSchemas: boolean tableMetadata: boolean + infos: boolean disableEslint: boolean /** @deprecated */ enums: boolean @@ -82,6 +85,7 @@ export default class Generator { genInsertSchemas: insertSchemas = true, genUpdateSchemas: updateSchemas = true, genTableMetadata: tableMetadata = true, + genInfos: infos = true, disableEslint = true, genEnums = false, genInsertTypes = false, @@ -92,6 +96,17 @@ export default class Generator { transformEnumMembers = 'pascal', transformTypeNames = 'pascal', }: GeneratorOptions) { + if ( + infos && + (!selectSchemas || !insertSchemas || !updateSchemas || !tableMetadata) + ) { + const message = + 'Cannot generate Info without insert, select, and update schemas \ + and table metadata' + console.error(message) + throw new Error(message) + } + this.printer = createPrinter({ newLine: NewLineKind.LineFeed, removeComments: false, @@ -105,6 +120,7 @@ export default class Generator { insertSchemas, updateSchemas, tableMetadata, + infos, disableEslint, enums: genEnums, insertTypes: genInsertTypes, @@ -245,6 +261,19 @@ export default class Generator { builders.push(builder) } + if (this.generate.infos) { + const builder = new InfoBuilder( + tableInfo, + this.types, + this.transform, + new InsertSchemaBuilder(tableInfo, this.types, this.transform), + new SelectSchemaBuilder(tableInfo, this.types, this.transform), + new UpdateSchemaBuilder(tableInfo, this.types, this.transform), + new TableMetadataBuilder(tableInfo, this.types, this.transform) + ) + builders.push(builder) + } + if (this.generate.tables) { const builder = new TableBuilder(tableInfo, this.types, this.transform) this.types.add(builder.name, builder.typename().text, 'table') diff --git a/src/generator/__tests__/Generator.test.ts b/src/generator/__tests__/Generator.test.ts index 375c317..1df15a7 100644 --- a/src/generator/__tests__/Generator.test.ts +++ b/src/generator/__tests__/Generator.test.ts @@ -44,6 +44,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: false, genInsertTypes: false, genTables: false, @@ -63,6 +64,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: false, genInsertTypes: false, genTables: true, @@ -83,6 +85,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: true, genInsertTypes: false, genTables: false, @@ -102,6 +105,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: false, genInsertTypes: true, genTables: false, @@ -122,6 +126,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: false, genInsertTypes: false, genTables: false, @@ -142,6 +147,7 @@ describe(Generator, () => { genSelectSchemas: false, genInsertSchemas: false, genUpdateSchemas: false, + genInfos: false, genEnums: false, genInsertTypes: false, genTables: false, diff --git a/src/generator/__tests__/integration.test.ts b/src/generator/__tests__/integration.test.ts index 70a8c71..02fcfb6 100644 --- a/src/generator/__tests__/integration.test.ts +++ b/src/generator/__tests__/integration.test.ts @@ -77,6 +77,7 @@ beforeEach(() => { genInsertSchemas: true, genSelectSchemas: true, genUpdateSchemas: true, + genInfos: true, genTableMetadata: true, genEnums: true, genInsertTypes: true, diff --git a/src/generator/builders/InfoBuilder.ts b/src/generator/builders/InfoBuilder.ts new file mode 100644 index 0000000..107becd --- /dev/null +++ b/src/generator/builders/InfoBuilder.ts @@ -0,0 +1,82 @@ +import { + factory, + VariableStatement, + NodeFlags, + ObjectLiteralExpression, +} from 'typescript' +import { z } from 'zod' +import { TableInfoWithColumns, TypeRegistry } from '../database' +import { Transformations } from '../types' +import InsertSchemaBuilder from './InsertSchemaBuilder' +import { ExportKeyword } from './NodeBuilder' +import SelectSchemaBuilder from './SelectSchemaBuilder' +import TableMetadataBuilder from './TableMetadataBuilder' + +import TypeBuilder from './TypeBuilder' +import UpdateSchemaBuilder from './UpdateSchemaBuilder' + +export default class InfoBuilder extends TypeBuilder { + constructor( + options: z.infer, + protected types: TypeRegistry, + transform: Transformations, + private readonly insertSchemaBuilder: InsertSchemaBuilder, + private readonly selectSchemaBuilder: SelectSchemaBuilder, + private readonly updateSchemaBuilder: UpdateSchemaBuilder, + private readonly tableMetadataBuilder: TableMetadataBuilder + ) { + super(options.name, types, transform) + } + + public buildNode(): VariableStatement { + const declaration = factory.createVariableDeclaration( + `${this.typename().text}Info`, + undefined, + undefined, + this.buildInfoDefinition() + ) + + const declarationList = factory.createVariableDeclarationList( + [declaration], + NodeFlags.Const + ) + + return factory.createVariableStatement([ExportKeyword], declarationList) + } + + protected buildInfoDefinition(): ObjectLiteralExpression { + return factory.createObjectLiteralExpression( + [ + factory.createPropertyAssignment( + this.createIdentifier('metadata'), + this.tableMetadataBuilder.typename() + ), + factory.createPropertyAssignment( + factory.createIdentifier('name'), + factory.createStringLiteral(this.name) + ), + factory.createPropertyAssignment( + factory.createIdentifier('schemas'), + factory.createObjectLiteralExpression( + [ + factory.createPropertyAssignment( + this.createIdentifier('insert'), + this.insertSchemaBuilder.typename() + ), + factory.createPropertyAssignment( + this.createIdentifier('select'), + this.selectSchemaBuilder.typename() + ), + factory.createPropertyAssignment( + this.createIdentifier('update'), + this.updateSchemaBuilder.typename() + ), + ], + true + ) + ), + ], + true + ) + } +}