import { Adapter , ConnectionOptions } from "./adapters/adapter.ts" ; import { connect } from "./connect.ts" ; import { QueryBuilder , QueryDescription , QueryType } from "./querybuilder.ts" ; import { assertEquals } from "../testdeps.ts" ; import { QueryCompiler } from "./querycompiler.ts" ; import { BelongsTo , Column , HasMany , Model , Primary } from "./model.ts" ; import { Colors } from "../deps.ts" ; import { formatDate } from "./utils/date.ts" ; /**
 * Postgres connection options
 */ export const postgresOptions = { database : Deno . env . get ( "POSTGRES_DATABASE" ) , hostname : Deno . env . get ( "POSTGRES_HOSTNAME" ) , username : Deno . env . get ( "POSTGRES_USERNAME" ) , password : Deno . env . get ( "POSTGRES_PASSWORD" ) , port : Number ( Deno . env . get ( "POSTGRES_PORT" ) ) || 5432 } ; /**
 * MySQL connection options
 */ export const mysqlOptions = { database : Deno . env . get ( "MYSQL_DATABASE" ) , hostname : Deno . env . get ( "MYSQL_HOSTNAME" ) , username : Deno . env . get ( "MYSQL_USERNAME" ) , password : Deno . env . get ( "MYSQL_PASSWORD" ) , port : Number ( Deno . env . get ( "MYSQL_PORT" ) ) || 3306 } ; /**
 * SQLite connection options
 */ export const sqliteOptions = { database : ":memory:" } ; param name param fn export async function testDB ( name , fn ) { Deno . test ( { name : `[sqlite]   ${ name }` , fn : async ( ) => { const db = await connect ( { type : "sqlite" , ... sqliteOptions } ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS users (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          email VARCHAR(255),
          first_name VARCHAR(255),
          last_name VARCHAR(255),
          age INTEGER,
          created_at DATETIME,
          is_active BOOLEAN,
          password VARCHAR(255)
        );
      ` ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS product (
          product_id INTEGER PRIMARY KEY AUTOINCREMENT,
          title VARCHAR(255),
          user_id INTEGER,
          FOREIGN KEY (user_id) REFERENCES users(id)
        );
      ` ) ; await runTestAndClean ( fn , db ) ; } } ) ; Deno . test ( { name : `[postgres] ${ name }` , fn : async ( ) => { const db = await connect ( { type : "postgres" , ... postgresOptions } ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS users (
          id SERIAL PRIMARY KEY,
          email VARCHAR(255),
          first_name VARCHAR(255),
          last_name VARCHAR(255),
          age INTEGER,
          created_at TIMESTAMP,
          is_active BOOLEAN,
          password VARCHAR(255)
        );
      ` ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS product (
          product_id SERIAL PRIMARY KEY,
          title VARCHAR(255),
          user_id INTEGER,
          FOREIGN KEY (user_id) REFERENCES users(id)
        );
      ` ) ; await runTestAndClean ( fn , db ) ; } } ) ; Deno . test ( { name : `[mysql]    ${ name }` , fn : async ( ) => { const db = await connect ( { type : "mysql" , ... mysqlOptions } ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS users (
          id INTEGER PRIMARY KEY AUTO_INCREMENT,
          email VARCHAR(255),
          first_name VARCHAR(255),
          last_name VARCHAR(255),
          age INTEGER,
          created_at DATETIME,
          is_active TINYINT,
          password VARCHAR(255)
        );
      ` ) ; await db . query ( `
        CREATE TABLE IF NOT EXISTS product (
          product_id INTEGER PRIMARY KEY AUTO_INCREMENT,
          title VARCHAR(255),
          user_id INTEGER,
          FOREIGN KEY (user_id) REFERENCES users(id)
        );
      ` ) ; await runTestAndClean ( fn , db ) ; } } ) ; } param fn param db async function runTestAndClean ( fn , db ) { try { await fn ( db ) ; } catch ( err ) { await db . query ( "DROP TABLE product;" ) ; await db . query ( "DROP TABLE users;" ) ; await db . disconnect ( ) ; throw err ; } await db . query ( "DROP TABLE product;" ) ; await db . query ( "DROP TABLE users;" ) ; await db . disconnect ( ) ; } param actual param expected export function assertDateEquals ( actual , expected ) { const result = actual . getFullYear ( ) === expected . getFullYear ( ) && actual . getMonth ( ) === expected . getMonth ( ) && actual . getDate ( ) === expected . getDate ( ) && actual . getHours ( ) === expected . getHours ( ) && actual . getMinutes ( ) === expected . getMinutes ( ) && actual . getSeconds ( ) === expected . getSeconds ( ) ; if ( ! result ) { const expectedDate = Colors . green ( formatDate ( expected ) ) ; const actualDate = Colors . red ( formatDate ( actual ) ) ; throw new Error ( `Dates are not equal!\n\n  expected: ${ expectedDate }\n  actual:   ${ actualDate }\n` ) ; } } param title param fn param description export function testQueryBuilder ( title , fn , description ) { Deno . test ( `QueryBuilder: ${ title }` , ( ) => { const query = new QueryBuilder ( "users" , { } as any ) ; fn ( query ) ; const expected = { tableName : "users" , type : QueryType . Select , columns : [ ] , wheres : [ ] , orders : [ ] , returning : [ ] , joins : [ ] , counts : [ ] , isDistinct : false , groupBy : [ ] , havings : [ ] , ... description } ; const actual = ( query as any ) . description ; assertEquals ( actual , expected ) ; } ) ; } param title param description param result export function testQueryCompiler ( title , description , result ) { for ( const dialect in result ) { const spaces = dialect === "postgres" ? " " : dialect === "mysql" ? "    " : "   " ; Deno . test ( `[${ dialect }]${ spaces }QueryCompiler: ${ title }` , ( ) => { const compiler = new QueryCompiler ( { tableName : "users" , type : QueryType . Select , columns : [ ] , wheres : [ ] , orders : [ ] , returning : [ ] , joins : [ ] , counts : [ ] , isDistinct : false , groupBy : [ ] , havings : [ ] , ... description } , dialect as any ) ; const { text , values } = compiler . compile ( ) ; assertEquals ( text , ( result as any ) [ dialect ] . text ) ; assertEquals ( values , ( result as any ) [ dialect ] . values ) ; } ) ; } } export const toUser = ( ) => User ; export const toProduct = ( ) => Product ; export const getCreationDate = ( ) => new Date ( ) ; @ Model ( "users" ) export class User { /**
     * Represents a primary key column
     */ @ Primary ( ) id ! : number ; /**
     * Represents column with validation
     */ @ Column ( ) email ! : string ; /**
     * Represents a string column with custom table column name
     */ @ Column ( { name : "first_name" } ) firstName ! : string ; /**
     * Represents a string column with custom table column name
     */ @ Column ( { name : "last_name" } ) lastName ! : string ; /**
     * Represents a number column
     */ @ Column ( ) age ! : number ; /**
     * Represents a hidden column
     */ @ Column ( ) password ! : string ; /**
     * Represents a date column with lazy default value
     */ @ Column ( { name : "created_at" , default : getCreationDate } ) createdAt ! : Date ; /**
     * Represents a boolean column with standard default value
     */ @ Column ( { name : "is_active" , default : false } ) isActive ! : boolean ; /**
     * Represents a has many relationship
     */ @ HasMany ( toProduct , "user_id" ) products ! : Product [ ] ; } /**
 * Represents a model with default table name and a custom id
 */ @ Model ( ) export class Product { @ Primary ( { name : "product_id" } ) productId ! : number ; @ Column ( ) title ! : string ; @ BelongsTo ( toUser , "user_id" ) user ! : User ; }