All files / owid-grapher/db db.ts

50.41% Statements 62/123
33.33% Branches 2/6
9.09% Functions 1/11
50.41% Lines 62/123

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 1151x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x 1x               1x 1x 1x 1x     1x 1x         1x 1x         1x 1x 1x 1x         1x 1x             1x 1x 1x 1x 1x 1x           1x 1x       1x 1x 1x 1x                                                   1x 1x 1x 1x 1x 1x
import * as mysql from "mysql"
import * as typeorm from "typeorm"
import { Knex, knex } from "knex"
import {
    DB_HOST,
    DB_USER,
    DB_PASS,
    DB_NAME,
    DB_PORT,
} from "../settings/serverSettings"
import { registerExitHandler } from "./cleanup"
let typeormConnection: typeorm.Connection
 
export const getConnection = async (): Promise<typeorm.Connection> => {
    if (typeormConnection) return typeormConnection
 
    try {
        typeormConnection = typeorm.getConnection()
    } catch (err) {
        if (err instanceof Error && err.name === "ConnectionNotFoundError")
            typeormConnection = await typeorm.createConnection()
        else throw err
    }

    registerExitHandler(async () => {
        if (typeormConnection) await typeormConnection.close()
    })

    return typeormConnection
}
 
export class TransactionContext {
    manager: typeorm.EntityManager
    constructor(manager: typeorm.EntityManager) {
        this.manager = manager
    }
 
    execute(queryStr: string, params?: any[]): Promise<any> {
        return this.manager.query(
            params ? mysql.format(queryStr, params) : queryStr
        )
    }
 
    query(queryStr: string, params?: any[]): Promise<any> {
        return this.manager.query(
            params ? mysql.format(queryStr, params) : queryStr
        )
    }
}
 
export const transaction = async <T>(
    callback: (t: TransactionContext) => Promise<T>
): Promise<T> =>
    (await getConnection()).transaction(async (manager) =>
        callback(new TransactionContext(manager))
    )
 
export const queryMysql = async (
    queryStr: string,
    params?: any[]
): Promise<any> => {
    const conn = await getConnection()
    return conn.query(params ? mysql.format(queryStr, params) : queryStr)
}
 
// For operations that modify data (TODO: handling to check query isn't used for this)
export const execute = queryMysql
 
// Return the first match from a mysql query
export const mysqlFirst = async (
    queryStr: string,
    params?: any[]
): Promise<any> => {
    return (await queryMysql(queryStr, params))[0]
}
 
export const closeTypeOrmAndKnexConnections = async (): Promise<void> => {
    if (typeormConnection) await typeormConnection.close()
    if (_knexInstance) await _knexInstance.destroy()
}
 
let _knexInstance: Knex
 
export const knexInstance = (): Knex<any, any[]> => {
    if (_knexInstance) return _knexInstance

    _knexInstance = knex({
        client: "mysql",
        connection: {
            host: DB_HOST,
            user: DB_USER,
            password: DB_PASS,
            database: DB_NAME,
            port: DB_PORT,
            typeCast: (field: any, next: any) => {
                if (field.type === "TINY" && field.length === 1) {
                    return field.string() === "1" // 1 = true, 0 = false
                }
                return next()
            },
        },
    })

    registerExitHandler(async () => {
        if (_knexInstance) await _knexInstance.destroy()
    })

    return _knexInstance
}
 
export const knexTable = (table: string): Knex.QueryBuilder =>
    knexInstance().table(table)
 
export const knexRaw = (str: string): Knex.Raw => knexInstance().raw(str)