🌳
pt0/serverF/dbF/doKnexConnF.mts
1import knex, { type Knex } from 'knex'
2import * as _ from 'lodash-es'
3import { betterKnex } from './betterDbF.mts'
4import * as knexKustH from './knexKustF.mts'
8import { maskQs } from './maskQsF.mts'
10type KnexConnParams = {
11 qsName: string
12 extQs: string
13 password: string
14 needsKubePortFwd?: boolean
17type QueryContext = {
18 postProcessors?: Array<(result: any) => any>
21export const doKnexConn = ({qsName, extQs, password, needsKubePortFwd}: KnexConnParams): Knex => {
22 if (isVeryVerbose) {
23 console.log('connecting to db (knex)', qsName, maskQs(extQs))
24 }
26 let cfgH = {
27 connection: extQs,
28 }
30 const pool: Knex.PoolConfig = {
31 min: 4, max: 12,
32 createTimeoutMillis: 10000,
33 acquireTimeoutMillis: 30000,
34 idleTimeoutMillis: 30000,
35 reapIntervalMillis: 1000,
36 createRetryIntervalMillis: 100,
37 // tarn supports validate but knex's PoolConfig type omits it
38 ...({ validate: async (conn: any) => {
39 try { await conn.query('SELECT 1'); return true }
40 catch { return false }
41 } } as any),
42 }
44 let db = knex({
45 ...cfgH,
46 client: 'pg',
47 asyncStackTraces: true,
48 pool,
49 })
51 const originalPostProcessResponse = db.client.config.postProcessResponse || ((x: any) => x)
52 db.client.config.postProcessResponse = (result: any, queryContext: QueryContext) => {
53 let processedResult = originalPostProcessResponse(result, queryContext)
55 if (queryContext && queryContext.postProcessors && queryContext.postProcessors.length > 0) {
56 for (const processFn of queryContext.postProcessors) {
57 processedResult = Array.isArray(processedResult)
58 ? processedResult.map(processFn)
59 : (processedResult ? processFn(processedResult) : processedResult)
60 }
61 }
63 return processedResult
64 }
66 const qb = db.queryBuilder()
67 const QueryBuilder = qb.constructor
69 _.each(knexKustH, (fnc: any, key: string) => {
70 QueryBuilder.prototype[key] = fnc
71 })
73 db = betterKnex(db) as Knex
74 return db