From 1605493d6bcc775c4f004ce98f9220145e6694bc Mon Sep 17 00:00:00 2001 From: Claire Neveu Date: Wed, 24 Apr 2024 14:07:23 -0400 Subject: [PATCH] More pg boilerplate --- packages/sij-dialect-postgresql/package.json | 2 +- .../src/ast/schema-manipulation.ts | 2 +- .../src/builder/delete.ts | 18 +- .../src/builder/index.ts | 22 ++- .../src/builder/insert.ts | 42 ++++- .../src/builder/query.ts | 156 ++++++++---------- packages/sij-dialect-postgresql/tsconfig.json | 19 +++ 7 files changed, 164 insertions(+), 97 deletions(-) create mode 100644 packages/sij-dialect-postgresql/tsconfig.json diff --git a/packages/sij-dialect-postgresql/package.json b/packages/sij-dialect-postgresql/package.json index 1cd861a..43bcc54 100644 --- a/packages/sij-dialect-postgresql/package.json +++ b/packages/sij-dialect-postgresql/package.json @@ -9,7 +9,7 @@ }, "scripts": { "prepublish": "npm run build", - "build": "npx tsc && copyfiles -u 2 \"src/types/*.d.ts\" dist", + "build": "npx tsc", "format": "npx prettier . --write", "test": "ava -v && tsd", "docs": "npx typedoc src/ --out docs/ --includeDeclarations --excludeExternals --excludeNotExported --excludePrivate && touch docs/.nojekyll" diff --git a/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts b/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts index 26b79f4..a5338bf 100644 --- a/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts +++ b/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts @@ -821,7 +821,7 @@ interface SetColumnCompression extends Tagged< 'SetColumnCompression', { - readonly; + readonly method: Ident; } > {} const SetColumnCompression = (args: UnTag): SetColumnCompression => diff --git a/packages/sij-dialect-postgresql/src/builder/delete.ts b/packages/sij-dialect-postgresql/src/builder/delete.ts index ce86649..5982a17 100644 --- a/packages/sij-dialect-postgresql/src/builder/delete.ts +++ b/packages/sij-dialect-postgresql/src/builder/delete.ts @@ -3,6 +3,22 @@ import { PgExtension } from '../ast'; import { TableOf, TypedAst, UnQualifiedTable, WithAlias } from 'sij-core/util'; import { Expr } from 'sij-core/ast'; -class PgDeleteBuilder extends DeleteBuilder {} +class PgDeleteBuilder extends DeleteBuilder { + override lit( + l: Return, + ): TypedAst> { + return super.lit(l); + } + + override where( + clause: { [K in keyof Table]?: Table[K] } | TypedAst>, + ): PgDeleteBuilder { + return super.where(clause); + } +} +// Merges with above class to provide calling as a function +interface PgDeleteBuilder extends DeleteBuilder { + (fn: (arg: PgDeleteBuilder) => T): T; +} export { PgDeleteBuilder }; diff --git a/packages/sij-dialect-postgresql/src/builder/index.ts b/packages/sij-dialect-postgresql/src/builder/index.ts index 5979987..fc9f4f9 100644 --- a/packages/sij-dialect-postgresql/src/builder/index.ts +++ b/packages/sij-dialect-postgresql/src/builder/index.ts @@ -45,11 +45,21 @@ class PgBuilder extends CoreBuilder { override insertInto( table: TableName, ): PgInsertBuilder, number> { - return super.insertInto(table) as PgInsertBuilder, number> + return super.insertInto(table) as PgInsertBuilder< + Schema, + Schema[TableName] & QualifiedTable, + number + >; } - override update(table: TableName): PgUpdateBuilder, number> { - return super.update(table) as PgUpdateBuilder, number> + override update( + table: TableName, + ): PgUpdateBuilder, number> { + return super.update(table) as PgUpdateBuilder< + Schema, + Schema[TableName] & QualifiedTable, + number + >; } override deleteFrom(table: TableName) { @@ -61,11 +71,11 @@ class PgBuilder extends CoreBuilder { } override get schema(): PgSchemaBuilder { - return super.schema() as PgSchemaBuilder + return super.schema() as PgSchemaBuilder; } override get type(): PgTypeBuilder { - return super.type + return super.type; } override get constraint(): PgConstraintBuilder { @@ -77,4 +87,4 @@ class PgBuilder extends CoreBuilder { } } -export { PgBuilder } \ No newline at end of file +export { PgBuilder }; diff --git a/packages/sij-dialect-postgresql/src/builder/insert.ts b/packages/sij-dialect-postgresql/src/builder/insert.ts index a2bd865..618d603 100644 --- a/packages/sij-dialect-postgresql/src/builder/insert.ts +++ b/packages/sij-dialect-postgresql/src/builder/insert.ts @@ -1,8 +1,44 @@ -import { InsertBuilder } from 'sij-core'; +import { InsertBuilder, QueryBuilder } from 'sij-core'; import { PgExtension } from '../ast'; import { TableOf, TypedAst, UnQualifiedTable, WithAlias } from 'sij-core/util'; -import { Expr } from 'sij-core/ast'; +import { DefaultValue, Expr } from 'sij-core/ast'; -class PgInsertBuilder extends InsertBuilder {} +class PgInsertBuilder extends InsertBuilder { + override apply(fn: (arg: PgInsertBuilder) => T): T { + return fn(this); + } + + override lit( + l: Return, + ): TypedAst> { + return super.lit(l); + } + + override values( + ...vs: Array<{ [Key in keyof Table]?: Table[Key] | DefaultValue | TypedAst> }> + ): Omit, 'fromQuery' | 'columns'> { + return super.values(...vs); + } + + override values1( + ...vs: Array<{ [Key in keyof Table]?: Table[Key] | DefaultValue | TypedAst> }> + ): Omit, 'fromQuery' | 'columns'> { + return super.values1(...vs); + } + + override columns(...columns: Array): Omit, 'columns'> { + return super.columns(...columns); + } + + override fromQuery( + query: QueryBuilder, + ): Omit, 'values' | 'values1' | 'columns'> { + return super.fromQuery(query); + } +} +// Merges with above class to provide calling as a function +interface PgInsertBuilder extends InsertBuilder { + (fn: (arg: PgInsertBuilder) => T): T; +} export { PgInsertBuilder }; diff --git a/packages/sij-dialect-postgresql/src/builder/query.ts b/packages/sij-dialect-postgresql/src/builder/query.ts index 8145c0b..2392f1a 100644 --- a/packages/sij-dialect-postgresql/src/builder/query.ts +++ b/packages/sij-dialect-postgresql/src/builder/query.ts @@ -5,24 +5,24 @@ import { Expr, JoinKind } from 'sij-core/ast'; class PgQueryBuilder extends QueryBuilder { override selectAs< - Alias extends string, - Ret, - Id extends keyof Table & string, - Col extends Id | TypedAst>, ->( - alias: Alias, - col: Col, -): PgQueryBuilder< - Schema, - TableOf> & Table, - UnQualifiedTable>> & Return -> { - return super.selectAs(alias, col) as PgQueryBuilder< - Schema, - TableOf> & Table, - UnQualifiedTable>> & Return -> -} + Alias extends string, + Ret, + Id extends keyof Table & string, + Col extends Id | TypedAst>, + >( + alias: Alias, + col: Col, + ): PgQueryBuilder< + Schema, + TableOf> & Table, + UnQualifiedTable>> & Return + > { + return super.selectAs(alias, col) as PgQueryBuilder< + Schema, + TableOf> & Table, + UnQualifiedTable>> & Return + >; + } // We need to override all of the superclass methods with new return types to expose our added methods on the builder override select< Alias extends string, @@ -41,16 +41,12 @@ class PgQueryBuilder extends QueryBuilder( ...cols: Array>>> - ): PgQueryBuilder< - Schema, - { [K in Alias]: ColType } & Table, - UnQualifiedTable<{ [K in Alias]: ColType }> & Return - > { + ): PgQueryBuilder & Return> { return super.selectExpr(...cols) as PgQueryBuilder< - Schema, - { [K in Alias]: ColType } & Table, - UnQualifiedTable<{ [K in Alias]: ColType }> & Return - >; + Schema, + { [K in Alias]: ColType } & Table, + UnQualifiedTable<{ [K in Alias]: ColType }> & Return + >; } override join< @@ -66,7 +62,11 @@ class PgQueryBuilder extends QueryBuilder> >, ): PgQueryBuilder, Return> { - return super.join(kind, table, on) as PgQueryBuilder, Return> + return super.join(kind, table, on) as PgQueryBuilder< + Schema, + Table & MakeJoinTable, + Return + >; } override leftJoin< @@ -84,7 +84,7 @@ class PgQueryBuilder extends QueryBuilder, Return>; } - rightJoin< + override rightJoin< TableName extends keyof Schema & string, Alias extends string, SubTable, @@ -96,10 +96,14 @@ class PgQueryBuilder extends QueryBuilder> >, ): PgQueryBuilder, Return> { - return super.rightJoin(table, on) as PgQueryBuilder, Return> + return super.rightJoin(table, on) as PgQueryBuilder< + Schema, + Table & MakeJoinTable, + Return + >; } - fullOuterJoin< + override fullOuterJoin< TableName extends keyof Schema & string, Alias extends string, SubTable, @@ -111,10 +115,14 @@ class PgQueryBuilder extends QueryBuilder> >, ): PgQueryBuilder, Return> { - return super.fullOuterJoin(table, on) as PgQueryBuilder, Return>; + return super.fullOuterJoin(table, on) as PgQueryBuilder< + Schema, + Table & MakeJoinTable, + Return + >; } - innerJoin< + override innerJoin< TableName extends keyof Schema & string, Alias extends string, SubTable, @@ -126,65 +134,63 @@ class PgQueryBuilder extends QueryBuilder> >, ): PgQueryBuilder, Return> { - return super.innerJoin(table, on) as PgQueryBuilder, Return> + return super.innerJoin(table, on) as PgQueryBuilder< + Schema, + Table & MakeJoinTable, + Return + >; } - with( + override with( alias: TableName, sub: QueryBuilder, ): PgQueryBuilder as `${TableName}.${K}`]: Table2[K] }, Return> { - return super.with(alias, sub) as PgQueryBuilder as `${TableName}.${K}`]: Table2[K] }, Return>; + return super.with(alias, sub) as PgQueryBuilder< + Schema, + Table & { [K in StringKeys as `${TableName}.${K}`]: Table2[K] }, + Return + >; } - orderBy, Col extends Id | Exp>( + override orderBy, Col extends Id | Exp>( col: Col, opts?: { order?: 'ASC' | 'DESC'; nullHandling?: 'NULLS FIRST' | 'NULLS LAST' }, ): PgQueryBuilder { return super.orderBy(col, opts) as PgQueryBuilder; } - orderByAsc, Col extends Id | Exp>( + override orderByAsc, Col extends Id | Exp>( col: Col, opts?: { nullHandling?: 'NULLS FIRST' | 'NULLS LAST' }, ): PgQueryBuilder { - return super.orderByAsc(col, opts) as PgQueryBuilder + return super.orderByAsc(col, opts) as PgQueryBuilder; } - orderByDesc, Col extends Id | Exp>( + override orderByDesc, Col extends Id | Exp>( col: Col, opts?: { nullHandling?: 'NULLS FIRST' | 'NULLS LAST' }, ): PgQueryBuilder { - return super.orderByDesc(col, opts) as PgQueryBuilder + return super.orderByDesc(col, opts) as PgQueryBuilder; } - limit(expr: Expr | number): PgQueryBuilder { - return super.limit(expr) as PgQueryBuilder + override limit(expr: Expr | number): PgQueryBuilder { + return super.limit(expr) as PgQueryBuilder; } - offset(expr: Expr | number): PgQueryBuilder { - return super.offset(expr) as PgQueryBuilder + override offset(expr: Expr | number): PgQueryBuilder { + return super.offset(expr) as PgQueryBuilder; } - where( + override where( clause: { [K in keyof Table]?: Table[K] } | TypedAst>, ): PgQueryBuilder { return super.where(clause) as PgQueryBuilder; } - groupBy, Col extends Id | Exp>( + override groupBy, Col extends Id | Exp>( ...cols: Array - ): QueryBuilder { - const makeColumn = (col: Col): Expr => { - if (typeof col === 'object') { - return col as Expr; - } - return Ident(col); - }; - const columns = cols.map(makeColumn); - return new (this.constructor as typeof QueryBuilder)( - lens>().selection.groupBy.set(e => [...e, ...columns])(this._statement), - this.fn as any, - ); + ): PgQueryBuilder { + return super.groupBy(...cols) as PgQueryBuilder; } /** @@ -192,30 +198,10 @@ class PgQueryBuilder extends QueryBuilder>, - ): QueryBuilder { - const expr: Expr = (() => { - if (typeof clause === 'object' && !('ast' in clause)) { - return Object.keys(clause) - .map(k => { - const val: any = (clause as any)[k] as any; - return this.fn.eq(k as any, ast>(makeLit(val))); - }) - .reduce((acc, val) => this.fn.and(acc, val)).ast; - } - return clause.ast; - })(); - const updateHaving = (old: Expr | null): Expr => { - if (old === null) { - return expr; - } - return this.fn.and(ast>(old), ast>(expr)).ast; - }; - return new (this.constructor as typeof QueryBuilder)( - lens>().selection.having.set(e => updateHaving(e))(this._statement), - this.fn as any, - ); + override having( + clause: { [K in keyof Table]?: Table[K] } | TypedAst>, + ): PgQueryBuilder { + return super.groupBy(clause as any) as PgQueryBuilder; } /** @@ -224,12 +210,12 @@ class PgQueryBuilder extends QueryBuilder { + unTyped(): PgQueryBuilder { return this; } get foo() { - return 5 + return 5; } } diff --git a/packages/sij-dialect-postgresql/tsconfig.json b/packages/sij-dialect-postgresql/tsconfig.json new file mode 100644 index 0000000..fabf6c5 --- /dev/null +++ b/packages/sij-dialect-postgresql/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "allowJs": true, + "target": "es6", + "alwaysStrict": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strict": true, + "esModuleInterop": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noUnusedLocals": false, + "module": "CommonJS", + "declaration": true, + "noErrorTruncation": true + }, + "include": ["./src/**/*"] +}