UNPKG

@jakub.knejzlik/ts-query-server

Version:

TypeScript library for executing SQL queries built with ts-query across diverse server environments.

90 lines (76 loc) 2.49 kB
import { Q, SelectQuery } from "@jakub.knejzlik/ts-query"; import * as mysql from "mysql2/promise"; import { URL } from "url"; import { QueryRouterClient, QueryRouterClientOpts } from "./client"; interface QueryRouterClientMySQLOpts extends Partial<QueryRouterClientOpts> { databaseUrl: string; databaseName: string; poolOptions?: mysql.PoolOptions; } export class QueryRouterClientMySQL extends QueryRouterClient<QueryRouterClientMySQLOpts> { constructor({ flavor, ...opts }: QueryRouterClientMySQLOpts) { super({ flavor: flavor ?? Q.flavors.mysql, ...opts }); } async executeRawQueries(queries: string[]): Promise<any[]> { const { databaseUrl, databaseName, poolOptions } = this.opts; const res = await executeQueries({ databaseUrl, databaseName, sqls: queries, poolOptions, }); return res.results; } } export interface ExecuteQueriesOpts { databaseUrl: string; databaseName: string; sqls: string[]; poolOptions?: mysql.PoolOptions; } export interface ExecuteQueryResult { results: any[]; } // Caches connection pools by MySQL hostname const poolCache: { [hostname: string]: mysql.Pool } = {}; function createPoolKey(databaseUrl: string): string { const { hostname } = new URL(databaseUrl); return hostname || ""; } function getPool( poolKey: string, databaseUrl: string, poolOptions?: mysql.PoolOptions ): mysql.Pool { if (!poolCache[poolKey]) { poolCache[poolKey] = mysql.createPool({ uri: databaseUrl, ...poolOptions, multipleStatements: true, }); } return poolCache[poolKey]; } export const executeQueries = async ( opts: ExecuteQueriesOpts ): Promise<ExecuteQueryResult> => { const { poolOptions, databaseName, sqls } = opts; if (sqls.length === 0) return { results: [] }; const databaseUrl = opts.databaseUrl .replace("{{MYSQL_USER}}", process.env.MYSQL_USER || "") .replace("{{MYSQL_PASSWORD}}", process.env.MYSQL_PASSWORD || ""); const poolKey = createPoolKey(databaseUrl); const pool = getPool(poolKey, databaseUrl, poolOptions); let connection: mysql.PoolConnection | null = null; try { connection = await pool.getConnection(); const sql = `USE \`${databaseName}\`;\n` + sqls.join(";\n"); const [results] = await connection.query({ sql }); return { results: (results as any[]).slice(1) }; } catch (error) { console.error(error); throw error; } finally { if (connection) connection.release(); } };