import { DMMF } from '@prisma/client/runtime/dmmf-types' ; import { DataSource } from '@prisma/generator-helper' ; import _ from 'lodash' ; import mysql from 'mysql' ; import url from 'url' ; import { migrateLift , getTmpPrismaSchemaPath } from '../lift' ; import { InternalPool } from '../pool' ; import { Pool , DBInstance } from '../../types' ; param dmmf export function getMySQLPool ( dmmf , cwd ) { return class extends MySQLPool { constructor ( options ) { super ( dmmf , { tmpPrismaSchemaPath : getTmpPrismaSchemaPath , ... options } , cwd ) ; } } ; } export interface MySQLConnection { host : string ; port : number ; user : string ; password ? : string ; database : string ; } export interface MySQLPoolOptions { connection : ( id : string ) => MySQLConnection ; pool ? : { max ? : number ; } ; tmpPrismaSchemaPath ? : ( id : string ) => string ; } class MySQLPool extends InternalPool { private dmmf : DMMF . Document ; private projectDir : string ; private getConnection : ( id : string ) => MySQLConnection ; private getTmpPrismaSchemaPath : ( id : string ) => string ; constructor ( dmmf , options , cwd ) { super ( { max : _ . get ( options , [ 'pool' , 'max' ] , Infinity ) } ) ; this . dmmf = dmmf ; this . projectDir = cwd ; this . getConnection = options . connection ; this . getTmpPrismaSchemaPath = options . tmpPrismaSchemaPath ! ; } async createDBInstance ( id ) { const connection = this . getConnection ( id ) ; const tmpPrismaSchemaPath = this . getTmpPrismaSchemaPath ( id ) ; const uri = readMySQLURI ( connection ) ; const datasources = [ { name : 'db' , connectorType : 'mysql' , url : { value : uri , fromEnvVar : null , } , config : { } , } , ] ; const { datamodel } = await migrateLift ( { id , projectDir : this . projectDir , datasources , tmpPrismaSchemaPath , dmmf : this . dmmf , } ) ; const instance = { url : uri , cwd : this . projectDir , datamodel : datamodel , } ; return instance ; } async deleteDBInstance ( instance ) { const connection = parseMySQLURI ( instance . url ) ; try { const client = await getMySQLClient ( connection ) ; await query ( client , `DROP DATABASE IF EXISTS \`${ connection . database }\`;` ) ; } catch ( err ) { throw err ; } } } param connection async function getMySQLClient ( connection ) { const client = mysql . createConnection ( { host : connection . host , port : connection . port , user : connection . user , password : connection . password , database : connection . database , } ) ; return new Promise ( ( resolve , reject ) => { client . connect ( err => { if ( err ) reject ( err ) ; else resolve ( client ) ; } ) ; } ) ; } param connection param query async function query < T > ( client , query ) { return new Promise ( ( resolve , reject ) => { client . query ( query , ( err , res ) => { if ( err ) reject ( err ) ; else resolve ( res ) ; } ) ; } ) ; } param connection function readMySQLURI ( connection ) { return `mysql://${ connection . user }:${ connection . password }@${ connection . host }:${ connection . port }/${ connection . database }` ; } param uri function parseMySQLURI ( uri ) { const { auth , hostname : host , port : rawPort , pathname } = url . parse ( uri , true ) ; const [ , user , password ] = auth ! . match ( /(\w+):(\w+)/ ) ! ; const [ , database ] = pathname ! . match ( /\/(.+)/ ) ! ; const port = parseInt ( rawPort ! , 10 ) ; return { user , password , host : host ! , port , database , } ; }