Skip to content

Commit

Permalink
refactor: streamline raw query handling and enhance type definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
zfben committed Feb 9, 2025
1 parent 4056c2c commit bdc743b
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/__tests__/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('client', () => {

it('string with type cast', async () => {
expect(
await client.raw('SELECT ?::integer + ?::integer', [1, 1])
await client.raw('SELECT ?::integer + ?::integer', 1, 1)
).toEqual([{ '?column?': 2 }])
})

Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type User = {
name: string
metadata: {
age: number
gender: string
gender?: string
}
}

Expand Down Expand Up @@ -43,7 +43,7 @@ describe('types', () => {
it('ColumnValue', () => {
expectTypeOf<ColumnValue<'query', 'id'>>().toEqualTypeOf<number>()
expectTypeOf<ColumnValue<'query', 'name'>>().toEqualTypeOf<string>()
expectTypeOf<ColumnValue<'query', 'metadata'>>().toEqualTypeOf<{ age: number, gender: string }>()
expectTypeOf<ColumnValue<'query', 'metadata'>>().toEqualTypeOf<{ age: number, gender?: string }>()
expectTypeOf<ColumnValue<'query'>>().toEqualTypeOf<any>()
expectTypeOf<ColumnValue>().toEqualTypeOf<any>()
})
Expand Down
25 changes: 4 additions & 21 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import type { Sql } from 'postgres'
import type { TableName } from './types'
import { QueryBuilder } from './query-builder'

function isTemplateStringsArray(value: any): value is TemplateStringsArray {
return Array.isArray(value) && typeof value[0] === 'string' && 'raw' in value
}
import { createTemplateStringsArray } from './utils'

export class Client {
readonly postgres: Sql
Expand All @@ -18,7 +15,7 @@ export class Client {
}

async transaction<T>(fn: (client: Client) => Promise<T>) {
return this.postgres.begin(async (sql) => {
return this.postgres.begin(async sql => {
const client = new Client(sql)
return fn(client)
})
Expand All @@ -28,23 +25,9 @@ export class Client {
query: string | TemplateStringsArray,
...params: any[]
): Promise<T[]> {
if (isTemplateStringsArray(query)) {
return this.postgres.call(
this.postgres,
query,
...params
) as unknown as Promise<T[]>
}

const paramsArray =
params.length === 1 && Array.isArray(params[0]) ? params[0] : params

let paramIndex = 0
const text = (query as string).replace(/\?/g, () => `$${++paramIndex}`)

console.log('raw', text, paramsArray)
const templateStringsArray = createTemplateStringsArray(query)

return this.postgres.unsafe(text, paramsArray) as Promise<T[]>
return this.postgres<T[]>(templateStringsArray, ...params)
}

async quit() {
Expand Down
14 changes: 7 additions & 7 deletions src/query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,15 @@ export class QueryBuilder<
): Promise<TResult1 | TResult2> {
const { sql, params } = this.toSql()

return this.client.raw(sql, params).then(onfulfilled as any, onrejected)
return this.client.raw(sql, ...params).then(onfulfilled as any, onrejected)
}

async first(): Promise<(TResult extends (infer U)[] ? U : TResult) | null> {
this.limit(1)

const { sql, params } = this.toSql()

return this.client.raw(sql, params).then(rows => rows[0])
return this.client.raw(sql, ...params).then(rows => rows[0])
}

async count() {
Expand All @@ -293,7 +293,7 @@ export class QueryBuilder<
sql.push(whereSql)
params.push(...whereParams)

const result = await this.client.raw(sql.join(' '), params)
const result = await this.client.raw(sql.join(' '), ...params)

return Number.parseInt(result[0].count, 10)
}
Expand All @@ -304,7 +304,7 @@ export class QueryBuilder<
this.selectColumns = [column]

const { sql, params } = this.toSql()
const result = await this.client.raw(sql, params)
const result = await this.client.raw(sql, ...params)

return result.map((row: any) => row[column])
}
Expand Down Expand Up @@ -339,7 +339,7 @@ export class QueryBuilder<
.join(',')
)

return this.client.raw(sql.join(' '), Object.values(values)) as any
return this.client.raw(sql.join(' '), ...Object.values(values)) as any
}

async update<Returning extends (keyof TableType<T>)[] | ['*']>(
Expand Down Expand Up @@ -379,7 +379,7 @@ export class QueryBuilder<
.join(',')
)

return this.client.raw(sql.join(' '), params) as any
return this.client.raw(sql.join(' '), ...params) as any
}

async delete() {
Expand All @@ -392,6 +392,6 @@ export class QueryBuilder<

sql.push(whereSql)

return this.client.raw(sql.join(' '), whereParams)
return this.client.raw(sql.join(' '), ...whereParams)
}
}
14 changes: 11 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,19 @@ export function escapeValue(value: any): string {
throw Error(`Unsupported value: ${value}`)
}

export function createTemplateStringsArray(str: string): TemplateStringsArray {
const arr = [str]
export function isTemplateStringsArray(value: any): value is TemplateStringsArray {
return Array.isArray(value) && typeof value[0] === 'string' && 'raw' in value
}

export function createTemplateStringsArray(str: string | TemplateStringsArray): TemplateStringsArray {
if (isTemplateStringsArray(str)) return str

const parts = str.split(/\?/g)

const arr = [...parts]

Object.defineProperty(arr, "raw", {
value: Object.freeze([str])
value: Object.freeze([...parts])
})

return Object.freeze(arr) as TemplateStringsArray
Expand Down

0 comments on commit bdc743b

Please sign in to comment.