UNPKG

scyllinx

Version:

A modern TypeScript ORM for ScyllaDB and SQL databases with Laravel-inspired syntax

1 lines 55.7 kB
"use strict";var t=require("node-cache"),e=require("redis"),s=require("util"),r=require("@faker-js/faker");require("reflect-metadata");class i{cache;constructor(e={}){this.cache=new t({stdTTL:e.stdTTL||600,checkperiod:e.checkperiod||120})}connect(){throw new Error("Method not implemented.")}async get(t){return this.cache.get(t)}async set(t,e,s){this.cache.set(t,e,s)}async forget(t){this.cache.del(t)}async flush(){this.cache.flushAll()}async remember(t,e,s){const r=await this.get(t);if(void 0!==r)return r;const i=await s();return await this.set(t,i,e),i}}class n{client;prefix;constructor(t={},s=""){this.prefix=s,this.client=e.createClient({socket:{host:t.host||"localhost",port:t.port||6379},password:t.password,database:t.db||0})}async connect(){await this.client.connect()}async get(t){const e=await this.client.get(this.prefixKey(t)),s="string"==typeof e?e:e?.toString?.("utf-8");return s?JSON.parse(s):void 0}async set(t,e,s){const r=JSON.stringify(e);s?await this.client.setEx(this.prefixKey(t),s,r):await this.client.set(this.prefixKey(t),r)}async forget(t){await this.client.del(this.prefixKey(t))}async flush(){const t=await this.client.keys(`${this.prefix}*`);t.length>0&&await this.client.del(t)}async remember(t,e,s){const r=await this.get(t);if(void 0!==r)return r;const i=await s();return await this.set(t,i,e),i}prefixKey(t){return this.prefix?`${this.prefix}:${t}`:t}}class a{static instance;stores=new Map;defaultStore="redis";static getInstance(){return a.instance||(a.instance=new a),a.instance}addStore(t,e){let s;if("redis"===e.driver)s=new n(e.redis,e.prefix);else s=new i(e.memory);this.stores.set(t,s)}getStore(t){const e=t||this.defaultStore,s=this.stores.get(e);if(!s)throw new Error(`Cache store '${e}' not found`);return s}setDefaultStore(t){this.defaultStore=t}async get(t,e){return await this.getStore(e).get(t)}async set(t,e,s,r){return await this.getStore(r).set(t,e,s)}async forget(t,e){return await this.getStore(e).forget(t)}async flush(t){return await this.getStore(t).flush()}async remember(t,e,s,r){return await this.getStore(r).remember(t,e,s)}tags(t){return new o(this,t)}}class o{cacheManager;tags;constructor(t,e){this.cacheManager=t,this.tags=e}async get(t){return this.cacheManager.get(this.taggedKey(t))}async set(t,e,s){await this.cacheManager.set(this.taggedKey(t),e,s);for(const e of this.tags){const s=await this.cacheManager.get(`tag:${e}`)||[];s.push(this.taggedKey(t)),await this.cacheManager.set(`tag:${e}`,s)}}async flush(){for(const t of this.tags){const e=await this.cacheManager.get(`tag:${t}`)||[];for(const t of e)await this.cacheManager.forget(t);await this.cacheManager.forget(`tag:${t}`)}}taggedKey(t){return`tagged:${this.tags.join(":")}:${t}`}}class c{name;driver;config;connected=!1;constructor(t,e,s){this.name=t,this.driver=e,this.config=s}getName(){return this.name}getDriver(){return this.driver}getConfig(){return this.config}async connect(){this.connected||(await this.driver.connect(),this.connected=!0)}async disconnect(){this.connected&&(await this.driver.disconnect(),this.connected=!1)}isConnected(){return this.connected}async query(t,e){if(!this.connected)throw new Error(`Connection '${this.name}' is not connected`);return await this.driver.query(t,e)}async beginTransaction(){await this.driver.beginTransaction()}async commit(){await this.driver.commit()}async rollback(){await this.driver.rollback()}}class h{static instance;connections=new Map;defaultConnection="default";constructor(){}static getInstance(){return h.instance||(h.instance=new h),h.instance}async initialize(t){this.defaultConnection=t.default;for(const[e,s]of Object.entries(t.connections))await this.addConnection(e,s);if(t.cache){const e=a.getInstance();for(const[s,r]of Object.entries(t.cache))e.addStore(s,r)}}async addConnection(t,e){if(this.connections.has(t))throw new Error(`Connection '${t}' already exists`);let s;switch(e.driver){case"scylladb":const{ScyllaDBDriver:t}=await Promise.resolve().then(function(){return g});s=new t(e);break;case"mysql":const{MySQLDriver:r}=await Promise.resolve().then(function(){return require("./MySQLDriver-eJJZDMtm.js")});s=new r(e);break;case"postgresql":const{PostgreSQLDriver:i}=await Promise.resolve().then(function(){return require("./PostgreSQLDriver-GOiKJmnQ.js")});s=new i(e);break;case"sqlite":const{SQLiteDriver:n}=await Promise.resolve().then(function(){return require("./SQLiteDriver-B4HX-7E2.js")});s=new n(e);break;case"mongodb":const{MongoDBDriver:a}=await Promise.resolve().then(function(){return require("./MongoDBDriver-yFZYPdvr.js")});s=new a(e);break;default:throw new Error(`Unsupported database driver: ${e.driver}`)}const r=new c(t,s,e);this.connections.set(t,r)}getConnection(t){const e=t||this.defaultConnection,s=this.connections.get(e);if(!s)throw new Error(`Connection '${e}' not found`);return s}setDefaultConnection(t){if(!this.connections.has(t))throw new Error(`Connection '${t}' not found`);this.defaultConnection=t}getDefaultConnectionName(){return this.defaultConnection}hasConnection(t){return this.connections.has(t)}async removeConnection(t){const e=this.connections.get(t);if(!e)throw new Error(`Connection '${t}' not found`);e.isConnected()&&await e.disconnect(),this.connections.delete(t),this.defaultConnection===t&&(this.defaultConnection="default")}getConnections(){return Array.from(this.connections.values())}getConnectionNames(){return Array.from(this.connections.keys())}async testConnection(t){const e=this.getConnection(t);try{return await e.connect(),await e.disconnect(),!0}catch{return!1}}async connectAll(){const t=Array.from(this.connections.values()).map(t=>t.connect());await Promise.all(t)}async disconnectAll(){const t=Array.from(this.connections.values()).map(t=>t.disconnect());await Promise.all(t)}getConnectionCount(){return this.connections.size}async clear(){await this.disconnectAll(),this.connections.clear(),this.defaultConnection="default"}}class u{config;connection;inTransaction=!1;constructor(t){this.config=t}isConnected(){return!!this.connection}isInTransaction(){return this.inTransaction}}class l{}class m extends l{compileSelect(t){const e=[];if(t.columns&&t.columns.length>0?e.push(`SELECT ${t.columns.map(t=>this.wrapColumn(t)).join(", ")}`):e.push("SELECT *"),t.from&&e.push(`FROM ${this.wrapTable(t.from)}`),t.wheres&&t.wheres.length>0&&e.push(`WHERE ${this.compileWheres(t.wheres)}`),t.orders&&t.orders.length>0){const s=t.orders.map(t=>`${this.wrapColumn(t.column)} ${t.direction.toUpperCase()}`).join(", ");e.push(`ORDER BY ${s}`)}return t.limit&&e.push(`LIMIT ${t.limit}`),t.allowFiltering&&e.push("ALLOW FILTERING"),e.join(" ")}compileInsert(t){const e=this.wrapTable(t.table),s=Object.keys(t.values).map(t=>this.wrapColumn(t)),r=Object.values(t.values).map(()=>"?");let i=`INSERT INTO ${e} (${s.join(", ")}) VALUES (${r.join(", ")})`;return t.ttl&&(i+=` USING TTL ${t.ttl}`),t.ifNotExists&&(i+=" IF NOT EXISTS"),i}compileUpdate(t){const e=this.wrapTable(t.table),s=Object.keys(t.values).map(t=>`${this.wrapColumn(t)} = ?`);let r=`UPDATE ${e}`;return t.ttl&&(r+=` USING TTL ${t.ttl}`),r+=` SET ${s.join(", ")}`,t.wheres&&t.wheres.length>0&&(r+=` WHERE ${this.compileWheres(t.wheres)}`),t.ifConditions&&t.ifConditions.length>0&&(r+=` IF ${this.compileWheres(t.ifConditions)}`),r}compileDelete(t){let e="DELETE";return t.columns&&t.columns.length>0&&(e+=` ${t.columns.map(t=>this.wrapColumn(t)).join(", ")}`),e+=` FROM ${this.wrapTable(t.table)}`,t.wheres&&t.wheres.length>0&&(e+=` WHERE ${this.compileWheres(t.wheres)}`),t.ifConditions&&t.ifConditions.length>0&&(e+=` IF ${this.compileWheres(t.ifConditions)}`),e}compileWheres(t){return t.map((t,e)=>{if(!t)return"";const s=e>0?t.boolean||"AND":"",r=e>0?` ${s.toUpperCase()} `:"";switch(t.type){case"basic":return t.column?`${r}${this.wrapColumn(t.column)} ${t.operator||"="} ?`:"";case"in":return t.column&&t.values?`${r}${this.wrapColumn(t.column)} IN (${t.values.map(()=>"?").join(", ")})`:"";case"notIn":return t.column&&t.values?`${r}${this.wrapColumn(t.column)} NOT IN (${t.values.map(()=>"?").join(", ")})`:"";case"between":return t.column?`${r}${this.wrapColumn(t.column)} >= ? AND ${this.wrapColumn(t.column)} <= ?`:"";case"null":return t.column?`${r}${this.wrapColumn(t.column)} IS NULL`:"";case"notNull":return t.column?`${r}${this.wrapColumn(t.column)} IS NOT NULL`:"";case"token":return t.columns&&t.values&&t.operator?`${r}TOKEN(${t.columns.map(t=>this.wrapColumn(t)).join(", ")}) ${t.operator} TOKEN(${t.values.map(()=>"?").join(", ")})`:"";case"raw":return t.raw||"";default:return""}}).filter(Boolean).join("")}wrapTable(t){return t.includes(".")?t:`${t}`}wrapColumn(t){return t}parameter(t){return"?"}getColumnType(t){switch(t.type){case"bigIncrements":case"bigInteger":return"bigint";case"integer":case"int":return"int";case"string":case"text":case"json":default:return"text";case"boolean":return"boolean";case"decimal":case"float":case"double":return"decimal";case"date":case"dateTime":case"timestamp":return"timestamp";case"uuid":return"uuid";case"timeuuid":return"timeuuid";case"counter":return"counter";case"set":return`set<${t.elementType}>`;case"list":return`list<${t.elementType}>`;case"map":return`map<${t.keyType}, ${t.valueType}>`}}compileColumn(t){return`${this.wrapColumn(t.name)} ${this.getColumnType(t)}`}compileCreateTable({name:t,columns:e,partitionKeys:s,clusteringKeys:r,clusteringOrder:i={},tableOptions:n={}}){const a=e.map(t=>this.compileColumn(t));let o="";if(s.length>0)o=r.length>0?`PRIMARY KEY ((${s.join(", ")}), ${r.join(", ")})`:`PRIMARY KEY ((${s.join(", ")}))`;else{const t=e.filter(t=>t.primary);t.length>0&&(o=r.length>0?`PRIMARY KEY ((${t.map(t=>t.name).join(", ")}), ${r.join(", ")})`:`PRIMARY KEY ((${t.map(t=>t.name).join(", ")}))`)}o&&a.push(o);let c="";const h=Object.entries(i);if(h.length>0){const t=h.map(([t,e])=>`${t} ${e}`).join(", ");c=` WITH CLUSTERING ORDER BY (${t})`}const u=[];for(const[t,e]of Object.entries(n))if("object"==typeof e&&null!==e){const s=Object.entries(e).map(([t,e])=>`'${t}': ${"string"==typeof e?`'${e}'`:e}`).join(", ");u.push(`${t} = { ${s} }`)}else u.push(`${t} = ${"string"==typeof e?`'${e}'`:e}`);let l="";if(c||u.length>0){l=` ${[c,...u.map((t,e)=>`${0!==e||c?"AND":"WITH"} ${t}`)].join(" ")}`}return`CREATE TABLE ${this.wrapTable(t)} (${a.join(", ")})${l}`}compileAlterTable({name:t,columns:e}){if(!e||0===e.length)throw new Error("No columns provided for ALTER TABLE.");return`ALTER TABLE ${this.wrapTable(t)} ${e.map(t=>`ADD ${this.wrapColumn(t.name)} ${this.getColumnType(t)}`).join(", ")}`}compileTableExists(t){return"\n SELECT table_name\n FROM system_schema.tables\n WHERE keyspace_name = ?\n AND table_name = ?\n ".trim().replace(/\s+/g," ")}compileColumnExists(t,e){return"\n SELECT column_name\n FROM system_schema.columns\n WHERE keyspace_name = ?\n AND table_name = ?\n AND column_name = ?\n ".trim().replace(/\s+/g," ")}rename(t,e){return Promise.reject(new Error(`Table rename from "${t}" to "${e}" is not supported by ScyllaDB.`))}}class p extends u{cassandraModule;client;grammar;preparedStatements=new Map;constructor(t){super(t),this.grammar=new m}async connect(){this.cassandraModule=await import("cassandra-driver");const{Client:t,types:e}=this.cassandraModule,s={contactPoints:[this.config.host||"localhost"],localDataCenter:this.config.localDataCenter||"datacenter1",keyspace:this.config.keyspace,credentials:this.config.username&&this.config.password?{username:this.config.username,password:this.config.password}:void 0,...this.config};this.client=new t(s),await this.client.connect(),this.connection=this.client}async disconnect(){this.client&&(await this.client.shutdown(),this.connection=null)}async query(t,e){try{const s=await this.client.execute(t,e||[],{prepare:!0});return{rows:s.rows?.map(t=>this.mapRow(t)),rowCount:s.rowLength||0}}catch(t){throw new Error(`ScyllaDB query failed: ${t.message}`)}}async prepare(t){if(this.preparedStatements.has(t)){const e=this.preparedStatements.get(t);return new d(this.client,e,this.cassandraModule.types)}const e=await this.client.execute(t,{prepare:!0});return this.preparedStatements.set(t,e),new d(this.client,e,this.cassandraModule.types)}async batch(t){const e=t.map(t=>({query:t.query,params:t.params||[]}));return await this.client.batch(e,{prepare:!0,consistency:this.cassandraModule.types?.consistencies.localQuorum}),{rows:[],rowCount:0}}async beginTransaction(){this.inTransaction=!0}async commit(){this.inTransaction=!1}async rollback(){this.inTransaction=!1}async getLastInsertId(){return""}escape(t){return null==t?"NULL":"string"==typeof t?`'${t.replace(/'/g,"''")}'`:"boolean"==typeof t?t?"true":"false":String(t)}getGrammar(){return this.grammar}supportsFeature(t){return["prepared_statements","batch_operations","lightweight_transactions","materialized_views","secondary_indexes","collections","user_defined_types","counters","ttl"].includes(t)}mapRow(t){const e={};for(const[s,r]of Object.entries(t))e[s]=this.mapValue(r);return e}mapValue(t){if(null==t)return null;const e=this.cassandraModule.types;return t instanceof e.Uuid||t instanceof e.TimeUuid?t.toString():t instanceof e.BigDecimal||t instanceof e.Long?t.toNumber():t instanceof Date?t.toISOString():t}}class d{client;prepared;types;constructor(t,e,s){this.client=t,this.prepared=e,this.types=s}async execute(t){const e=await this.client.execute(this.prepared,t||[],{consistency:this.types.consistencies.localQuorum});return{rows:e.rows||[],rowCount:e.rowLength||0}}async close(){}}var g=Object.freeze({__proto__:null,ScyllaDBDriver:p});class y{static instance;models=new Map;aliases=new Map;static getInstance(){return y.instance||(y.instance=new y),y.instance}register(t,e,s=[]){return this.models.set(t,e),s.forEach(e=>{this.aliases.set(e,t)}),this.aliases.set(t.toLowerCase(),t),this.aliases.set(this.pluralize(t.toLowerCase()),t),this}get(t){const e=this.models.get(t)||this.models.get(this.aliases.get(t));if(!e)throw new Error(`Model '${t}' not found`);return e}has(t){return this.models.has(t)||this.aliases.has(t)}all(){return new Map(this.models)}getModelNames(){return Array.from(this.models.keys())}autoDiscover(t="./app/Models"){console.log(`Auto-discovering models in ${t}...`)}pluralize(t){return t.endsWith("y")?t.slice(0,-1)+"ies":t.match(/(s|sh|ch|x|z)$/)?t+"es":t+"s"}}class w{driver;grammar;_select=["*"];_from;_values={};_joins=[];_wheres=[];_groups=[];_havings=[];_orders=[];_limit;_offset;_unions=[];eager=[];_allowFiltering=!1;_ttl;_ifNotExists=!1;_ifConditions=[];model;connection;cacheKey;cacheTtl;cacheStore;constructor(t,e){this._from=t,this.connection=e;const s=h.getInstance();this.driver=s.getConnection(e).getDriver(),this.grammar=this.driver.getGrammar()}setModel(t){return this.model=t,this}select(...t){return this._select=t.length>0?t.map(String):["*"],this}addSelect(...t){if(1===this._select.length&&"*"===this._select[0])this._select=t.map(String);else for(const e of t){const t=String(e);this._select.includes(t)||this._select.push(t)}return this}where(t,e,s){const r=arguments;return"object"==typeof t?Object.entries(t).forEach(([t,e])=>{this._wheres.push({type:"basic",column:t,operator:"=",value:e,boolean:"and"})}):2===r.length?this._wheres.push({type:"basic",column:t,operator:"=",value:e,boolean:"and"}):this._wheres.push({type:"basic",column:t,operator:e,value:s,boolean:"and"}),this}orWhere(t,e,s){return 2===arguments.length?this._wheres.push({type:"basic",column:t,operator:"=",value:e,boolean:"or"}):this._wheres.push({type:"basic",column:t,operator:e,value:s,boolean:"or"}),this}whereIn(t,e){return this._wheres.push({type:"in",column:t,values:e,boolean:"and"}),this}whereNotIn(t,e){return this._wheres.push({type:"notIn",column:t,values:e,boolean:"and"}),this}whereBetween(t,e){return this._wheres.push({type:"between",column:t,values:e,boolean:"and"}),this}whereNull(t){return this._wheres.push({type:"null",column:t,boolean:"and"}),this}whereNotNull(t){return this._wheres.push({type:"notNull",column:t,boolean:"and"}),this}join(t,e,s,r){return this._joins.push({type:"inner",table:t,first:e,operator:s,second:r}),this}leftJoin(t,e,s,r){return this._joins.push({type:"left",table:t,first:e,operator:s,second:r}),this}rightJoin(t,e,s,r){return this._joins.push({type:"right",table:t,first:e,operator:s,second:r}),this}orderBy(t,e="asc"){return this._orders.push({column:t,direction:e.toLowerCase()}),this}groupBy(...t){return this._groups.push(...t.map(String)),this}having(t,e,s){return 2===arguments.length&&(s=e,e="="),this._havings.push({type:"basic",column:t,operator:e,value:s,boolean:"and"}),this}limit(t){return this._limit=t,this}offset(t){return this._offset=t,this}take(t){return this.limit(t)}skip(t){return this.offset(t)}allowFiltering(){return this._allowFiltering=!0,this}ttl(t){return this._ttl=t,this}ifNotExists(){return this._ifNotExists=!0,this}if(t,e,s){return this._ifConditions.push({type:"basic",column:t,operator:e,value:s,boolean:"AND"}),this}whereToken(t,e,s){return this._wheres.push({type:"token",columns:t,operator:e,values:s,boolean:"and"}),this}async get(){const t=this.grammar.compileSelect(this.toBase()),e=this.getParams(),s=await this.driver.query(t,e);if(this.cacheTtl){const t=this.cacheKey??JSON.stringify({sql:this.toSql(),params:e}),r=a.getInstance();let i,n=await r.remember(t,this.cacheTtl,async()=>s.rows,this.cacheStore);return i=this.model?n.map(t=>this.hydrate(t)):n,this.eager.length&&await Promise.all(i.map(t=>this.loadEagerFor(t,this.eager))),i}let r;return r=this.model?s.rows.map(t=>this.hydrate(t)):s.rows,this.eager.length&&await Promise.all(r.map(t=>this.loadEagerFor(t,this.eager))),r}async execute(){const t=this.grammar.compileSelect(this.toBase()),e=this.getParams(),s=await this.driver.query(t,e);let r=[];return r=this.model?s.rows.map(t=>this.hydrate(t)):s.rows,this.eager.length&&await Promise.all(r.map(t=>this.loadEagerFor(t,this.eager))),r}cache(t,e,s){return this.cacheTtl=t,this.cacheKey=e,this.cacheStore=s,this}with(...t){const e=Array.isArray(t)?t:[t];return this.eager.push(...e),this}async loadEagerFor(t,e){for(const s of e){const[e,...r]=s.split("."),i=t[`${e}Relation`](),n=await i.getResults();if(t.setAttribute(e,n),r.length&&n){const t=Array.isArray(n)?n:[n];await Promise.all(t.map(t=>this.loadEagerFor(t,[r.join(".")])))}}}async first(){const t=await this.take(1).get();return t.length>0?t[0]:null}async count(t="*"){const e=this.clone();e._select=[`COUNT(${t}) as aggregate`];const s=await e.get();return s[0]?.aggregate||0}async exists(){return await this.count()>0}async insert(t){if(Array.isArray(t)){const e=t.map(t=>({query:this.grammar.compileInsert({table:this._from,values:t,ttl:this._ttl,ifNotExists:this._ifNotExists}),params:Object.values(t)}));if(this.driver instanceof(await Promise.resolve().then(function(){return g})).ScyllaDBDriver)await this.driver.batch(e);else for(const t of e)await this.driver.query(t.query,t.params)}else{const e=this.grammar.compileInsert({table:this._from,values:t,ttl:this._ttl,ifNotExists:this._ifNotExists}),s=Object.values(t);this._values=t,await this.driver.query(e,s)}return!0}async insertGetId(t){return await this.insert(t),await this.driver.getLastInsertId()}async update(t){const e=this.grammar.compileUpdate({table:this._from,values:t,wheres:this._wheres,ttl:this._ttl,ifConditions:this._ifConditions}),s=[...Object.values(t),...this.getWhereParams(this._wheres),...this.getWhereParams(this._ifConditions)];this._values=t;return(await this.driver.query(e,s)).affectedRows||0}async updateOrInsert(t,e={}){return await this.where(t).exists()?await this.where(t).update(e)>0:await this.insert({...t,...e})}async delete(){this._model;const t=this.grammar.compileDelete({table:this._from,wheres:this._wheres,ifConditions:this._ifConditions}),e=[...this.getWhereParams(this._wheres),...this.getWhereParams(this._ifConditions)];return(await this.driver.query(t,e)).affectedRows||0}async truncate(){const t=`TRUNCATE ${this.grammar.wrapTable(this._from)}`;await this.driver.query(t)}toBase(){return{columns:this._select,from:this._from,values:this._values,joins:this._joins,wheres:this._wheres,groups:this._groups,havings:this._havings,orders:this._orders,limit:this._limit,offset:this._offset,unions:this._unions,allowFiltering:this._allowFiltering}}getParams(){return[...this.getWhereParams(this._wheres),...this.getHavingParams()]}getWhereParams(t){const e=[];for(const s of t)switch(s.type){case"basic":e.push(s.value);break;case"in":case"notIn":case"between":case"token":e.push(...s.values??[])}return e}getHavingParams(){const t=[];for(const e of this._havings)"basic"===e.type&&t.push(e.value);return t}hydrate(t){if(!this.model)throw new Error("Model is not set on QueryBuilder");const e=new this.model;return e.setAttributes(t),e.setExists(!0),e.setOriginal(t),e}clone(){const t=new w(this._from,this.connection);return t._select=[...this._select],t._values=this._values,t._joins=[...this._joins],t._wheres=[...this._wheres],t._groups=[...this._groups],t._havings=[...this._havings],t._orders=[...this._orders],t._limit=this._limit,t._offset=this._offset,t._unions=[...this._unions],t._allowFiltering=this._allowFiltering,t._ttl=this._ttl,t._ifNotExists=this._ifNotExists,t._ifConditions=[...this._ifConditions],t.model=this.model,t}toSql(){return this.grammar.compileSelect(this.toBase())}toRawSql(){const t=this.toSql(),e=this.getParams();let s=0;return t.replace(/\?/g,()=>{const t=e[s++];return"string"==typeof t?`'${t}'`:String(t)})}}class f{parent;relatedCtor;foreignKey;localKey;constructor(t,e,s,r){this.parent=t,this.relatedCtor=e,this.foreignKey=s,this.localKey=r}related(){return new this.relatedCtor}getQuery(){const t=this.related();return new w(t.getTable(),t.getConnection()).setModel(this.relatedCtor)}async get(){const t=this.getQuery();return this.addConstraints(t).allowFiltering(),await t.get()}async first(){const t=this.getQuery();return this.addConstraints(t),await t.first()}where(t,e,s){const r=this.getQuery();return this.addConstraints(r),r.where(t,e,s)}with(...t){const e=this.getQuery();return this.addConstraints(e).allowFiltering(),e.with(...t)}getParentKey(){return this.parent.getAttribute(this.localKey)}getForeignKeyName(){return this.foreignKey}getLocalKeyName(){return this.localKey}}class b extends f{addConstraints(t){const e=this.getParentKey();return null!=e&&t.where(this.localKey,e),t}async getResults(){return await this.first()}associate(t){const e=t.getAttribute(this.localKey);return this.parent.setAttribute(this.foreignKey,e),this.parent}dissociate(){return this.parent.setAttribute(this.foreignKey,null),this.parent}getParentKey(){return this.parent.getAttribute(this.foreignKey)}}class v extends f{pivotTable;relatedPivotKey;parentPivotKey;relatedKey;parentKey;pivotColumns=[];pivotWheres=[];constructor(t,e,s,r,i,n,a){super(t,e,r,n),this.pivotTable=s,this.parentPivotKey=r,this.relatedPivotKey=a,this.relatedKey=i,this.parentKey=n}addConstraints(t){if("default"!==this.parent.getConnection()){const e=this.getParentKey();t.select("*").addSelect(...this.getPivotColumns()).join(this.pivotTable,`${this.getRelatedTable()}.${this.relatedPivotKey}`,"=",`${this.pivotTable}.${this.relatedPivotKey}`).where(`${this.pivotTable}.${this.parentPivotKey}`,e);for(const e of this.pivotWheres)"in"===e.type?t.whereIn(e.column,e.values??[]):t.where(e.column,e.operator,e.value)}return t}async getResults(){const t=this.parent.getConnection();if("default"===t){const e=this.getParentKey(),s=this.newPivotQuery();for(const t of this.pivotWheres)"in"===t.type?s.whereIn(t.column,t.values??[]):s.where(t.column,t.operator,t.value);const r=(await s.get()).filter(t=>t[this.parentPivotKey]===e),i=r.map(t=>t[this.relatedPivotKey]);if(!i.length)return[];const n=new w(this.getRelatedTable(),t).setModel(this.relatedCtor).whereIn(this.relatedKey,i),a=await n.get();for(const t of a){const e=r.find(e=>e[this.relatedPivotKey]===t.getAttribute(this.relatedPivotKey));t.setAttribute("pivot",e)}return a}return this.get()}async attach(t,e={}){const s=Array.isArray(t)?t:[t],r=this.getParentKey(),i=s.map(t=>({[this.parentPivotKey]:r,[this.relatedPivotKey]:t,...e}));await this.newPivotQuery().insert(i)}async detach(t){const e=this.newPivotQuery().where(this.parentPivotKey,this.getParentKey());if(null!=t){const s=Array.isArray(t)?t:[t];e.whereIn(this.relatedPivotKey,s)}return e.delete()}async sync(t,e=!0){const s={attached:[],detached:[],updated:[]},r=(await this.newPivotQuery().where(this.parentPivotKey,this.getParentKey()).get()).map(t=>t[this.relatedPivotKey]),i=t,n=i.filter(t=>!r.includes(t)),a=e?r.filter(t=>!i.includes(t)):[];return n.length&&(await this.attach(n),s.attached=n),a.length&&(await this.detach(a),s.detached=a),s}async toggle(t){const e=Array.isArray(t)?t:[t],s={attached:[],detached:[]},r=(await this.newPivotQuery().where(this.parentPivotKey,this.getParentKey()).whereIn(this.relatedPivotKey,e).get()).map(t=>t[this.relatedPivotKey]),i=e.filter(t=>!r.includes(t)),n=r;return i.length&&(await this.attach(i),s.attached=i),n.length&&(await this.detach(n),s.detached=n),s}async updateExistingPivot(t,e){return this.newPivotQuery().where(this.parentPivotKey,this.getParentKey()).where(this.relatedPivotKey,t).update(e)}withPivot(...t){return this.pivotColumns.push(...t),this}wherePivot(t,e,s){return void 0===s&&(s=e,e="="),this.pivotWheres.push({column:`${this.pivotTable}.${t}`,operator:e,value:s}),this}wherePivotIn(t,e){return this.pivotWheres.push({type:"in",column:`${this.pivotTable}.${t}`,values:e}),this}getPivotColumns(){const t=[`${this.pivotTable}.${this.parentPivotKey} as pivot_${this.parentPivotKey}`,`${this.pivotTable}.${this.relatedPivotKey} as pivot_${this.relatedPivotKey}`];for(const e of this.pivotColumns)t.push(`${this.pivotTable}.${e} as pivot_${e}`);return t}newPivotQuery(){const t=this.related();return new w(this.pivotTable,t.getConnection()).allowFiltering()}getRelatedTable(){return this.related().getTable()}}class T extends f{addConstraints(t){const e=this.getParentKey();return null!=e&&t.where(this.foreignKey,e),t}async getResults(){return await this.get()}async create(t){const e=new this.relatedCtor;return e.setAttribute(this.foreignKey,this.getParentKey()),e.fill(t),await e.save(),e}async createMany(t){const e=[];for(const s of t){const t=await this.create(s);e.push(t)}return e}async save(t){return t.setAttribute(this.foreignKey,this.getParentKey()),await t.save(),t}async saveMany(t){for(const e of t)await this.save(e);return t}async find(t){const e=this.getQuery();return this.addConstraints(e),await e.find(t)}async update(t){const e=this.getQuery();return this.addConstraints(e),await e.update(t)}async delete(){const t=this.getQuery();return this.addConstraints(t),await t.delete()}}class _ extends f{addConstraints(t){const e=this.getParentKey();return null!=e&&t.where(this.foreignKey,e),t}async getResults(){return await this.first()}async create(t){const e=new this.relatedCtor;return e.setAttribute(this.foreignKey,this.getParentKey()),e.fill(t),await e.save(),e}async save(t){return t.setAttribute(this.foreignKey,this.getParentKey()),await t.save(),t}associate(t){return t.setAttribute(this.foreignKey,this.getParentKey()),t}async dissociate(){const t=await this.getResults();t&&(t.setAttribute(this.foreignKey,null),await t.save())}}class $ extends f{morphType;morphId;constructor(t,e,s,r,i){super(t,e,r,i),this.morphType=s,this.morphId=r}addConstraints(t){const e=this.getParentKey(),s=this.parent.constructor.name.toLowerCase();return null!=e&&t.where(this.morphId,e).where(this.morphType,s),t}async getResults(){return await this.get()}async create(t){const e=new this.relatedCtor,s=this.parent.constructor.name.toLowerCase();return e.setAttribute(this.morphType,s),e.setAttribute(this.morphId,this.getParentKey()),e.fill(t),await e.save(),e}async createMany(t){const e=[];for(const s of t){const t=await this.create(s);e.push(t)}return e}async save(t){const e=this.parent.constructor.name.toLowerCase();return t.setAttribute(this.morphType,e),t.setAttribute(this.morphId,this.getParentKey()),await t.save(),t}async saveMany(t){for(const e of t)await this.save(e);return t}}class E extends f{morphType;morphId;constructor(t,e,s,r,i){super(t,e,r,i),this.morphType=s,this.morphId=r}addConstraints(t){const e=this.getParentKey(),s=this.parent.constructor.name.toLowerCase();return null!=e&&t.where(this.morphId,e).where(this.morphType,s),t}async getResults(){return await this.first()}async create(t){const e=new this.relatedCtor,s=this.parent.constructor.name.toLowerCase();return e.setAttribute(this.morphType,s),e.setAttribute(this.morphId,this.getParentKey()),e.fill(t),await e.save(),e}async save(t){const e=this.parent.constructor.name.toLowerCase();return t.setAttribute(this.morphType,e),t.setAttribute(this.morphId,this.getParentKey()),await t.save(),t}}class C extends f{morphType;morphId;models=new Map;constructor(t,e,s,r){super(t,null,s,r),this.morphType=e,this.morphId=s}addConstraints(t){return t}async getResults(){const t=this.parent.getAttribute(this.morphType),e=this.parent.getAttribute(this.morphId);if(!t||!e)return null;const s=this.models.get(t);if(!s)throw new Error(`Model not registered for morph type: ${t}`);const r=new s;return new w(r.getTable(),r.getConnection()).setModel(s),null}registerModel(t,e){return this.models.set(t,e),this}associate(t){const e=t.constructor.name.toLowerCase(),s=t.getAttribute(this.localKey);return this.parent.setAttribute(this.morphType,e),this.parent.setAttribute(this.morphId,s),this.parent}dissociate(){return this.parent.setAttribute(this.morphType,null),this.parent.setAttribute(this.morphId,null),this.parent}getMorphType(){return this.parent.getAttribute(this.morphType)}getMorphId(){return this.parent.getAttribute(this.morphId)}}class N{static table;static primaryKey="id";static keyspace;static partitionKeys=[];static clusteringKeys=[];static connection;static fillable=[];static guarded=["*"];static hidden=[];static visible=[];static casts={};static dates=["created_at","updated_at"];static timestamps=!0;static softDeletes=!1;static scopes={};attributes={};original={};changes={};exists=!1;wasRecentlyCreated=!1;constructor(t={},e=!1){!0===e?this.forceFill(t):this.fill(t)}[s.inspect.custom](){return{__model__:this.constructor.name,attributes:this.attributes,original:this.original,changes:this.getDirty(),dirty:this.isDirty(),exists:this.exists,wasRecentlyCreated:this.wasRecentlyCreated}}defineAccessor(t){Object.prototype.hasOwnProperty.call(this,t)||Object.defineProperty(this,t,{get:()=>this.getAttribute(t),set:e=>this.setAttribute(t,e),enumerable:!0,configurable:!0})}static query(){const t=new this;return new w(t.getTable(),t.getConnection()).setModel(this)}static async find(t){const e=new this({});return await this.query().where(e.getKeyName(),t).first()}static async findOrFail(t){const e=await this.find(t);if(!e)throw new Error(`Model not found with id: ${t}`);return e}static async create(t){const e=new this(t,!0);return await e.save(),e}static async createMany(t){const e=[];for(const s of t){const t=new this(s,!0);await t.save(),e.push(t)}return e}static async all(){return await this.query().get()}static async first(){return await this.query().first()}static async updateOrCreate(t,e={}){const s=await this.query().where(t).first();return s?(s.fill(e),await s.save(),s):await this.create({...t,...e})}async save(){const t=this.newQuery();if(!1===await this.fireModelEvent("saving"))return!1;if(this.exists){if(!1===await this.fireModelEvent("updating"))return!1;this.isDirty()&&(await this.performUpdate(t),this.fireModelEvent("updated",!1))}else{if(!1===await this.fireModelEvent("creating"))return!1;await this.performInsert(t),this.exists=!0,this.wasRecentlyCreated=!0,this.fireModelEvent("created",!1)}return this.finishSave(),this.fireModelEvent("saved",!1),!0}async update(t){return!!this.exists&&(this.fill(t),await this.save())}async delete(){return!!this.exists&&(!1!==await this.fireModelEvent("deleting")&&(await this.performDeleteOnModel(),this.exists=!1,this.fireModelEvent("deleted",!1),!0))}async refresh(){if(!this.exists)return this;const t=await this.newQuery().where(this.getKeyName(),this.getKey()).first();return t&&(this.attributes=t.attributes,this.original={...this.attributes},this.changes={}),this}replicate(t={}){const e=this.getKeyName(),s={...this.attributes};delete s[e];const r=new(0,this.constructor)(s,!0);return r.setExists(!1),r.setOriginal({}),r.changes={},r.fill(t),r}fill(t){for(const[e,s]of Object.entries(t))this.isFillable(e)&&this.setAttribute(e,s);return this}forceFill(t){return Object.entries(t).forEach(([t,e])=>{this.setAttribute(t,e)}),this}async touch(t){const e=new Date;if(this.setAttribute("updated_at",e),await this.save(),t&&t.length)for(const e of t){const t=this[e+"Relation"];if("function"==typeof t){const e=await t.call(this).get();for(const t of e)"function"==typeof t.touch&&await t.touch()}}return this}getAttribute(t){return this.hasGetMutator(t)?this.mutateAttribute(t,this.attributes[t]):this.hasCast(t)?this.castAttribute(t,this.attributes[t]):this.attributes[t]}setAttribute(t,e){this.hasSetMutator(t)&&(e=this.mutateAttributeForArray(t,e)),this.hasCast(t)&&(e=this.castAttributeAsJson(t,e));const s=this.attributes[t];return this.original[t],this.original.hasOwnProperty(t)||(this.original[t]=s),e!==this.original[t]?this.changes[t]=e:delete this.changes[t],this.attributes[t]=e,this.defineAccessor(t),this}getKey(){return this.getAttribute(this.getKeyName())}getKeyName(){return this.constructor.primaryKey}getTable(){const t=this.constructor.table;if(!t){return this.constructor.name.replace(/([A-Z])/g,"_$1").toLowerCase().slice(1)+"s"}return t}getConnection(){return this.constructor.connection}isDirty(t){return t?t.some(t=>this.changes.hasOwnProperty(t)):Object.keys(this.changes).length>0}getDirty(){return{...this.changes}}setAttributes(t){this.attributes={...t},Object.keys(this.attributes).forEach(t=>{this.defineAccessor(t)}),this.changes={}}setExists(t){this.exists=t}setOriginal(t){this.original={...t},this.changes={}}toObject(){const t={...this.attributes},e=this.getHidden(),s=this.getVisible();if(s.length>0)for(const e of Object.keys(t))s.includes(e)||delete t[e];for(const s of e)delete t[s];return t}toJSON(){return JSON.stringify(this.toObject())}newQuery(){return new w(this.getTable(),this.getConnection()).setModel(this.constructor)}async performInsert(t){this.getTimestamps()&&this.updateTimestamps();const e=this.getAttributesForInsert();await t.insert(e)}async performUpdate(t){this.getTimestamps()&&this.updateTimestamps();const e=this.getDirty();0!==Object.keys(e).length&&await t.where(this.getKeyName(),this.getKey()).update(e)}async performDeleteOnModel(){await this.newQuery().where(this.getKeyName(),this.getKey()).delete()}getAttributesForInsert(){return{...this.attributes}}updateTimestamps(){const t=new Date;this.exists||this.attributes.created_at||this.setAttribute("created_at",t),this.setAttribute("updated_at",t)}getTimestamps(){return this.constructor.timestamps}getFillable(){return this.constructor.fillable}getGuarded(){return this.constructor.guarded}getHidden(){return this.constructor.hidden}getVisible(){return this.constructor.visible}getCasts(){return this.constructor.casts}getScopes(){return this.constructor.scopes}isFillable(t){const e=this.getFillable(),s=this.getGuarded();return!(e.length>0&&!e.includes(t))&&(s.includes("*")?e.includes(t):!s.includes(t))}hasCast(t){return this.getCasts().hasOwnProperty(String(t))}castAttribute(t,e){const s=this.getCasts()[String(t)];if(null===e)return null;switch(s){case"int":case"integer":return Number.parseInt(e,10);case"real":case"float":case"double":return Number.parseFloat(e);case"string":return String(e);case"bool":case"boolean":return Boolean(e);case"object":case"array":case"json":return"string"==typeof e?JSON.parse(e):e;case"date":case"datetime":return new Date(e);default:return e}}castAttributeAsJson(t,e){const s=this.getCasts()[String(t)];return["object","array","json"].includes(s)&&"object"==typeof e?JSON.stringify(e):e}hasGetMutator(t){return"function"==typeof this[`get${this.studly(String(t))}Attribute`]}hasSetMutator(t){return"function"==typeof this[`set${this.studly(String(t))}Attribute`]}mutateAttribute(t,e){return this[`get${this.studly(String(t))}Attribute`](e)}mutateAttributeForArray(t,e){return this[`set${this.studly(String(t))}Attribute`](e)}studly(t){return t.replace(/_(.)/g,(t,e)=>e.toUpperCase()).replace(/^(.)/,t=>t.toUpperCase())}async fireModelEvent(t,e=!0){const s=`scyllinx.${t}: ${this.constructor.name}`;return console.log("Method not implemented","for debug",s),!0}finishSave(){this.original={...this.attributes},this.changes={}}getPartitionKeys(){return this.constructor.partitionKeys}getClusteringKeys(){return this.constructor.clusteringKeys}getKeyspace(){return this.constructor.keyspace}withTTL(t){return this.newQuery().ttl(t)}ifNotExists(){return this.newQuery().ifNotExists()}async load(...t){const e=Array.isArray(t)?t:[t];return await new w(this.getTable(),this.getConnection()).setModel(this.constructor).loadEagerFor(this,e),this}hasOne(t,e,s){const r=e||`${this.getTable()}_id`,i=s||this.getKeyName();return new _(this,t,r,i)}hasMany(t,e,s){const r=e||`${this.getTable()}_id`,i=s||this.getKeyName();return new T(this,t,r,i)}belongsTo(t,e,s){const r=new t,i=e||`${r.getTable()}_id`,n=s||r.getKeyName();return new b(this,t,i,n)}belongsToMany(t,e,s,r,i,n){const a=new t,o=e||[this.getTable(),a.getTable()].sort().join("_"),c=s||`${this.getTable()}_id`,h=r||`${a.getTable()}_id`,u=i||this.getKeyName(),l=n||a.getKeyName();return new v(this,t,o,c,l,u,h)}morphOne(t,e,s,r,i){const n=s||`${e}_type`,a=r||`${e}_id`,o=i||this.getKeyName();return new E(this,t,n,a,o)}morphMany(t,e,s,r,i){const n=s||`${e}_type`,a=r||`${e}_id`,o=i||this.getKeyName();return new $(this,t,n,a,o)}morphTo(t,e,s,r){const i=t||"morphable";return new C(this,e||`${i}_type`,s||`${i}_id`,r||"id")}}class S{column;foreignKeys;constructor(t,e){this.column=t,this.foreignKeys=e}references(t){const e=this.foreignKeys.find(t=>t.column===this.column);return e?e.references.column=t:this.foreignKeys.push({column:this.column,references:{table:"",column:t}}),this}on(t){const e=this.foreignKeys.find(t=>t.column===this.column);return e&&(e.references.table=t),this}onDelete(t){const e=this.foreignKeys.find(t=>t.column===this.column);return e&&(e.onDelete=t),this}onUpdate(t){const e=this.foreignKeys.find(t=>t.column===this.column);return e&&(e.onUpdate=t),this}}class K{column;constructor(t){this.column=t}nullable(){return this.column.nullable=!0,this}notNullable(){return this.column.nullable=!1,this}required(){return this.column.required=!0,this}default(t){return this.column.default=t,this}comment(t){return this.column.comment=t,this}unique(){return this.column.unique=!0,this}primary(){return this.column.primary=!0,this}autoIncrement(){return this.column.autoIncrement=!0,this}minLength(t){return this.column.minLength=t,this}maxLength(t){return this.column.maxLength=t,this}min(t){return this.column.minimum=t,this}max(t){return this.column.maximum=t,this}pattern(t){return this.column.pattern="string"==typeof t?t:t.source,this}format(t){return this.column.format=t,this}}class A{options={};compaction(t,e={}){return this.options.compaction={class:t,...e},this}compression(t){return this.options.compression=t,this}gcGraceSeconds(t){return this.options.gc_grace_seconds=t,this}caching(t,e){return this.options.caching={keys:t,rows_per_partition:e},this}defaultTTL(t){return this.options.default_time_to_live=t,this}speculativeRetry(t){return this.options.speculative_retry=t,this}comment(t){return this.options.comment=t,this}addCustomOption(t,e){return this.options[t]=e,this}build(){return this.options}}class I{tableName;columns=[];indexes=[];foreignKeys=[];partitionKeys=[];clusteringKeys=[];_clusteringOrder={};tableOptions={};tableExists=!1;constructor(t){this.tableName=t}setTableExists(t){this.tableExists=t}id(t="id"){return this.columns.push({name:t,type:"integer",primary:!0,autoIncrement:!0,nullable:!1}),this}string(t,e=255){const s={name:t,type:"string",length:e};return this.columns.push(s),new K(s)}text(t){const e={name:t,type:"text"};return this.columns.push(e),new K(e)}integer(t){const e={name:t,type:"integer"};return this.columns.push(e),new K(e)}bigInteger(t){const e={name:t,type:"bigInteger"};return this.columns.push(e),new K(e)}float(t){const e={name:t,type:"float"};return this.columns.push(e),new K(e)}double(t){const e={name:t,type:"double"};return this.columns.push(e),new K(e)}decimal(t,e=8,s=2){const r={name:t,type:`decimal(${e},${s})`};return this.columns.push(r),new K(r)}boolean(t){const e={name:t,type:"boolean"};return this.columns.push(e),new K(e)}date(t){const e={name:t,type:"date"};return this.columns.push(e),new K(e)}dateTime(t){const e={name:t,type:"dateTime"};return this.columns.push(e),new K(e)}timestamp(t){const e={name:t,type:"timestamp"};return this.columns.push(e),new K(e)}timestamps(){return this.timestamp("created_at").nullable(),this.timestamp("updated_at").nullable(),this}json(t){const e={name:t,type:"json"};return this.columns.push(e),new K(e)}uuid(t){const e={name:t,type:"uuid"};return this.columns.push(e),new K(e)}enum(t,e){const s={name:t,type:"enum",allowed:e};return this.columns.push(s),new K(s)}set(t,e){const s={name:t,type:"set",elementType:e};return this.columns.push(s),new K(s)}list(t,e){const s={name:t,type:"list",elementType:e};return this.columns.push(s),new K(s)}map(t,e,s){const r={name:t,type:"map",keyType:e,valueType:s};return this.columns.push(r),new K(r)}counter(t){const e={name:t,type:"counter"};return this.columns.push(e),new K(e)}timeUuid(t){const e={name:t,type:"timeuuid"};return this.columns.push(e),new K(e)}foreign(t){return new S(t,this.foreignKeys)}index(t,e){const s=Array.isArray(t)?t:[t];return this.indexes.push({name:e||`idx_${this.tableName}_${s.join("_")}`,columns:s}),this}unique(t,e){const s=Array.isArray(t)?t:[t];return this.indexes.push({name:e||`unq_${this.tableName}_${s.join("_")}`,columns:s,unique:!0}),this}partitionKey(...t){return this.partitionKeys=t,this}clusteringKey(...t){return this.clusteringKeys=t,this}clusteringOrder(t,e){return this._clusteringOrder[t]=e,this}withOptions(t){const e=new A;return t(e),this.tableOptions=e.build(),this}build(){return{name:this.tableName,columns:this.columns,indexes:this.indexes,foreignKeys:this.foreignKeys,partitionKeys:this.partitionKeys,clusteringKeys:this.clusteringKeys,clusteringOrder:this._clusteringOrder,tableOptions:this.tableOptions}}}class x{viewName;baseTable;selectColumns=["*"];whereConditions=[];partitionKeys=[];clusteringKeys=[];_clusteringOrder={};_ifNotExists=!1;constructor(t,e){this.viewName=t,this.baseTable=e}select(...t){return this.selectColumns=t,this}where(t){return this.whereConditions.push(t),this}partitionKey(...t){return this.partitionKeys=t,this}clusteringKey(...t){return this.clusteringKeys=t,this}clusteringOrder(t,e){return this._clusteringOrder[t]=e,this}ifNotExists(){return this._ifNotExists=!0,this}toSQL(){if(0===this.partitionKeys.length)throw new Error("Materialized view must have at least one partition key");let t=`CREATE MATERIALIZED VIEW ${this._ifNotExists?"IF NOT EXISTS ":""}${this.viewName} AS\n`;if(t+=`SELECT ${this.selectColumns.join(", ")}\n`,t+=`FROM ${this.baseTable}\n`,this.whereConditions.length>0?t+=`WHERE ${this.whereConditions.join(" AND ")}\n`:t+=`WHERE ${this.partitionKeys[0]} IS NOT NULL\n`,t+="PRIMARY KEY (",1===this.partitionKeys.length&&0===this.clusteringKeys.length?t+=this.partitionKeys[0]:(t+=`(${this.partitionKeys.join(", ")})`,this.clusteringKeys.length>0&&(t+=`, ${this.clusteringKeys.join(", ")}`)),t+=")",this.clusteringKeys.length>0&&Object.keys(this._clusteringOrder).length>0){t+=`\nWITH CLUSTERING ORDER BY (${this.clusteringKeys.map(t=>`${t} ${this._clusteringOrder[t]||"ASC"}`).join(", ")})`}return t}}class M{typeName;_fields=[];_ifNotExists=!1;constructor(t){this.typeName=t}field(t,e){return this._fields.push({name:t,type:e}),this}fields(t){for(const[e,s]of Object.entries(t))this.field(e,s);return this}ifNotExists(){return this._ifNotExists=!0,this}toSQL(){if(0===this._fields.length)throw new Error("User-defined type must have at least one field");const t=this._ifNotExists?"IF NOT EXISTS ":"",e=this._fields.map(t=>` ${t.name} ${t.type}`);return`CREATE TYPE ${t}${this.typeName} (\n${e.join(",\n")}\n)`}addField(t,e){return`ALTER TYPE ${this.typeName} ADD ${t} ${e}`}renameField(t,e){return`ALTER TYPE ${this.typeName} RENAME ${t} TO ${e}`}}class P{functionName;parameters=[];returnType="text";language="java";body="";_calledOnNullInput=!0;_ifNotExists=!1;_orReplace=!1;_security=null;constructor(t){this.functionName=t}ifNotExists(){return this._ifNotExists=!0,this}replace(){return this._orReplace=!0,this}withParams(t){return this.parameters=t,this}param(t,e){return this.parameters.push([t,e]),this}returns(t){return this.returnType=t,this}usingLanguage(t){return this.language=t,this}as(t){return this.body=t,this}calledOnNullInput(){return this._calledOnNullInput=!0,this}returnsNullOnNullInput(){return this._calledOnNullInput=!1,this}securityDefiner(){return this._security="DEFINER",this}securityInvoker(){return this._security="INVOKER",this}toSQL(){if(0===this.parameters.length)throw new Error("User-defined function must have at least one parameter");const t=this._orReplace?"CREATE OR REPLACE FUNCTION":this._ifNotExists?"CREATE FUNCTION IF NOT EXISTS":"CREATE FUNCTION",e=this.parameters.map(([t,e])=>`${t} ${e}`).join(", "),s=this._calledOnNullInput?"CALLED ON NULL INPUT":"RETURNS NULL ON NULL INPUT",r=this._security?`SECURITY ${this._security}`:"";return`\n${t} ${this.functionName}(${e})\nRETURNS ${this.returnType}\nLANGUAGE ${this.language}\n${s}\n${r}\nAS $$${this.body}$$;\n `.trim()}dropSQL(t=!0){const e=this.parameters.map(([,t])=>t).join(", ");return`DROP FUNCTION ${t?"IF EXISTS ":""}${this.functionName}(${e});`}}class D{aggregateName;parameters=[];stateFunctionName="";stateType="int";finalFunctionName;initCondition;_orReplace=!1;constructor(t){this.aggregateName=t}orReplace(){return this._orReplace=!0,this}withParameters(t){return this.parameters=t,this}stateFunction(t){return this.stateFunctionName=t,this}stateTypeIs(t){return this.stateType=t,this}finalFunction(t){return this.finalFunctionName=t,this}initialCondition(t){return this.initCondition=t,this}toSQL(){if(!this.aggregateName||0===this.parameters.length||!this.stateFunctionName)throw new Error("Aggregate name, parameters, and state function must be provided");const t=this._orReplace?"OR REPLACE ":"",e=this.parameters.join(", ");let s=`CREATE ${t}AGGREGATE ${this.aggregateName}(${e})\n`;return s+=`SFUNC ${this.stateFunctionName}\n`,s+=`STYPE ${this.stateType}`,this.finalFunctionName&&(s+=`\nFINALFUNC ${this.finalFunctionName}`),void 0!==this.initCondition&&(s+=`\nINITCOND ${this.initCondition}`),s}dropSQL(){const t=this.parameters.join(", ");return`DROP AGGREGATE IF EXISTS ${this.aggregateName}(${t})`}}class O{driver;constructor(t){this.driver=t}async createTable(t,e){const s=new I(t);e(s);const r=s.build(),i=this.driver.getGrammar().compileCreateTable(r);await this.driver.query(i)}async alterTable(t,e){const s=new I(t);s.setTableExists(!0),e(s);const r=s.build(),i=this.driver.getGrammar().compileAlterTable(r);await this.driver.query(i)}async dropTable(t){const e=`DROP TABLE ${this.driver.getGrammar().wrapTable(t)}`;await this.driver.query(e)}async dropTableIfExists(t){const e=this.driver.getGrammar();if("ScyllaDBDriver"===this.driver.constructor.name){const s=`DROP TABLE IF EXISTS ${e.wrapTable(t)}`;await this.driver.query(s)}else{await this.hasTable(t)&&await this.dropTable(t)}}async truncateTable(t){const e=`TRUNCATE ${this.driver.getGrammar().wrapTable(t)}`;await this.driver.query(e)}async createMaterializedView(t,e,s){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("Materialized views are only supported in ScyllaDB");const r=new x(t,e);s(r);const i=r.toSQL();await this.driver.query(i)}async dropMaterializedView(t){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("Materialized views are only supported in ScyllaDB");const e=`DROP MATERIALIZED VIEW IF EXISTS ${t}`;await this.driver.query(e)}async createType(t,e){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined types are only supported in ScyllaDB");const s=new M(t);e(s);const r=s.toSQL();await this.driver.query(r)}async dropType(t){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined types are only supported in ScyllaDB");const e=`DROP TYPE IF EXISTS ${t}`;await this.driver.query(e)}async createFunction(t,e){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined functions are only supported in ScyllaDB");const s=new P(t);e(s);const r=s.toSQL();await this.driver.query(r)}async dropFunction(t,e){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined functions are only supported in ScyllaDB");if(0===e.length)throw new Error("Parameter types are required to drop a UDF in ScyllaDB");const s=`DROP FUNCTION IF EXISTS ${t}(${e.join(", ")})`;await this.driver.query(s)}async createAggregate(t,e){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined aggregates are only supported in ScyllaDB");const s=new D(t);e(s);const r=s.toSQL();await this.driver.query(r)}async dropAggregate(t,e){if("ScyllaDBDriver"!==this.driver.constructor.name)throw new Error("User-defined aggregates are only supported in ScyllaDB");if(0===e.length)throw new Error("Parameter types are required to drop a UDA in ScyllaDB");const s=new D(t).withParameters(e).dropSQL();await this.driver.query(s)}async hasTable(t){const e=this.driver.getGrammar().compileTableExists(t);return(await this.driver.query(e)).rows.length>0}async hasColumn(t,e){const s=this.driver.getGrammar().compileColumnExists(t,e);return(await this.driver.query(s)).rows.length>0}async raw