@beeblock/svelar 0.6.4 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
- var zn=Object.defineProperty;var je=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var y=(c,e)=>()=>(c&&(e=c(c=0)),e);var P=(c,e)=>{for(var t in e)zn(c,t,{get:e[t],enumerable:!0})};function b(c,e){let t=Symbol.for(c),s=globalThis;return s[t]||(s[t]=e()),s[t]}var C=y(()=>{"use strict"});var v={};P(v,{Connection:()=>g});var St,g,w=y(()=>{"use strict";C();St=class{connections=new Map;config=null;defaultName="default";configure(e){this.config=e,this.defaultName=e.default}async connection(e){let t=e??this.defaultName;if(this.connections.has(t))return this.connections.get(t).drizzle;if(!this.config)throw new Error("Database not configured. Call Connection.configure() first, or register DatabaseServiceProvider.");let s=this.config.connections[t];if(!s)throw new Error(`Database connection "${t}" is not defined in configuration.`);let r=await this.createConnection(s);return this.connections.set(t,r),r.drizzle}async rawClient(e){let t=e??this.defaultName;return await this.connection(t),this.connections.get(t).rawClient}async raw(e,t=[],s){let r=await this.connection(s),n=this.getConfig(s);switch(n.driver){case"sqlite":{let o=await this.rawClient(s),i=t.map(u=>typeof u=="boolean"?u?1:0:u instanceof Date?u.toISOString():u),a=o.prepare(e),l=e.trimStart().toUpperCase();return l.startsWith("SELECT")||l.startsWith("PRAGMA")||l.startsWith("WITH")?a.all(...i):a.run(...i)}case"postgres":return(await this.rawClient(s))(e,...t);case"mysql":{let o=await this.rawClient(s),[i]=await o.execute(e,t);return i}default:throw new Error(`Unsupported driver: ${n.driver}`)}}getDriver(e){return this.getConfig(e).driver}getConfig(e){let t=e??this.defaultName;if(!this.config)throw new Error("Database not configured.");let s=this.config.connections[t];if(!s)throw new Error(`Database connection "${t}" is not defined.`);return s}async disconnect(e){if(e){let t=this.connections.get(e);t&&(await this.closeConnection(t),this.connections.delete(e))}else{for(let[t,s]of this.connections)await this.closeConnection(s);this.connections.clear()}}isConnected(e){return this.connections.has(e??this.defaultName)}async transaction(e,t){let s=this.getConfig(t),r=await this.rawClient(t);switch(s.driver){case"sqlite":{r.exec("BEGIN");try{let n=await e();return r.exec("COMMIT"),n}catch(n){throw r.exec("ROLLBACK"),n}}case"postgres":{await r`BEGIN`;try{let n=await e();return await r`COMMIT`,n}catch(n){throw await r`ROLLBACK`,n}}case"mysql":{let n=await r.getConnection();await n.beginTransaction();try{let o=await e();return await n.commit(),n.release(),o}catch(o){throw await n.rollback(),n.release(),o}}default:throw new Error(`Unsupported driver: ${s.driver}`)}}async createConnection(e){switch(e.driver){case"sqlite":return this.createSQLiteConnection(e);case"postgres":return this.createPostgresConnection(e);case"mysql":return this.createMySQLConnection(e);default:throw new Error(`Unsupported database driver: ${e.driver}`)}}async createSQLiteConnection(e){let t=e.filename??e.database??":memory:";try{let s=(await import("better-sqlite3")).default,{drizzle:r}=await import("drizzle-orm/better-sqlite3"),n=new s(t);return n.pragma("journal_mode = WAL"),n.pragma("foreign_keys = ON"),{drizzle:r(n),config:e,rawClient:n}}catch(s){let r;try{r=(await new Function("mod","return import(mod)")("node:sqlite")).DatabaseSync}catch{throw new Error(`No SQLite driver available. Install better-sqlite3 (npm install better-sqlite3) or use Node.js v22+ which includes built-in SQLite support. Original error: ${s instanceof Error?s.message:String(s)}`)}let n=new r(t);n.exec("PRAGMA journal_mode = WAL"),n.exec("PRAGMA foreign_keys = ON");let o={prepare(a){let l=n.prepare(a);return{all(...u){return l.all(...u)},run(...u){return l.run(...u)},get(...u){return l.get(...u)}}},exec(a){n.exec(a)},pragma(a){return n.prepare(`PRAGMA ${a}`).all()},close(){n.close()}},i;try{let{drizzle:a}=await import("drizzle-orm/better-sqlite3");i=a(o)}catch{i=o}return{drizzle:i,config:e,rawClient:o}}}async createPostgresConnection(e){let t=(await import("postgres")).default,{drizzle:s}=await import("drizzle-orm/postgres-js"),r=e.url??`postgres://${e.user}:${e.password}@${e.host??"localhost"}:${e.port??5432}/${e.database}`,n=t(r);return{drizzle:s(n),config:e,rawClient:n}}async createMySQLConnection(e){let t=await import("mysql2/promise"),{drizzle:s}=await import("drizzle-orm/mysql2"),r=t.createPool({host:e.host??"localhost",port:e.port??3306,database:e.database,user:e.user,password:e.password,uri:e.url});return{drizzle:s(r),config:e,rawClient:r}}async closeConnection(e){try{switch(e.config.driver){case"sqlite":e.rawClient.close();break;case"postgres":await e.rawClient.end();break;case"mysql":await e.rawClient.end();break}}catch{}}},g=b("svelar.connection",()=>new St)});var I,es,Y,j,Mr,ts=y(()=>{"use strict";w();C();I=class{constructor(e){this.column=e}nullable(){return this.column.nullable=!0,this}notNullable(){return this.column.nullable=!1,this}default(e){return this.column.defaultValue=e,this}primary(){return this.column.primaryKey=!0,this}unique(){return this.column.unique=!0,this}unsigned(){return this.column.unsigned=!0,this}references(e,t){return this.column.references={table:t,column:e},new es(this.column)}build(){return this.column}},es=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},Y=class{columns=[];indices=[];compositePrimary=null;addColumn(e,t){let s={name:e,type:t,nullable:!1,primaryKey:!1,autoIncrement:!1,unique:!1,unsigned:!1};return this.columns.push(s),new I(s)}increments(e="id"){let t={name:e,type:"INTEGER",nullable:!1,primaryKey:!0,autoIncrement:!0,unique:!1,unsigned:!0};return this.columns.push(t),new I(t)}bigIncrements(e="id"){let t={name:e,type:"BIGINT",nullable:!1,primaryKey:!0,autoIncrement:!0,unique:!1,unsigned:!0};return this.columns.push(t),new I(t)}string(e,t=255){return this.addColumn(e,`VARCHAR(${t})`)}text(e){return this.addColumn(e,"TEXT")}integer(e){return this.addColumn(e,"INTEGER")}bigInteger(e){return this.addColumn(e,"BIGINT")}float(e){return this.addColumn(e,"FLOAT")}decimal(e,t=8,s=2){return this.addColumn(e,`DECIMAL(${t},${s})`)}boolean(e){return this.addColumn(e,"BOOLEAN")}date(e){return this.addColumn(e,"DATE")}datetime(e){return this.addColumn(e,"DATETIME")}timestamp(e){return this.addColumn(e,"TIMESTAMP")}timestamps(){this.timestamp("created_at").nullable(),this.timestamp("updated_at").nullable()}json(e){return this.addColumn(e,"JSON")}blob(e){return this.addColumn(e,"BLOB")}enum(e,t){return this.addColumn(e,`ENUM(${t.map(s=>`'${s}'`).join(",")})`)}uuid(e="id"){return this.addColumn(e,"UUID")}ulid(e="id"){return this.addColumn(e,"ULID")}jsonb(e){return this.addColumn(e,"JSONB")}primary(e){this.compositePrimary=e}index(e,t){let s=Array.isArray(e)?e:[e];this.indices.push({columns:s,unique:!1,name:t})}uniqueIndex(e,t){let s=Array.isArray(e)?e:[e];this.indices.push({columns:s,unique:!0,name:t})}foreign(e){let t=this.columns.find(s=>s.name===e);if(!t)throw new Error(`Column "${e}" must be defined before adding a foreign key.`);return new I(t)}toSQL(e,t){let s=[],r=[];for(let n of this.columns)r.push(this.columnToSQL(n,t));this.compositePrimary&&r.push(`PRIMARY KEY (${this.compositePrimary.join(", ")})`);for(let n of this.columns)if(n.references){let o=`FOREIGN KEY (${n.name}) REFERENCES ${n.references.table}(${n.references.column})`;n.references.onDelete&&(o+=` ON DELETE ${n.references.onDelete}`),n.references.onUpdate&&(o+=` ON UPDATE ${n.references.onUpdate}`),r.push(o)}s.push(`CREATE TABLE ${e} (
1
+ var Yn=Object.defineProperty;var je=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var y=(c,e)=>()=>(c&&(e=c(c=0)),e);var P=(c,e)=>{for(var t in e)Yn(c,t,{get:e[t],enumerable:!0})};function b(c,e){let t=Symbol.for(c),s=globalThis;return s[t]||(s[t]=e()),s[t]}var C=y(()=>{"use strict"});var w={};P(w,{Connection:()=>g});var Ct,g,v=y(()=>{"use strict";C();Ct=class{connections=new Map;config=null;defaultName="default";configure(e){this.config=e,this.defaultName=e.default}async connection(e){let t=e??this.defaultName;if(this.connections.has(t))return this.connections.get(t).drizzle;if(!this.config)throw new Error("Database not configured. Call Connection.configure() first, or register DatabaseServiceProvider.");let s=this.config.connections[t];if(!s)throw new Error(`Database connection "${t}" is not defined in configuration.`);let r=await this.createConnection(s);return this.connections.set(t,r),r.drizzle}async rawClient(e){let t=e??this.defaultName;return await this.connection(t),this.connections.get(t).rawClient}async raw(e,t=[],s){let r=await this.connection(s),i=this.getConfig(s);switch(i.driver){case"sqlite":{let o=await this.rawClient(s),n=t.map(u=>typeof u=="boolean"?u?1:0:u instanceof Date?u.toISOString():u),a=o.prepare(e),l=e.trimStart().toUpperCase();return l.startsWith("SELECT")||l.startsWith("PRAGMA")||l.startsWith("WITH")?a.all(...n):a.run(...n)}case"postgres":return(await this.rawClient(s))(e,...t);case"mysql":{let o=await this.rawClient(s),[n]=await o.execute(e,t);return n}default:throw new Error(`Unsupported driver: ${i.driver}`)}}getDriver(e){return this.getConfig(e).driver}getConfig(e){let t=e??this.defaultName;if(!this.config)throw new Error("Database not configured.");let s=this.config.connections[t];if(!s)throw new Error(`Database connection "${t}" is not defined.`);return s}async disconnect(e){if(e){let t=this.connections.get(e);t&&(await this.closeConnection(t),this.connections.delete(e))}else{for(let[t,s]of this.connections)await this.closeConnection(s);this.connections.clear()}}isConnected(e){return this.connections.has(e??this.defaultName)}async transaction(e,t){let s=this.getConfig(t),r=await this.rawClient(t);switch(s.driver){case"sqlite":{r.exec("BEGIN");try{let i=await e();return r.exec("COMMIT"),i}catch(i){throw r.exec("ROLLBACK"),i}}case"postgres":{await r`BEGIN`;try{let i=await e();return await r`COMMIT`,i}catch(i){throw await r`ROLLBACK`,i}}case"mysql":{let i=await r.getConnection();await i.beginTransaction();try{let o=await e();return await i.commit(),i.release(),o}catch(o){throw await i.rollback(),i.release(),o}}default:throw new Error(`Unsupported driver: ${s.driver}`)}}async createConnection(e){switch(e.driver){case"sqlite":return this.createSQLiteConnection(e);case"postgres":return this.createPostgresConnection(e);case"mysql":return this.createMySQLConnection(e);default:throw new Error(`Unsupported database driver: ${e.driver}`)}}async createSQLiteConnection(e){let t=e.filename??e.database??":memory:";try{let s=(await import("better-sqlite3")).default,{drizzle:r}=await import("drizzle-orm/better-sqlite3"),i=new s(t);return i.pragma("journal_mode = WAL"),i.pragma("foreign_keys = ON"),{drizzle:r(i),config:e,rawClient:i}}catch(s){let r;try{r=(await new Function("mod","return import(mod)")("node:sqlite")).DatabaseSync}catch{throw new Error(`No SQLite driver available. Install better-sqlite3 (npm install better-sqlite3) or use Node.js v22+ which includes built-in SQLite support. Original error: ${s instanceof Error?s.message:String(s)}`)}let i=new r(t);i.exec("PRAGMA journal_mode = WAL"),i.exec("PRAGMA foreign_keys = ON");let o={prepare(a){let l=i.prepare(a);return{all(...u){return l.all(...u)},run(...u){return l.run(...u)},get(...u){return l.get(...u)}}},exec(a){i.exec(a)},pragma(a){return i.prepare(`PRAGMA ${a}`).all()},close(){i.close()}},n;try{let{drizzle:a}=await import("drizzle-orm/better-sqlite3");n=a(o)}catch{n=o}return{drizzle:n,config:e,rawClient:o}}}async createPostgresConnection(e){let t=(await import("postgres")).default,{drizzle:s}=await import("drizzle-orm/postgres-js"),r=e.url??`postgres://${e.user}:${e.password}@${e.host??"localhost"}:${e.port??5432}/${e.database}`,i=t(r);return{drizzle:s(i),config:e,rawClient:i}}async createMySQLConnection(e){let t=await import("mysql2/promise"),{drizzle:s}=await import("drizzle-orm/mysql2"),r=t.createPool({host:e.host??"localhost",port:e.port??3306,database:e.database,user:e.user,password:e.password,uri:e.url});return{drizzle:s(r),config:e,rawClient:r}}async closeConnection(e){try{switch(e.config.driver){case"sqlite":e.rawClient.close();break;case"postgres":await e.rawClient.end();break;case"mysql":await e.rawClient.end();break}}catch{}}},g=b("svelar.connection",()=>new Ct)});var q,ts,G,U,Mr,ss=y(()=>{"use strict";v();C();q=class{constructor(e){this.column=e}nullable(){return this.column.nullable=!0,this}notNullable(){return this.column.nullable=!1,this}default(e){return this.column.defaultValue=e,this}primary(){return this.column.primaryKey=!0,this}unique(){return this.column.unique=!0,this}unsigned(){return this.column.unsigned=!0,this}references(e,t){return this.column.references={table:t,column:e},new ts(this.column)}build(){return this.column}},ts=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},G=class{columns=[];indices=[];compositePrimary=null;addColumn(e,t){let s={name:e,type:t,nullable:!1,primaryKey:!1,autoIncrement:!1,unique:!1,unsigned:!1};return this.columns.push(s),new q(s)}increments(e="id"){let t={name:e,type:"INTEGER",nullable:!1,primaryKey:!0,autoIncrement:!0,unique:!1,unsigned:!0};return this.columns.push(t),new q(t)}bigIncrements(e="id"){let t={name:e,type:"BIGINT",nullable:!1,primaryKey:!0,autoIncrement:!0,unique:!1,unsigned:!0};return this.columns.push(t),new q(t)}string(e,t=255){return this.addColumn(e,`VARCHAR(${t})`)}text(e){return this.addColumn(e,"TEXT")}integer(e){return this.addColumn(e,"INTEGER")}bigInteger(e){return this.addColumn(e,"BIGINT")}float(e){return this.addColumn(e,"FLOAT")}decimal(e,t=8,s=2){return this.addColumn(e,`DECIMAL(${t},${s})`)}boolean(e){return this.addColumn(e,"BOOLEAN")}date(e){return this.addColumn(e,"DATE")}datetime(e){return this.addColumn(e,"DATETIME")}timestamp(e){return this.addColumn(e,"TIMESTAMP")}timestamps(){this.timestamp("created_at").nullable(),this.timestamp("updated_at").nullable()}json(e){return this.addColumn(e,"JSON")}blob(e){return this.addColumn(e,"BLOB")}enum(e,t){return this.addColumn(e,`ENUM(${t.map(s=>`'${s}'`).join(",")})`)}uuid(e="id"){return this.addColumn(e,"UUID")}ulid(e="id"){return this.addColumn(e,"ULID")}jsonb(e){return this.addColumn(e,"JSONB")}primary(e){this.compositePrimary=e}index(e,t){let s=Array.isArray(e)?e:[e];this.indices.push({columns:s,unique:!1,name:t})}uniqueIndex(e,t){let s=Array.isArray(e)?e:[e];this.indices.push({columns:s,unique:!0,name:t})}foreign(e){let t=this.columns.find(s=>s.name===e);if(!t)throw new Error(`Column "${e}" must be defined before adding a foreign key.`);return new q(t)}toSQL(e,t){let s=[],r=[];for(let i of this.columns)r.push(this.columnToSQL(i,t));this.compositePrimary&&r.push(`PRIMARY KEY (${this.compositePrimary.join(", ")})`);for(let i of this.columns)if(i.references){let o=`FOREIGN KEY (${i.name}) REFERENCES ${i.references.table}(${i.references.column})`;i.references.onDelete&&(o+=` ON DELETE ${i.references.onDelete}`),i.references.onUpdate&&(o+=` ON UPDATE ${i.references.onUpdate}`),r.push(o)}s.push(`CREATE TABLE ${e} (
2
2
  ${r.join(`,
3
3
  `)}
4
- )`);for(let n of this.indices){let o=n.name??`idx_${e}_${n.columns.join("_")}`,i=n.unique?"UNIQUE ":"";s.push(`CREATE ${i}INDEX ${o} ON ${e} (${n.columns.join(", ")})`)}return s}columnToSQL(e,t){let s=e.name,r=e.type;if(t==="sqlite"?r=this.mapSQLiteType(r,e):t==="postgres"?r=this.mapPostgresType(r,e):t==="mysql"&&(r=this.mapMySQLType(r,e)),s+=` ${r}`,e.primaryKey&&!this.compositePrimary&&(s+=" PRIMARY KEY",e.autoIncrement&&(t==="sqlite"?s+=" AUTOINCREMENT":t==="postgres"||t==="mysql"&&(s+=" AUTO_INCREMENT"))),!e.nullable&&!e.primaryKey&&(s+=" NOT NULL"),e.unique&&!e.primaryKey&&(s+=" UNIQUE"),e.defaultValue!==void 0){let n=typeof e.defaultValue=="string"?`'${e.defaultValue}'`:e.defaultValue===null?"NULL":e.defaultValue;s+=` DEFAULT ${n}`}return s}mapSQLiteType(e,t){return e==="BOOLEAN"?"INTEGER":e==="UUID"||e==="ULID"||e.startsWith("ENUM")||e==="JSON"||e==="JSONB"?"TEXT":e==="BIGINT"&&t.autoIncrement?"INTEGER":e}mapPostgresType(e,t){return t.autoIncrement&&e==="INTEGER"?"SERIAL":t.autoIncrement&&e==="BIGINT"?"BIGSERIAL":e==="DATETIME"?"TIMESTAMP":e==="BLOB"?"BYTEA":e.startsWith("ENUM")?"TEXT":e==="UUID"?"UUID":e==="ULID"?"VARCHAR(26)":e==="JSON"||e==="JSONB"?"JSONB":e}mapMySQLType(e,t){return e==="BOOLEAN"?"TINYINT(1)":e==="UUID"?"CHAR(36)":e==="ULID"?"CHAR(26)":e==="JSONB"?"JSON":e==="TIMESTAMP"?"DATETIME":t.unsigned&&!e.startsWith("DECIMAL")?`${e} UNSIGNED`:e}},j=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new Y;t(s);let r=g.getDriver(this.connectionName),n=s.toSQL(e,r);for(let o of n)await g.raw(o,[],this.connectionName)}async dropTable(e){await g.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async dropTableIfExists(e){await g.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async renameTable(e,t){g.getDriver(this.connectionName)==="mysql"?await g.raw(`RENAME TABLE ${e} TO ${t}`,[],this.connectionName):await g.raw(`ALTER TABLE ${e} RENAME TO ${t}`,[],this.connectionName)}async hasTable(e){let t=g.getDriver(this.connectionName),s;switch(t){case"sqlite":s=await g.raw("SELECT name FROM sqlite_master WHERE type='table' AND name=?",[e],this.connectionName);break;case"postgres":s=await g.raw("SELECT tablename FROM pg_tables WHERE tablename = $1",[e],this.connectionName);break;case"mysql":s=await g.raw("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME = ?",[e],this.connectionName);break;default:throw new Error(`Unsupported driver: ${t}`)}return s.length>0}async addColumn(e,t){let s=new Y;t(s);let r=g.getDriver(this.connectionName),n=s.columns;for(let o of n){let i=s.columnToSQL(o,r);await g.raw(`ALTER TABLE ${e} ADD COLUMN ${i}`,[],this.connectionName)}}async dropColumn(e,t){await g.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},Mr=b("svelar.schema",()=>new j)});var Lr={};P(Lr,{Migration:()=>ve,Migrator:()=>Ee});var ve,Ee,ss=y(()=>{"use strict";w();ts();ve=class{schema=new j},Ee=class{migrationsTable="svelar_migrations";connectionName;constructor(e){this.connectionName=e}async ensureMigrationsTable(){let e=new j(this.connectionName);await e.hasTable(this.migrationsTable)||await e.createTable(this.migrationsTable,s=>{s.increments("id"),s.string("migration").unique(),s.integer("batch"),s.timestamp("ran_at").default("CURRENT_TIMESTAMP")})}async run(e){await this.ensureMigrationsTable();let t=await this.getRanMigrations(),s=e.filter(o=>!t.includes(o.name));if(s.length===0)return[];let r=await this.getNextBatch(),n=[];for(let o of s)await o.migration.up(),await g.raw(`INSERT INTO ${this.migrationsTable} (migration, batch) VALUES (?, ?)`,[o.name,r],this.connectionName),n.push(o.name);return n}async rollback(e){await this.ensureMigrationsTable();let t=await this.getLastBatch();if(t===0)return[];let s=await g.raw(`SELECT migration FROM ${this.migrationsTable} WHERE batch = ? ORDER BY id DESC`,[t],this.connectionName),r=[];for(let n of s){let o=n.migration,i=e.find(a=>a.name===o);i&&(await i.migration.down(),await g.raw(`DELETE FROM ${this.migrationsTable} WHERE migration = ?`,[o],this.connectionName),r.push(o))}return r}async reset(e){let t=[];for(;;){let s=await this.rollback(e);if(s.length===0)break;t.push(...s)}return t}async refresh(e){let t=await this.reset(e),s=await this.run(e);return{reset:t,migrated:s}}async fresh(e){let t=await this.dropAllTables(),s=await this.run(e);return{dropped:t,migrated:s}}async dropAllTables(){let e=g.getDriver(this.connectionName),t=[];switch(e){case"sqlite":{t=(await g.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",[],this.connectionName)).map(r=>r.name),await g.raw("PRAGMA foreign_keys = OFF",[],this.connectionName);for(let r of t)await g.raw(`DROP TABLE IF EXISTS "${r}"`,[],this.connectionName);await g.raw("PRAGMA foreign_keys = ON",[],this.connectionName);break}case"mysql":{t=(await g.raw("SHOW TABLES",[],this.connectionName)).map(r=>Object.values(r)[0]),await g.raw("SET FOREIGN_KEY_CHECKS = 0",[],this.connectionName);for(let r of t)await g.raw(`DROP TABLE IF EXISTS \`${r}\``,[],this.connectionName);await g.raw("SET FOREIGN_KEY_CHECKS = 1",[],this.connectionName);break}case"postgres":{t=(await g.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'",[],this.connectionName)).map(r=>r.tablename);for(let r of t)await g.raw(`DROP TABLE IF EXISTS "${r}" CASCADE`,[],this.connectionName);break}default:throw new Error(`Unsupported driver for fresh: ${e}`)}return t}async getRanMigrations(){try{return(await g.raw(`SELECT migration FROM ${this.migrationsTable} ORDER BY batch, id`,[],this.connectionName)).map(t=>t.migration)}catch{return[]}}async status(e){let t=await this.getRanMigrations(),s=new Map;try{let r=await g.raw(`SELECT migration, batch FROM ${this.migrationsTable}`,[],this.connectionName);for(let n of r)s.set(n.migration,n.batch)}catch{}return e.map(r=>({name:r.name,ran:t.includes(r.name),batch:s.get(r.name)??null}))}async getNextBatch(){return await this.getLastBatch()+1}async getLastBatch(){try{return(await g.raw(`SELECT MAX(batch) as max_batch FROM ${this.migrationsTable}`,[],this.connectionName))[0]?.max_batch??0}catch{return 0}}}});var Ue={};P(Ue,{SchedulerLock:()=>Se});import{hostname as _o}from"os";async function Te(){let{Connection:c}=await Promise.resolve().then(()=>(w(),v));return c}async function Mo(){return(await Te()).getDriver()}var qr,B,Se,Ce=y(()=>{"use strict";qr=!1,B=`${_o()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;Se=class{static getOwnerId(){return B}static async ensureTable(){if(qr)return;let e=await Te();switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
4
+ )`);for(let i of this.indices){let o=i.name??`idx_${e}_${i.columns.join("_")}`,n=i.unique?"UNIQUE ":"";s.push(`CREATE ${n}INDEX ${o} ON ${e} (${i.columns.join(", ")})`)}return s}columnToSQL(e,t){let s=e.name,r=e.type;if(t==="sqlite"?r=this.mapSQLiteType(r,e):t==="postgres"?r=this.mapPostgresType(r,e):t==="mysql"&&(r=this.mapMySQLType(r,e)),s+=` ${r}`,e.primaryKey&&!this.compositePrimary&&(s+=" PRIMARY KEY",e.autoIncrement&&(t==="sqlite"?s+=" AUTOINCREMENT":t==="postgres"||t==="mysql"&&(s+=" AUTO_INCREMENT"))),!e.nullable&&!e.primaryKey&&(s+=" NOT NULL"),e.unique&&!e.primaryKey&&(s+=" UNIQUE"),e.defaultValue!==void 0){let i=typeof e.defaultValue=="string"?`'${e.defaultValue}'`:e.defaultValue===null?"NULL":e.defaultValue;s+=` DEFAULT ${i}`}return s}mapSQLiteType(e,t){return e==="BOOLEAN"?"INTEGER":e==="UUID"||e==="ULID"||e.startsWith("ENUM")||e==="JSON"||e==="JSONB"?"TEXT":e==="BIGINT"&&t.autoIncrement?"INTEGER":e}mapPostgresType(e,t){return t.autoIncrement&&e==="INTEGER"?"SERIAL":t.autoIncrement&&e==="BIGINT"?"BIGSERIAL":e==="DATETIME"?"TIMESTAMP":e==="BLOB"?"BYTEA":e.startsWith("ENUM")?"TEXT":e==="UUID"?"UUID":e==="ULID"?"VARCHAR(26)":e==="JSON"||e==="JSONB"?"JSONB":e}mapMySQLType(e,t){return e==="BOOLEAN"?"TINYINT(1)":e==="UUID"?"CHAR(36)":e==="ULID"?"CHAR(26)":e==="JSONB"?"JSON":e==="TIMESTAMP"?"DATETIME":t.unsigned&&!e.startsWith("DECIMAL")?`${e} UNSIGNED`:e}},U=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new G;t(s);let r=g.getDriver(this.connectionName),i=s.toSQL(e,r);for(let o of i)await g.raw(o,[],this.connectionName)}async dropTable(e){await g.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async dropTableIfExists(e){await g.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async renameTable(e,t){g.getDriver(this.connectionName)==="mysql"?await g.raw(`RENAME TABLE ${e} TO ${t}`,[],this.connectionName):await g.raw(`ALTER TABLE ${e} RENAME TO ${t}`,[],this.connectionName)}async hasTable(e){let t=g.getDriver(this.connectionName),s;switch(t){case"sqlite":s=await g.raw("SELECT name FROM sqlite_master WHERE type='table' AND name=?",[e],this.connectionName);break;case"postgres":s=await g.raw("SELECT tablename FROM pg_tables WHERE tablename = $1",[e],this.connectionName);break;case"mysql":s=await g.raw("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME = ?",[e],this.connectionName);break;default:throw new Error(`Unsupported driver: ${t}`)}return s.length>0}async addColumn(e,t){let s=new G;t(s);let r=g.getDriver(this.connectionName),i=s.columns;for(let o of i){let n=s.columnToSQL(o,r);await g.raw(`ALTER TABLE ${e} ADD COLUMN ${n}`,[],this.connectionName)}}async dropColumn(e,t){await g.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},Mr=b("svelar.schema",()=>new U)});var Lr={};P(Lr,{Migration:()=>we,Migrator:()=>Ee});var we,Ee,rs=y(()=>{"use strict";v();ss();we=class{schema=new U},Ee=class{migrationsTable="svelar_migrations";connectionName;constructor(e){this.connectionName=e}async ensureMigrationsTable(){let e=new U(this.connectionName);await e.hasTable(this.migrationsTable)||await e.createTable(this.migrationsTable,s=>{s.increments("id"),s.string("migration").unique(),s.integer("batch"),s.timestamp("ran_at").default("CURRENT_TIMESTAMP")})}async run(e){await this.ensureMigrationsTable();let t=await this.getRanMigrations(),s=e.filter(o=>!t.includes(o.name));if(s.length===0)return[];let r=await this.getNextBatch(),i=[];for(let o of s)await o.migration.up(),await g.raw(`INSERT INTO ${this.migrationsTable} (migration, batch) VALUES (?, ?)`,[o.name,r],this.connectionName),i.push(o.name);return i}async rollback(e){await this.ensureMigrationsTable();let t=await this.getLastBatch();if(t===0)return[];let s=await g.raw(`SELECT migration FROM ${this.migrationsTable} WHERE batch = ? ORDER BY id DESC`,[t],this.connectionName),r=[];for(let i of s){let o=i.migration,n=e.find(a=>a.name===o);n&&(await n.migration.down(),await g.raw(`DELETE FROM ${this.migrationsTable} WHERE migration = ?`,[o],this.connectionName),r.push(o))}return r}async reset(e){let t=[];for(;;){let s=await this.rollback(e);if(s.length===0)break;t.push(...s)}return t}async refresh(e){let t=await this.reset(e),s=await this.run(e);return{reset:t,migrated:s}}async fresh(e){let t=await this.dropAllTables(),s=await this.run(e);return{dropped:t,migrated:s}}async dropAllTables(){let e=g.getDriver(this.connectionName),t=[];switch(e){case"sqlite":{t=(await g.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",[],this.connectionName)).map(r=>r.name),await g.raw("PRAGMA foreign_keys = OFF",[],this.connectionName);for(let r of t)await g.raw(`DROP TABLE IF EXISTS "${r}"`,[],this.connectionName);await g.raw("PRAGMA foreign_keys = ON",[],this.connectionName);break}case"mysql":{t=(await g.raw("SHOW TABLES",[],this.connectionName)).map(r=>Object.values(r)[0]),await g.raw("SET FOREIGN_KEY_CHECKS = 0",[],this.connectionName);for(let r of t)await g.raw(`DROP TABLE IF EXISTS \`${r}\``,[],this.connectionName);await g.raw("SET FOREIGN_KEY_CHECKS = 1",[],this.connectionName);break}case"postgres":{t=(await g.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'",[],this.connectionName)).map(r=>r.tablename);for(let r of t)await g.raw(`DROP TABLE IF EXISTS "${r}" CASCADE`,[],this.connectionName);break}default:throw new Error(`Unsupported driver for fresh: ${e}`)}return t}async getRanMigrations(){try{return(await g.raw(`SELECT migration FROM ${this.migrationsTable} ORDER BY batch, id`,[],this.connectionName)).map(t=>t.migration)}catch{return[]}}async status(e){let t=await this.getRanMigrations(),s=new Map;try{let r=await g.raw(`SELECT migration, batch FROM ${this.migrationsTable}`,[],this.connectionName);for(let i of r)s.set(i.migration,i.batch)}catch{}return e.map(r=>({name:r.name,ran:t.includes(r.name),batch:s.get(r.name)??null}))}async getNextBatch(){return await this.getLastBatch()+1}async getLastBatch(){try{return(await g.raw(`SELECT MAX(batch) as max_batch FROM ${this.migrationsTable}`,[],this.connectionName))[0]?.max_batch??0}catch{return 0}}}});var He={};P(He,{SchedulerLock:()=>Se});import{hostname as No}from"os";async function Te(){let{Connection:c}=await Promise.resolve().then(()=>(v(),w));return c}async function Mo(){return(await Te()).getDriver()}var qr,K,Se,Ce=y(()=>{"use strict";qr=!1,K=`${No()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;Se=class{static getOwnerId(){return K}static async ensureTable(){if(qr)return;let e=await Te();switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
5
5
  task_key TEXT PRIMARY KEY,
6
6
  owner TEXT NOT NULL,
7
7
  expires_at TEXT NOT NULL
@@ -13,7 +13,7 @@ var zn=Object.defineProperty;var je=(c=>typeof require<"u"?require:typeof Proxy<
13
13
  task_key VARCHAR(255) PRIMARY KEY,
14
14
  owner VARCHAR(255) NOT NULL,
15
15
  expires_at DATETIME NOT NULL
16
- ) ENGINE=InnoDB`);break}qr=!0}static async acquire(e,t=5){await this.ensureTable();let s=await Te(),r=await Mo(),n=new Date().toISOString(),o=new Date(Date.now()+t*6e4).toISOString();try{await s.transaction(async()=>{switch(await s.raw("DELETE FROM scheduler_locks WHERE task_key = ? AND expires_at < ?",[e,n]),r){case"sqlite":await s.raw("INSERT OR IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,B,o]);break;case"postgres":await s.raw("INSERT INTO scheduler_locks (task_key, owner, expires_at) VALUES ($1, $2, $3) ON CONFLICT (task_key) DO NOTHING",[e,B,o]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,B,o]);break}});let i=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return i.length>0&&i[0].owner===B}catch{return!1}}static async release(e){try{await(await Te()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,B])}catch{}}static async releaseAll(){try{await(await Te()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[B])}catch{}}}});var Hr={};P(Hr,{ScheduledTask:()=>He,Scheduler:()=>as,SchedulerLock:()=>Se,cronMatches:()=>os,parseCron:()=>Ur,task:()=>Lo});function xe(c,e,t){if(c==="*")return null;let s=new Set;for(let r of c.split(",")){let[n,o]=r.split("/"),i=o?parseInt(o,10):1;if(n==="*")for(let a=e;a<=t;a+=i)s.add(a);else if(n.includes("-")){let[a,l]=n.split("-"),u=parseInt(a,10),d=parseInt(l,10);for(let h=u;h<=d;h+=i)s.add(h)}else s.add(parseInt(n,10))}return[...s].sort((r,n)=>r-n)}function Ur(c){let e=c.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${c}". Expected 5 fields.`);return{minute:xe(e[0],0,59),hour:xe(e[1],0,23),dayOfMonth:xe(e[2],1,31),month:xe(e[3],1,12),dayOfWeek:xe(e[4],0,6)}}function os(c,e){let t=Ur(c),s=e.getMinutes(),r=e.getHours(),n=e.getDate(),o=e.getMonth()+1,i=e.getDay();return!(t.minute&&!t.minute.includes(s)||t.hour&&!t.hour.includes(r)||t.dayOfMonth&&!t.dayOfMonth.includes(n)||t.month&&!t.month.includes(o)||t.dayOfWeek&&!t.dayOfWeek.includes(i))}function Lo(c,e,t){class s extends He{name=c;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var He,as,Fr=y(()=>{"use strict";Ce();He=class{name=this.constructor.name;_running=!1;withoutOverlapping=!1;_lockTtlMinutes=5;_expression="* * * * *";schedule(){return this}onSuccess(){}onFailure(e){console.error(`[Scheduler] Task "${this.name}" failed:`,e.message)}everyMinute(){return this._expression="* * * * *",this}everyMinutes(e){return this._expression=`*/${e} * * * *`,this}everyFiveMinutes(){return this.everyMinutes(5)}everyTenMinutes(){return this.everyMinutes(10)}everyFifteenMinutes(){return this.everyMinutes(15)}everyThirtyMinutes(){return this.everyMinutes(30)}hourly(){return this._expression="0 * * * *",this}hourlyAt(e){return this._expression=`${e} * * * *`,this}daily(){return this._expression="0 0 * * *",this}dailyAt(e){let[t,s]=e.split(":").map(Number);return this._expression=`${s??0} ${t} * * *`,this}twiceDaily(e=1,t=13){return this._expression=`0 ${e},${t} * * *`,this}weekly(){return this._expression="0 0 * * 0",this}weeklyOn(e,t="00:00"){let[s,r]=t.split(":").map(Number);return this._expression=`${r??0} ${s} * * ${e}`,this}weekdays(){return this._expression=`${this._expression.split(" ").slice(0,4).join(" ")} 1-5`,this}weekends(){return this._expression=`${this._expression.split(" ").slice(0,4).join(" ")} 0,6`,this}monthly(){return this._expression="0 0 1 * *",this}monthlyOn(e,t="00:00"){let[s,r]=t.split(":").map(Number);return this._expression=`${r??0} ${s} ${e} * *`,this}quarterly(){return this._expression="0 0 1 1,4,7,10 *",this}yearly(){return this._expression="0 0 1 1 *",this}cron(e){return this._expression=e,this}preventOverlap(){return this.withoutOverlapping=!0,this}lockExpiresAfter(e){return this._lockTtlMinutes=e,this}getExpression(){return this.schedule(),this._expression}isRunning(){return this._running}async executeTask(){if(this.withoutOverlapping&&this._running)return{task:this.name,success:!0,duration:0,timestamp:new Date};let e=!1;if(this.withoutOverlapping)try{let{SchedulerLock:s}=await Promise.resolve().then(()=>(Ce(),Ue));if(e=await s.acquire(this.name,this._lockTtlMinutes),!e)return{task:this.name,success:!0,duration:0,timestamp:new Date}}catch{}this._running=!0;let t=Date.now();try{await this.handle();let s=Date.now()-t;return await this.onSuccess(),{task:this.name,success:!0,duration:s,timestamp:new Date}}catch(s){let r=Date.now()-t;return await this.onFailure(s),{task:this.name,success:!1,duration:r,error:s.message,timestamp:new Date}}finally{if(this._running=!1,e)try{let{SchedulerLock:s}=await Promise.resolve().then(()=>(Ce(),Ue));await s.release(this.name)}catch{}}}},as=class{tasks=[];timer=null;history=[];maxHistory=100;_persistToDb=!1;persistToDatabase(){return this._persistToDb=!0,this}register(e){return this.tasks.push(e),this}registerMany(e){for(let t of e)this.register(t);return this}async run(e){let t=e??new Date,s=[];for(let r of this.tasks){let n=r.getExpression();if(os(n,t)){let o=await r.executeTask();s.push(o),this.addToHistory(o)}}return s}start(){if(this.timer)return;this.run().catch(s=>console.error("[Scheduler] Error:",s));let t=6e4-Date.now()%6e4;this.timer=setTimeout(()=>{this.run().catch(s=>console.error("[Scheduler] Error:",s)),this.timer=setInterval(()=>{this.run().catch(s=>console.error("[Scheduler] Error:",s))},6e4)},t),console.log(`[Scheduler] Started with ${this.tasks.length} task(s). Next tick in ${Math.round(t/1e3)}s.`)}async stop(){this.timer&&(clearTimeout(this.timer),clearInterval(this.timer),this.timer=null);try{let{SchedulerLock:e}=await Promise.resolve().then(()=>(Ce(),Ue));await e.releaseAll()}catch{}console.log("[Scheduler] Stopped.")}getTasks(){return[...this.tasks]}getHistory(){return[...this.history]}dueTasks(e){let t=e??new Date;return this.tasks.filter(s=>os(s.getExpression(),t))}remove(e){let t=this.tasks.findIndex(s=>s.name===e);return t!==-1?(this.tasks.splice(t,1),!0):!1}clear(){this.tasks=[]}addToHistory(e){this.history.push(e),this.history.length>this.maxHistory&&this.history.shift(),this._persistToDb&&this.persistResult(e).catch(()=>{})}_historyTableEnsured=!1;async ensureHistoryTable(){if(this._historyTableEnsured)return;let{Connection:e}=await Promise.resolve().then(()=>(w(),v));switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
16
+ ) ENGINE=InnoDB`);break}qr=!0}static async acquire(e,t=5){await this.ensureTable();let s=await Te(),r=await Mo(),i=new Date().toISOString(),o=new Date(Date.now()+t*6e4).toISOString();try{await s.transaction(async()=>{switch(await s.raw("DELETE FROM scheduler_locks WHERE task_key = ? AND expires_at < ?",[e,i]),r){case"sqlite":await s.raw("INSERT OR IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,K,o]);break;case"postgres":await s.raw("INSERT INTO scheduler_locks (task_key, owner, expires_at) VALUES ($1, $2, $3) ON CONFLICT (task_key) DO NOTHING",[e,K,o]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,K,o]);break}});let n=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return n.length>0&&n[0].owner===K}catch{return!1}}static async release(e){try{await(await Te()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,K])}catch{}}static async releaseAll(){try{await(await Te()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[K])}catch{}}}});var Hr={};P(Hr,{ScheduledTask:()=>Fe,Scheduler:()=>cs,SchedulerLock:()=>Se,cronMatches:()=>as,parseCron:()=>Ur,task:()=>Lo});function xe(c,e,t){if(c==="*")return null;let s=new Set;for(let r of c.split(",")){let[i,o]=r.split("/"),n=o?parseInt(o,10):1;if(i==="*")for(let a=e;a<=t;a+=n)s.add(a);else if(i.includes("-")){let[a,l]=i.split("-"),u=parseInt(a,10),d=parseInt(l,10);for(let h=u;h<=d;h+=n)s.add(h)}else s.add(parseInt(i,10))}return[...s].sort((r,i)=>r-i)}function Ur(c){let e=c.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${c}". Expected 5 fields.`);return{minute:xe(e[0],0,59),hour:xe(e[1],0,23),dayOfMonth:xe(e[2],1,31),month:xe(e[3],1,12),dayOfWeek:xe(e[4],0,6)}}function as(c,e){let t=Ur(c),s=e.getMinutes(),r=e.getHours(),i=e.getDate(),o=e.getMonth()+1,n=e.getDay();return!(t.minute&&!t.minute.includes(s)||t.hour&&!t.hour.includes(r)||t.dayOfMonth&&!t.dayOfMonth.includes(i)||t.month&&!t.month.includes(o)||t.dayOfWeek&&!t.dayOfWeek.includes(n))}function Lo(c,e,t){class s extends Fe{name=c;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var Fe,cs,Fr=y(()=>{"use strict";Ce();Fe=class{name=this.constructor.name;_running=!1;withoutOverlapping=!1;_lockTtlMinutes=5;_expression="* * * * *";schedule(){return this}onSuccess(){}onFailure(e){console.error(`[Scheduler] Task "${this.name}" failed:`,e.message)}everyMinute(){return this._expression="* * * * *",this}everyMinutes(e){return this._expression=`*/${e} * * * *`,this}everyFiveMinutes(){return this.everyMinutes(5)}everyTenMinutes(){return this.everyMinutes(10)}everyFifteenMinutes(){return this.everyMinutes(15)}everyThirtyMinutes(){return this.everyMinutes(30)}hourly(){return this._expression="0 * * * *",this}hourlyAt(e){return this._expression=`${e} * * * *`,this}daily(){return this._expression="0 0 * * *",this}dailyAt(e){let[t,s]=e.split(":").map(Number);return this._expression=`${s??0} ${t} * * *`,this}twiceDaily(e=1,t=13){return this._expression=`0 ${e},${t} * * *`,this}weekly(){return this._expression="0 0 * * 0",this}weeklyOn(e,t="00:00"){let[s,r]=t.split(":").map(Number);return this._expression=`${r??0} ${s} * * ${e}`,this}weekdays(){return this._expression=`${this._expression.split(" ").slice(0,4).join(" ")} 1-5`,this}weekends(){return this._expression=`${this._expression.split(" ").slice(0,4).join(" ")} 0,6`,this}monthly(){return this._expression="0 0 1 * *",this}monthlyOn(e,t="00:00"){let[s,r]=t.split(":").map(Number);return this._expression=`${r??0} ${s} ${e} * *`,this}quarterly(){return this._expression="0 0 1 1,4,7,10 *",this}yearly(){return this._expression="0 0 1 1 *",this}cron(e){return this._expression=e,this}preventOverlap(){return this.withoutOverlapping=!0,this}lockExpiresAfter(e){return this._lockTtlMinutes=e,this}getExpression(){return this.schedule(),this._expression}isRunning(){return this._running}async executeTask(){if(this.withoutOverlapping&&this._running)return{task:this.name,success:!0,duration:0,timestamp:new Date};let e=!1;if(this.withoutOverlapping)try{let{SchedulerLock:s}=await Promise.resolve().then(()=>(Ce(),He));if(e=await s.acquire(this.name,this._lockTtlMinutes),!e)return{task:this.name,success:!0,duration:0,timestamp:new Date}}catch{}this._running=!0;let t=Date.now();try{await this.handle();let s=Date.now()-t;return await this.onSuccess(),{task:this.name,success:!0,duration:s,timestamp:new Date}}catch(s){let r=Date.now()-t;return await this.onFailure(s),{task:this.name,success:!1,duration:r,error:s.message,timestamp:new Date}}finally{if(this._running=!1,e)try{let{SchedulerLock:s}=await Promise.resolve().then(()=>(Ce(),He));await s.release(this.name)}catch{}}}},cs=class{tasks=[];timer=null;history=[];maxHistory=100;_persistToDb=!1;persistToDatabase(){return this._persistToDb=!0,this}register(e){return this.tasks.push(e),this}registerMany(e){for(let t of e)this.register(t);return this}async run(e){let t=e??new Date,s=[];for(let r of this.tasks){let i=r.getExpression();if(as(i,t)){let o=await r.executeTask();s.push(o),this.addToHistory(o)}}return s}start(){if(this.timer)return;this.run().catch(s=>console.error("[Scheduler] Error:",s));let t=6e4-Date.now()%6e4;this.timer=setTimeout(()=>{this.run().catch(s=>console.error("[Scheduler] Error:",s)),this.timer=setInterval(()=>{this.run().catch(s=>console.error("[Scheduler] Error:",s))},6e4)},t),console.log(`[Scheduler] Started with ${this.tasks.length} task(s). Next tick in ${Math.round(t/1e3)}s.`)}async stop(){this.timer&&(clearTimeout(this.timer),clearInterval(this.timer),this.timer=null);try{let{SchedulerLock:e}=await Promise.resolve().then(()=>(Ce(),He));await e.releaseAll()}catch{}console.log("[Scheduler] Stopped.")}getTasks(){return[...this.tasks]}getHistory(){return[...this.history]}dueTasks(e){let t=e??new Date;return this.tasks.filter(s=>as(s.getExpression(),t))}remove(e){let t=this.tasks.findIndex(s=>s.name===e);return t!==-1?(this.tasks.splice(t,1),!0):!1}clear(){this.tasks=[]}addToHistory(e){this.history.push(e),this.history.length>this.maxHistory&&this.history.shift(),this._persistToDb&&this.persistResult(e).catch(()=>{})}_historyTableEnsured=!1;async ensureHistoryTable(){if(this._historyTableEnsured)return;let{Connection:e}=await Promise.resolve().then(()=>(v(),w));switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
17
17
  id INTEGER PRIMARY KEY AUTOINCREMENT,
18
18
  task TEXT NOT NULL,
19
19
  success INTEGER NOT NULL,
@@ -34,11 +34,11 @@ var zn=Object.defineProperty;var je=(c=>typeof require<"u"?require:typeof Proxy<
34
34
  duration INT NOT NULL,
35
35
  error TEXT,
36
36
  ran_at DATETIME NOT NULL
37
- ) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(w(),v));await t.raw("INSERT INTO scheduled_task_runs (task, success, duration, error, ran_at) VALUES (?, ?, ?, ?, ?)",[e.task,e.success,e.duration,e.error||null,e.timestamp.toISOString()])}catch{}}}});var Br={};P(Br,{Job:()=>Q,Queue:()=>gs});var Q,Fe,us,G,Be,ds,hs,ps,ms,gs,fs=y(()=>{"use strict";C();Q=class{attempts=0;maxAttempts=3;retryDelay=60;queue="default";failed(e){console.error(`[Queue] Job ${this.constructor.name} permanently failed:`,e.message)}retrying(e){}serialize(){let e={};for(let[t,s]of Object.entries(this))typeof s!="function"&&(e[t]=s);return JSON.stringify(e)}restore(e){for(let[t,s]of Object.entries(e))t!=="attempts"&&t!=="maxAttempts"&&t!=="retryDelay"&&t!=="queue"&&(this[t]=s)}},Fe=class{async push(e){try{e.job.attempts=1,await e.job.handle()}catch(t){if(e.attempts+1<e.maxAttempts)return e.attempts++,e.job.attempts=e.attempts+1,e.job.retrying(e.job.attempts),this.push(e);e.job.failed(t)}}async pop(){return null}async size(){return 0}async clear(){}},us=class{queues=new Map;async push(e){let t=e.queue;this.queues.has(t)||this.queues.set(t,[]),this.queues.get(t).push(e)}async pop(e="default"){let t=this.queues.get(e)??[],s=Date.now(),r=t.findIndex(n=>n.availableAt<=s);return r===-1?null:t.splice(r,1)[0]}async size(e="default"){return this.queues.get(e)?.length??0}async clear(e){e?this.queues.delete(e):this.queues.clear()}},G=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(w(),v));return e}async push(e){await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, payload, attempts, max_attempts, available_at, created_at)
37
+ ) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(v(),w));await t.raw("INSERT INTO scheduled_task_runs (task, success, duration, error, ran_at) VALUES (?, ?, ?, ?, ?)",[e.task,e.success,e.duration,e.error||null,e.timestamp.toISOString()])}catch{}}}});var Br={};P(Br,{Job:()=>X,Queue:()=>fs});var X,Be,ds,Q,Ke,hs,ps,ms,gs,fs,ys=y(()=>{"use strict";C();X=class{attempts=0;maxAttempts=3;retryDelay=60;queue="default";failed(e){console.error(`[Queue] Job ${this.constructor.name} permanently failed:`,e.message)}retrying(e){}serialize(){let e={};for(let[t,s]of Object.entries(this))typeof s!="function"&&(e[t]=s);return JSON.stringify(e)}restore(e){for(let[t,s]of Object.entries(e))t!=="attempts"&&t!=="maxAttempts"&&t!=="retryDelay"&&t!=="queue"&&(this[t]=s)}},Be=class{async push(e){try{e.job.attempts=1,await e.job.handle()}catch(t){if(e.attempts+1<e.maxAttempts)return e.attempts++,e.job.attempts=e.attempts+1,e.job.retrying(e.job.attempts),this.push(e);e.job.failed(t)}}async pop(){return null}async size(){return 0}async clear(){}},ds=class{queues=new Map;async push(e){let t=e.queue;this.queues.has(t)||this.queues.set(t,[]),this.queues.get(t).push(e)}async pop(e="default"){let t=this.queues.get(e)??[],s=Date.now(),r=t.findIndex(i=>i.availableAt<=s);return r===-1?null:t.splice(r,1)[0]}async size(e="default"){return this.queues.get(e)?.length??0}async clear(e){e?this.queues.delete(e):this.queues.clear()}},Q=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(v(),w));return e}async push(e){await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, payload, attempts, max_attempts, available_at, created_at)
38
38
  VALUES (?, ?, ?, ?, ?, ?, ?)`,[e.id,e.queue,JSON.stringify({jobClass:e.jobClass,payload:e.payload}),e.attempts,e.maxAttempts,Math.floor(e.availableAt/1e3),Math.floor(e.createdAt/1e3)])}async pop(e="default"){let t=await this.getConnection(),s=Math.floor(Date.now()/1e3),r=await t.raw(`SELECT * FROM ${this.table}
39
39
  WHERE queue = ? AND available_at <= ? AND reserved_at IS NULL
40
- ORDER BY created_at ASC LIMIT 1`,[e,s]);if(!r||r.length===0)return null;let n=r[0];await t.raw(`UPDATE ${this.table} SET reserved_at = ?, attempts = attempts + 1 WHERE id = ?`,[s,n.id]);let o=JSON.parse(n.payload),i=this.registry.resolve(o.jobClass,o.payload);return{id:n.id,jobClass:o.jobClass,payload:o.payload,queue:n.queue,attempts:n.attempts+1,maxAttempts:n.max_attempts,availableAt:n.available_at*1e3,createdAt:n.created_at*1e3,job:i}}async size(e="default"){return(await(await this.getConnection()).raw(`SELECT COUNT(*) as count FROM ${this.table} WHERE queue = ? AND reserved_at IS NULL`,[e]))?.[0]?.count??0}async clear(e){let t=await this.getConnection();e?await t.raw(`DELETE FROM ${this.table} WHERE queue = ?`,[e]):await t.raw(`DELETE FROM ${this.table}`,[])}async delete(e){await(await this.getConnection()).raw(`DELETE FROM ${this.table} WHERE id = ?`,[e])}async release(e,t=0){let s=await this.getConnection(),r=Math.floor(Date.now()/1e3)+t;await s.raw(`UPDATE ${this.table} SET reserved_at = NULL, available_at = ? WHERE id = ?`,[r,e])}},Be=class{queues=new Map;config;registry;_bullmq=null;constructor(e,t){this.config=e,this.registry=t}async getBullMQ(){if(this._bullmq)return this._bullmq;try{return this._bullmq=await Function('return import("bullmq")')(),this._bullmq}catch{throw new Error("bullmq is required for the Redis queue driver. Install it with: npm install bullmq")}}getRedisConnection(){if(this.config.url){let e=new URL(this.config.url);return{host:e.hostname||"localhost",port:parseInt(e.port)||6379,password:e.password||this.config.password||void 0,db:parseInt(e.pathname?.slice(1)||"0")||this.config.db||0}}return{host:this.config.host??"localhost",port:this.config.port??6379,password:this.config.password,db:this.config.db??0}}async getQueue(e){if(this.queues.has(e))return this.queues.get(e);let t=await this.getBullMQ(),s=this.getRedisConnection(),r=this.config.prefix??"svelar",n=new t.Queue(e,{connection:s,prefix:r,defaultJobOptions:{removeOnComplete:this.config.defaultJobOptions?.removeOnComplete??100,removeOnFail:this.config.defaultJobOptions?.removeOnFail??500}});return this.queues.set(e,n),n}async push(e){let t=await this.getQueue(e.queue),s=Math.max(0,e.availableAt-Date.now());await t.add(e.jobClass,{jobClass:e.jobClass,payload:e.payload},{jobId:e.id,delay:s>0?s:void 0,attempts:e.maxAttempts,backoff:{type:"fixed",delay:(e.job.retryDelay??60)*1e3}})}async pop(e){return null}async size(e="default"){let s=await(await this.getQueue(e)).getJobCounts("waiting","delayed","active");return s.waiting+s.delayed+s.active}async clear(e){if(e)await(await this.getQueue(e)).obliterate({force:!0});else for(let t of this.queues.values())await t.obliterate({force:!0})}async createWorker(e,t,s,r){let n=await this.getBullMQ(),o=this.getRedisConnection(),i=this.config.prefix??"svelar",a=new n.Worker(e,async l=>{let u=l.data,d=t.resolve(u.jobClass,u.payload);d.attempts=l.attemptsMade+1,await d.handle()},{connection:o,prefix:i,concurrency:r?.concurrency??1});return a.on("failed",async(l,u)=>{let d=l?.data;if(d)try{let h=t.resolve(d.jobClass,d.payload);l.attemptsMade>=(l.opts?.attempts??3)&&(h.failed(u),await s.store({id:l.id,jobClass:d.jobClass,payload:d.payload,queue:e,attempts:l.attemptsMade,maxAttempts:l.opts?.attempts??3,availableAt:Date.now(),createdAt:l.timestamp??Date.now(),job:h},u))}catch{console.error("[Queue] Failed to resolve job for failure handler:",u.message)}}),a}},ds=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(w(),v));return e}async store(e,t){try{await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, job_class, payload, exception, failed_at)
41
- VALUES (?, ?, ?, ?, ?, ?)`,[crypto.randomUUID(),e.queue,e.jobClass,e.payload,t.stack??t.message,Math.floor(Date.now()/1e3)])}catch{console.error("[Queue] Could not persist failed job (run migration to create svelar_failed_jobs table)")}}async all(){return(await(await this.getConnection()).raw(`SELECT * FROM ${this.table} ORDER BY failed_at DESC`,[])??[]).map(s=>({id:s.id,queue:s.queue,jobClass:s.job_class,payload:s.payload,exception:s.exception,failedAt:s.failed_at}))}async find(e){let s=await(await this.getConnection()).raw(`SELECT * FROM ${this.table} WHERE id = ? LIMIT 1`,[e]);if(!s||s.length===0)return null;let r=s[0];return{id:r.id,queue:r.queue,jobClass:r.job_class,payload:r.payload,exception:r.exception,failedAt:r.failed_at}}async forget(e){return await(await this.getConnection()).raw(`DELETE FROM ${this.table} WHERE id = ?`,[e]),!0}async flush(){let e=await this.getConnection(),s=(await e.raw(`SELECT COUNT(*) as count FROM ${this.table}`,[]))?.[0]?.count??0;return await e.raw(`DELETE FROM ${this.table}`,[]),s}},hs=class{jobs=new Map;register(e){this.jobs.set(e.name,e)}registerAll(e){for(let t of e)this.register(t)}resolve(e,t){let s=this.jobs.get(e);if(!s)throw new Error(`Job class "${e}" is not registered. Call Queue.register(${e}) in your app bootstrap. Registered jobs: [${[...this.jobs.keys()].join(", ")}]`);let r=Object.create(s.prototype);r.attempts=0,r.maxAttempts=3,r.retryDelay=60,r.queue="default";try{let n=JSON.parse(t);r.restore(n)}catch{}return r}has(e){return this.jobs.has(e)}},ps=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new hs;failedStore=new ds;_activeWorker=null;configure(e){this.config=e,this.drivers.clear()}register(e){this.jobRegistry.register(e)}registerAll(e){this.jobRegistry.registerAll(e)}async dispatch(e,t){let s=this.config.default,r=this.config.connections[s],n=this.resolveDriver(s);t?.queue&&(e.queue=t.queue),t?.maxAttempts!==void 0&&(e.maxAttempts=t.maxAttempts);let o={id:crypto.randomUUID(),jobClass:e.constructor.name,payload:e.serialize(),queue:e.queue??r?.queue??"default",attempts:0,maxAttempts:e.maxAttempts,availableAt:Date.now()+(t?.delay??0)*1e3,createdAt:Date.now(),job:e};await n.push(o)}async dispatchSync(e){let t=new Fe,s={id:crypto.randomUUID(),jobClass:e.constructor.name,payload:e.serialize(),queue:e.queue,attempts:0,maxAttempts:e.maxAttempts,availableAt:Date.now(),createdAt:Date.now(),job:e};await t.push(s)}async chain(e,t){if(e.length===0)return;let s=new ms(e);t?.queue&&(s.queue=t.queue),t?.maxAttempts!==void 0&&(s.maxAttempts=t.maxAttempts),await this.dispatch(s,t)}async work(e){let t=this.config.default,s=this.resolveDriver(t),r=e?.queue??"default";if(s instanceof Be){let a=await s.createWorker(r,this.jobRegistry,this.failedStore,{concurrency:e?.concurrency??1});return this.processing=!0,this._activeWorker=a,await new Promise(l=>{let u=()=>{this.processing?setTimeout(u,500):a.close().then(l).catch(l)};u()}),0}let n=e?.maxJobs??1/0,o=(e?.sleep??1)*1e3,i=0;for(this.processing=!0;this.processing&&i<n;){let a=await s.pop(r);if(!a){if(n===1/0){await new Promise(l=>setTimeout(l,o));continue}break}a.attempts++,a.job.attempts=a.attempts;try{await a.job.handle(),i++,s instanceof G&&await s.delete(a.id)}catch(l){if(a.attempts<a.maxAttempts){a.job.retrying(a.attempts);let u=a.job.retryDelay??60;s instanceof G?await s.release(a.id,u):(a.availableAt=Date.now()+u*1e3,await s.push(a))}else a.job.failed(l),await this.failedStore.store(a,l),s instanceof G&&await s.delete(a.id)}}return i}async stop(){this.processing=!1,this._activeWorker&&(await this._activeWorker.close(),this._activeWorker=null)}async size(e){return this.resolveDriver(this.config.default).size(e)}async clear(e){return this.resolveDriver(this.config.default).clear(e)}async failed(){return this.failedStore.all()}async retry(e){let t=await this.failedStore.find(e);if(!t)return!1;let s=this.jobRegistry.resolve(t.jobClass,t.payload);return s.queue=t.queue,await this.dispatch(s,{queue:t.queue}),await this.failedStore.forget(e),!0}async retryAll(){let e=await this.failedStore.all(),t=0;for(let s of e)try{let r=this.jobRegistry.resolve(s.jobClass,s.payload);r.queue=s.queue,await this.dispatch(r,{queue:s.queue}),await this.failedStore.forget(s.id),t++}catch{}return t}async forgetFailed(e){return this.failedStore.forget(e)}async flushFailed(){return this.failedStore.flush()}resolveDriver(e){if(this.drivers.has(e))return this.drivers.get(e);let t=this.config.connections[e];if(!t)throw new Error(`Queue connection "${e}" is not defined.`);let s;switch(t.driver){case"sync":s=new Fe;break;case"memory":s=new us;break;case"database":s=new G(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Be(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},ms=class extends Q{remainingJobs;constructor(e){super(),this.remainingJobs=[...e],this.maxAttempts=1}async handle(){for(let e of this.remainingJobs){let t=null,s=!1;for(let r=1;r<=e.maxAttempts;r++){e.attempts=r;try{await e.handle(),s=!0;break}catch(n){t=n,r<e.maxAttempts&&(e.retrying(r),e.retryDelay>0&&await new Promise(o=>setTimeout(o,e.retryDelay*1e3)))}}if(!s&&t)throw e.failed(t),new Error(`Chain stopped: ${e.constructor.name} failed after ${e.maxAttempts} attempt(s). Remaining jobs: [${this.remainingJobs.slice(this.remainingJobs.indexOf(e)+1).map(r=>r.constructor.name).join(", ")}]`)}}serialize(){return JSON.stringify({jobs:this.remainingJobs.map(e=>({jobClass:e.constructor.name,payload:e.serialize()}))})}},gs=b("svelar.queue",()=>new ps)});var N,bs=y(()=>{"use strict";w();N=class c{tableName;selectColumns=["*"];whereClauses=[];joinClauses=[];orderClauses=[];groupByColumns=[];havingClauses=[];limitValue=null;offsetValue=null;eagerLoads=[];isDistinct=!1;connectionName;cteClauses=[];unionClauses=[];modelClass;constructor(e,t,s){this.tableName=e,this.modelClass=t,this.connectionName=s}select(...e){return this.selectColumns=e.length>0?e:["*"],this}addSelect(...e){return this.selectColumns[0]==="*"?this.selectColumns=e:this.selectColumns.push(...e),this}distinct(){return this.isDistinct=!0,this}from(e){return this.tableName=e,this}where(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"AND"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}orWhere(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"OR"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"OR"}),this}whereIn(e,t){return this.whereClauses.push({type:"in",column:e,values:t,boolean:"AND"}),this}whereNotIn(e,t){return this.whereClauses.push({type:"notIn",column:e,values:t,boolean:"AND"}),this}whereNull(e){return this.whereClauses.push({type:"null",column:e,boolean:"AND"}),this}whereNotNull(e){return this.whereClauses.push({type:"notNull",column:e,boolean:"AND"}),this}whereBetween(e,t){return this.whereClauses.push({type:"between",column:e,values:t,boolean:"AND"}),this}whereRaw(e,t=[]){return this.whereClauses.push({type:"raw",raw:e,values:t,boolean:"AND"}),this}whereNested(e,t="AND"){let s=new c(this.tableName,this.modelClass,this.connectionName);if(e(s),s.whereClauses.length>0){let{whereSQL:r,whereBindings:n}=s.buildWhere(),o=r.replace(/^WHERE /,"");this.whereClauses.push({type:"raw",raw:`(${o})`,values:n,boolean:t})}return this}orWhereNested(e){return this.whereNested(e,"OR")}whereExists(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"exists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereNotExists(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"notExists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereSub(e,t,s){let r=new c("__placeholder__",void 0,this.connectionName);s(r);let{sql:n,bindings:o}=r.toSQL();return this.whereClauses.push({type:"sub",column:e,operator:t,subSQL:n,subBindings:o,boolean:"AND"}),this}orWhereRaw(e,t=[]){return this.whereClauses.push({type:"raw",raw:e,values:t,boolean:"OR"}),this}orWhereIn(e,t){return this.whereClauses.push({type:"in",column:e,values:t,boolean:"OR"}),this}orWhereNull(e){return this.whereClauses.push({type:"null",column:e,boolean:"OR"}),this}orWhereNotNull(e){return this.whereClauses.push({type:"notNull",column:e,boolean:"OR"}),this}withCTE(e,t,s=!1){let r=new c("__placeholder__",void 0,this.connectionName);t(r);let{sql:n,bindings:o}=r.toSQL();return this.cteClauses.push({name:e,sql:n,bindings:o,recursive:s}),this}withRecursiveCTE(e,t){return this.withCTE(e,t,!0)}withRawCTE(e,t,s=[],r=!1){return this.cteClauses.push({name:e,sql:t,bindings:s,recursive:r}),this}union(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!1}),this}unionAll(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!0}),this}join(e,t,s,r){return this.joinClauses.push({type:"INNER",table:e,first:t,operator:s,second:r}),this}leftJoin(e,t,s,r){return this.joinClauses.push({type:"LEFT",table:e,first:t,operator:s,second:r}),this}rightJoin(e,t,s,r){return this.joinClauses.push({type:"RIGHT",table:e,first:t,operator:s,second:r}),this}crossJoin(e){return this.joinClauses.push({type:"CROSS",table:e,first:"",operator:"",second:""}),this}orderBy(e,t="asc"){return this.orderClauses.push({column:e,direction:t}),this}latest(e="created_at"){return this.orderBy(e,"desc")}oldest(e="created_at"){return this.orderBy(e,"asc")}groupBy(...e){return this.groupByColumns.push(...e),this}having(e,t,s){return this.havingClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}limit(e){return this.limitValue=e,this}offset(e){return this.offsetValue=e,this}take(e){return this.limit(e)}skip(e){return this.offset(e)}with(...e){return this.eagerLoads.push(...e),this}async get(){let{sql:e,bindings:t}=this.toSQL(),s=await g.raw(e,t,this.connectionName),r=this.hydrateMany(s);return this.eagerLoads.length>0&&this.modelClass&&await this.loadRelations(r),r}async first(){return this.limitValue=1,(await this.get())[0]??null}async firstOrFail(){let e=await this.first();if(!e)throw new Error(`No results found for query on "${this.tableName}".`);return e}async find(e,t="id"){return this.where(t,e).first()}async findOrFail(e,t="id"){return this.where(t,e).firstOrFail()}async count(e="*"){let{sql:t,bindings:s}=this.buildAggregate(`COUNT(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async sum(e){let{sql:t,bindings:s}=this.buildAggregate(`SUM(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async avg(e){let{sql:t,bindings:s}=this.buildAggregate(`AVG(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async max(e){let{sql:t,bindings:s}=this.buildAggregate(`MAX(${e})`);return(await g.raw(t,s,this.connectionName))[0]?.aggregate??null}async min(e){let{sql:t,bindings:s}=this.buildAggregate(`MIN(${e})`);return(await g.raw(t,s,this.connectionName))[0]?.aggregate??null}async exists(){return await this.count()>0}async doesntExist(){return!await this.exists()}async pluck(e){return this.selectColumns=[e],(await g.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName)).map(s=>s[e])}async value(e){return this.selectColumns=[e],this.limitValue=1,(await g.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName))[0]?.[e]??null}async chunk(e,t){let s=1,r=!0;for(;r;){let n=this.clone();n.limitValue=e,n.offsetValue=(s-1)*e;let o=await n.get();if(o.length===0||await t(o,s)===!1||o.length<e)break;s++}}when(e,t){return e&&t(this),this}selectRaw(e){return this.selectColumns[0]==="*"?this.selectColumns=[e]:this.selectColumns.push(e),this}async upsert(e,t,s){let r=g.getDriver(this.connectionName),n=Object.keys(e),o=Object.values(e),i=o.map(()=>"?").join(", "),a=s??n.filter(u=>!t.includes(u)),l;if(r==="postgres"){let u=a.map(d=>`${d} = EXCLUDED.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${i}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}else if(r==="mysql"){let u=a.map(d=>`${d} = VALUES(${d})`).join(", ");l=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${i}) ON DUPLICATE KEY UPDATE ${u}`}else{let u=a.map(d=>`${d} = excluded.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${i}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}return g.raw(l,o,this.connectionName)}async insertMany(e){if(e.length===0)return;let t=Object.keys(e[0]),s=[],r=[];for(let o of e){let i=t.map(a=>o[a]);s.push(...i),r.push(`(${i.map(()=>"?").join(", ")})`)}let n=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES ${r.join(", ")}`;return g.raw(n,s,this.connectionName)}async firstOrCreate(e,t={}){for(let[o,i]of Object.entries(e))this.where(o,i);let s=await this.first();if(s)return s;let r={...e,...t},n=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new c(this.tableName,this.modelClass,this.connectionName).findOrFail(n)}async updateOrCreate(e,t){let s=new c(this.tableName,this.modelClass,this.connectionName);for(let[i,a]of Object.entries(e))s.where(i,a);let r=await s.first();if(r)return await new c(this.tableName,this.modelClass,this.connectionName).where(this.modelClass?.primaryKey??"id",r[this.modelClass?.primaryKey??"id"]).update(t),new c(this.tableName,this.modelClass,this.connectionName).findOrFail(r[this.modelClass?.primaryKey??"id"]);let n={...e,...t},o=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(n);return new c(this.tableName,this.modelClass,this.connectionName).findOrFail(o)}whereColumn(e,t,s){return s===void 0?this.whereClauses.push({type:"raw",raw:`${e} = ${t}`,values:[],boolean:"AND"}):this.whereClauses.push({type:"raw",raw:`${e} ${t} ${s}`,values:[],boolean:"AND"}),this}havingRaw(e,t=[]){return this.havingClauses.push({type:"raw",raw:e,values:t,boolean:"AND"}),this}orderByRaw(e){return this.orderClauses.push({column:e,direction:"asc"}),this.orderClauses[this.orderClauses.length-1].__raw=!0,this}selectSub(e,t){let s=new c("__placeholder__",void 0,this.connectionName);e(s);let{sql:r,bindings:n}=s.toSQL(),o=`(${r}) as ${t}`;return this.selectColumns[0]==="*"?this.selectColumns=[o]:this.selectColumns.push(o),this._selectBindings||(this._selectBindings=[]),this._selectBindings.push(...n),this}_selectBindings;async truncate(){g.getDriver(this.connectionName)==="sqlite"?(await g.raw(`DELETE FROM ${this.tableName}`,[],this.connectionName),await g.raw("DELETE FROM sqlite_sequence WHERE name = ?",[this.tableName],this.connectionName)):await g.raw(`TRUNCATE TABLE ${this.tableName}`,[],this.connectionName)}async paginate(e=1,t=15){let s=await this.clone().count(),r=Math.ceil(s/t);return this.limitValue=t,this.offsetValue=(e-1)*t,{data:await this.get(),total:s,page:e,perPage:t,lastPage:r,hasMore:e<r}}async insert(e){let t=Object.keys(e),s=Object.values(e),r=s.map(()=>"?").join(", "),n=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES (${r})`;return g.raw(n,s,this.connectionName)}async insertGetId(e,t="id"){let s=g.getDriver(this.connectionName),r=Object.keys(e),n=Object.values(e),o=n.map(()=>"?").join(", "),i=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${o})`;return s==="postgres"?(i+=` RETURNING ${t}`,(await g.raw(i,n,this.connectionName))[0]?.[t]):(await g.raw(i,n,this.connectionName),s==="sqlite"?(await g.raw("SELECT last_insert_rowid() as id",[],this.connectionName))[0]?.id:s==="mysql"?(await g.raw("SELECT LAST_INSERT_ID() as id",[],this.connectionName))[0]?.id:0)}async update(e){let t=Object.keys(e),s=Object.values(e),r=t.map(a=>`${a} = ?`).join(", "),{whereSQL:n,whereBindings:o}=this.buildWhere(),i=`UPDATE ${this.tableName} SET ${r}${n}`;return await g.raw(i,[...s,...o],this.connectionName),1}async delete(){let{whereSQL:e,whereBindings:t}=this.buildWhere(),s=`DELETE FROM ${this.tableName}${e}`;return await g.raw(s,t,this.connectionName),1}async increment(e,t=1){let{whereSQL:s,whereBindings:r}=this.buildWhere(),n=`UPDATE ${this.tableName} SET ${e} = ${e} + ?${s}`;await g.raw(n,[t,...r],this.connectionName)}async decrement(e,t=1){return this.increment(e,-t)}toSQL(){let e=[],t=[];if(this.cteClauses.length>0){let i=this.cteClauses.some(l=>l.recursive)?"WITH RECURSIVE":"WITH",a=this.cteClauses.map(l=>(t.push(...l.bindings),`${l.name} AS (${l.sql})`));e.push(`${i} ${a.join(", ")}`)}this._selectBindings?.length&&t.push(...this._selectBindings);let s=this.isDistinct?"DISTINCT ":"";e.push(`SELECT ${s}${this.selectColumns.join(", ")}`),e.push(`FROM ${this.tableName}`);for(let o of this.joinClauses)o.type==="CROSS"?e.push(`CROSS JOIN ${o.table}`):e.push(`${o.type} JOIN ${o.table} ON ${o.first} ${o.operator} ${o.second}`);let{whereSQL:r,whereBindings:n}=this.buildWhere();if(r&&(e.push(r.trim()),t.push(...n)),this.groupByColumns.length>0&&e.push(`GROUP BY ${this.groupByColumns.join(", ")}`),this.havingClauses.length>0){let o=[];for(let i of this.havingClauses)i.type==="raw"?(o.push(i.raw),i.values&&t.push(...i.values)):(o.push(`${i.column} ${i.operator} ?`),t.push(i.value));e.push(`HAVING ${o.join(" AND ")}`)}if(this.orderClauses.length>0){let o=this.orderClauses.map(i=>i.__raw?i.column:`${i.column} ${i.direction.toUpperCase()}`);e.push(`ORDER BY ${o.join(", ")}`)}if(this.limitValue!==null&&e.push(`LIMIT ${this.limitValue}`),this.offsetValue!==null&&e.push(`OFFSET ${this.offsetValue}`),this.unionClauses.length>0)for(let o of this.unionClauses)e.push(o.all?"UNION ALL":"UNION"),e.push(o.sql),t.push(...o.bindings);return{sql:e.join(" "),bindings:t}}clone(){let e=new c(this.tableName,this.modelClass,this.connectionName);return e.selectColumns=[...this.selectColumns],e.whereClauses=[...this.whereClauses],e.joinClauses=[...this.joinClauses],e.orderClauses=[...this.orderClauses],e.groupByColumns=[...this.groupByColumns],e.havingClauses=[...this.havingClauses],e.limitValue=this.limitValue,e.offsetValue=this.offsetValue,e.eagerLoads=[...this.eagerLoads],e.isDistinct=this.isDistinct,e.cteClauses=[...this.cteClauses],e.unionClauses=[...this.unionClauses],e}buildWhere(){if(this.whereClauses.length===0)return{whereSQL:"",whereBindings:[]};let e=[],t=[];for(let s=0;s<this.whereClauses.length;s++){let r=this.whereClauses[s],n=s===0?"WHERE":r.boolean;switch(r.type){case"basic":if((r.operator==="IS"||r.operator==="IS NOT")&&r.value===null){let a=(r.operator==="IS","null");e.push(`${n} ${r.column} ${r.operator} ${a}`)}else e.push(`${n} ${r.column} ${r.operator} ?`),t.push(r.value);break;case"in":let o=r.values.map(()=>"?").join(", ");e.push(`${n} ${r.column} IN (${o})`),t.push(...r.values);break;case"notIn":let i=r.values.map(()=>"?").join(", ");e.push(`${n} ${r.column} NOT IN (${i})`),t.push(...r.values);break;case"null":e.push(`${n} ${r.column} IS NULL`);break;case"notNull":e.push(`${n} ${r.column} IS NOT NULL`);break;case"between":e.push(`${n} ${r.column} BETWEEN ? AND ?`),t.push(r.values[0],r.values[1]);break;case"raw":e.push(`${n} ${r.raw}`),r.values&&t.push(...r.values);break;case"exists":e.push(`${n} EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"notExists":e.push(`${n} NOT EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"sub":e.push(`${n} ${r.column} ${r.operator} (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break}}return{whereSQL:e.join(" "),whereBindings:t}}buildAggregate(e){let t=this.selectColumns;this.selectColumns=[`${e} as aggregate`];let s=this.toSQL();return this.selectColumns=t,s}hydrateMany(e){return this.modelClass?e.map(t=>this.modelClass.hydrate(t)):e}async loadRelations(e){if(!(!this.modelClass||e.length===0))for(let t of this.eagerLoads){let r=new this.modelClass()[t]?.();r&&typeof r.eagerLoad=="function"&&await r.eagerLoad(e,t)}}}});var X,Z,ee,te,se,ws=y(()=>{"use strict";w();X=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},Z=class extends X{constructor(t,s,r,n="id"){super(t,s);this.foreignKey=r;this.localKey=n}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).first()}async eagerLoad(t,s){let r=t.map(i=>i.getAttribute(this.localKey)),n=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),o=new Map;for(let i of n)o.set(i.getAttribute(this.foreignKey),i);for(let i of t){let a=i.getAttribute(this.localKey);i.setRelation(s,o.get(a)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},ee=class extends X{constructor(t,s,r,n="id"){super(t,s);this.foreignKey=r;this.localKey=n}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).get()}async eagerLoad(t,s){let r=t.map(i=>i.getAttribute(this.localKey)),n=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),o=new Map;for(let i of n){let a=i.getAttribute(this.foreignKey);o.has(a)||o.set(a,[]),o.get(a).push(i)}for(let i of t){let a=i.getAttribute(this.localKey);i.setRelation(s,o.get(a)??[])}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}async createMany(t){let s=[];for(let r of t)s.push(await this.create(r));return s}},te=class extends X{constructor(t,s,r,n="id"){super(t,s);this.foreignKey=r;this.ownerKey=n}async load(t){let s=t.getAttribute(this.foreignKey);return s==null?null:this.relatedModel.query().where(this.ownerKey,s).first()}async eagerLoad(t,s){let r=t.map(i=>i.getAttribute(this.foreignKey)).filter(i=>i!=null);if(r.length===0){for(let i of t)i.setRelation(s,null);return}let n=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),o=new Map;for(let i of n)o.set(i.getAttribute(this.ownerKey),i);for(let i of t){let a=i.getAttribute(this.foreignKey);i.setRelation(s,o.get(a)??null)}}associate(t){return this.parentModel.setAttribute(this.foreignKey,t.getAttribute(this.ownerKey)),this.parentModel}dissociate(){return this.parentModel.setAttribute(this.foreignKey,null),this.parentModel}},se=class extends X{constructor(t,s,r,n,o,i="id",a="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=n;this.relatedPivotKey=o;this.parentKey=i;this.relatedKey=a}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,o=(await g.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(i=>i[this.relatedPivotKey]);return o.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,o).get()}async eagerLoad(t,s){let r=t.map(d=>d.getAttribute(this.parentKey));if(r.length===0){for(let d of t)d.setRelation(s,[]);return}let n=r.map(()=>"?").join(", "),o=await g.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${n})`,r),i=[...new Set(o.map(d=>d[this.relatedPivotKey]))],a=i.length>0?await this.relatedModel.query().whereIn(this.relatedKey,i).get():[],l=new Map;for(let d of a)l.set(d.getAttribute(this.relatedKey),d);let u=new Map;for(let d of o){let h=d[this.foreignPivotKey],m=d[this.relatedPivotKey],f=l.get(m);f&&(u.has(h)||u.set(h,[]),u.get(h).push(f))}for(let d of t){let h=d.getAttribute(this.parentKey);d.setRelation(s,u.get(h)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),n={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},o=Object.keys(n),i=Object.values(n),a=i.map(()=>"?").join(", ");await g.raw(`INSERT INTO ${this.pivotTable} (${o.join(", ")}) VALUES (${a})`,i)}async detach(t){let s=this.parentModel.getAttribute(this.parentKey);t?await g.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ?`,[s,t]):await g.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])}async sync(t){await this.detach();for(let s of t)await this.attach(s)}async toggle(t){let s=this.parentModel.getAttribute(this.parentKey);for(let r of t)(await g.raw(`SELECT 1 FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ? LIMIT 1`,[s,r])).length>0?await this.detach(r):await this.attach(r)}}});var Kr=y(()=>{"use strict"});var Pe,vs=y(()=>{"use strict";Pe=class{app;constructor(e){this.app=e}boot(){}}});var Wr=y(()=>{"use strict";vs();Ke()});var Re,re,Ke=y(()=>{"use strict";C();Kr();Wr();Re=class{listeners=new Map;wildcardListeners=[];onceListeners=new Map;listen(e,t){let s=typeof e=="string"?e:e.name;return this.listeners.has(s)||this.listeners.set(s,[]),this.listeners.get(s).push(t),()=>{let r=this.listeners.get(s);if(r){let n=r.indexOf(t);n>=0&&r.splice(n,1)}}}once(e,t){let s=typeof e=="string"?e:e.name;return this.onceListeners.has(s)||this.onceListeners.set(s,[]),this.onceListeners.get(s).push(t),()=>{let r=this.onceListeners.get(s);if(r){let n=r.indexOf(t);n>=0&&r.splice(n,1)}}}onAny(e){return this.wildcardListeners.push(e),()=>{let t=this.wildcardListeners.indexOf(e);t>=0&&this.wildcardListeners.splice(t,1)}}async dispatch(e){let t=e.constructor.name,s=this.listeners.get(t)??[];for(let n of s)await n(e);let r=this.onceListeners.get(t)??[];for(let n of r)await n(e);this.onceListeners.delete(t);for(let n of this.wildcardListeners)await n(t,e)}async emit(e,t){let s=this.listeners.get(e)??[];for(let n of s)await n(t);let r=this.onceListeners.get(e)??[];for(let n of r)await n(t);this.onceListeners.delete(e);for(let n of this.wildcardListeners)await n(e,t)}subscribe(e){e.subscribe(this)}forget(e){let t=typeof e=="string"?e:e.name;this.listeners.delete(t),this.onceListeners.delete(t)}flush(){this.listeners.clear(),this.onceListeners.clear(),this.wildcardListeners=[]}hasListeners(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)>0||(this.onceListeners.get(t)?.length??0)>0||this.wildcardListeners.length>0}listenerCount(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)+(this.onceListeners.get(t)?.length??0)}},re=b("svelar.event",()=>new Re)});var We,Jr=y(()=>{"use strict";bs();ws();Ke();We=class c{static table;static primaryKey="id";static incrementing=!0;static timestamps=!0;static createdAt="created_at";static updatedAt="updated_at";static casts={};static fillable=[];static hidden=[];static connection=void 0;static hooks=new Map;static observers=new Map;static events=[];attributes={};originalAttributes={};relations={};exists=!1;constructor(e){return e&&this.fill(e),new Proxy(this,{get(t,s,r){return typeof s=="symbol"||s in t||typeof s!="string"||["table","primaryKey","incrementing","timestamps","casts","fillable","hidden","connection"].includes(s)?Reflect.get(t,s,r):typeof t[s]=="function"?t[s].bind(t):t.getAttribute(s)},set(t,s,r){return typeof s=="symbol"||s in t?Reflect.set(t,s,r):(t.setAttribute(s,r),!0)}})}static query(){let e=new this,t=this;return new N(t.table,this,t.connection)}static async find(e){let t=this;return this.query().find(e,t.primaryKey)}static async findOrFail(e){let t=this;return this.query().findOrFail(e,t.primaryKey)}static async all(){return this.query().get()}static async first(){return this.query().first()}static async firstOrFail(){return this.query().firstOrFail()}static where(e,t,s){return this.query().where(e,t,s)}static whereIn(e,t){return this.query().whereIn(e,t)}static whereNull(e){return this.query().whereNull(e)}static whereNotNull(e){return this.query().whereNotNull(e)}static orderBy(e,t){return this.query().orderBy(e,t)}static latest(e){return this.query().latest(e)}static oldest(e){return this.query().oldest(e)}static with(...e){return this.query().with(...e)}static async count(){return this.query().count()}static async create(e){let t=new this,s=this;if(t.fill(e),await t.fireHook("creating"),await t.fireHook("saving"),s.timestamps){let i=new Date().toISOString();t.setAttribute(s.createdAt,i),t.setAttribute(s.updatedAt,i)}let r=t.getInsertableAttributes(),o=await new N(s.table,this,s.connection).insertGetId(r,s.primaryKey);return s.incrementing&&o&&t.setAttribute(s.primaryKey,o),t.syncOriginal(),t.exists=!0,await t.fireHook("created"),await t.fireHook("saved"),t}async save(){let e=this.constructor;if(this.exists){await this.fireHook("updating"),await this.fireHook("saving"),e.timestamps&&this.setAttribute(e.updatedAt,new Date().toISOString());let t=this.getDirty();if(Object.keys(t).length>0){let s=this.getAttribute(e.primaryKey);await new N(e.table,this.constructor,e.connection).where(e.primaryKey,s).update(t)}this.syncOriginal(),await this.fireHook("updated"),await this.fireHook("saved")}else{if(await this.fireHook("creating"),await this.fireHook("saving"),e.timestamps){let n=new Date().toISOString();this.getAttribute(e.createdAt)||this.setAttribute(e.createdAt,n),this.setAttribute(e.updatedAt,n)}let t=this.getInsertableAttributes(),r=await new N(e.table,this.constructor,e.connection).insertGetId(t,e.primaryKey);e.incrementing&&r&&this.setAttribute(e.primaryKey,r),this.syncOriginal(),this.exists=!0,await this.fireHook("created"),await this.fireHook("saved")}}async update(e){this.fill(e),await this.save()}async delete(){let e=this.constructor;await this.fireHook("deleting");let t=this.getAttribute(e.primaryKey);await new N(e.table,this.constructor,e.connection).where(e.primaryKey,t).delete(),this.exists=!1,await this.fireHook("deleted")}async refresh(){let e=this.constructor,t=this.getAttribute(e.primaryKey),s=await this.constructor.find(t);s&&(this.attributes={...s.attributes},this.syncOriginal())}getAttribute(e){let t=this.constructor,s=this.attributes[e],r=t.casts[e];if(r&&s!==void 0&&s!==null)switch(r){case"number":return Number(s);case"boolean":return!!s;case"string":return String(s);case"date":return new Date(s);case"json":return typeof s=="string"?JSON.parse(s):s}return s}setAttribute(e,t){this.constructor.casts[e]==="json"&&typeof t!="string"?this.attributes[e]=JSON.stringify(t):this.attributes[e]=t}fill(e){let t=this.constructor;for(let[s,r]of Object.entries(e))t.fillable.length>0&&!t.fillable.includes(s)||this.setAttribute(s,r)}getAttributes(){return{...this.attributes}}getOriginal(e){return e?this.originalAttributes[e]:{...this.originalAttributes}}getDirty(){let e={};for(let[t,s]of Object.entries(this.attributes))s!==this.originalAttributes[t]&&(e[t]=s);return e}isDirty(...e){let t=this.getDirty();return e.length===0?Object.keys(t).length>0:e.some(s=>s in t)}isClean(...e){return!this.isDirty(...e)}wasChanged(...e){return this.isDirty(...e)}hasOne(e,t,s){return new Z(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new ee(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new te(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,n,o){return new se(this,e,t,s,r,n??this.constructor.primaryKey,o??e.primaryKey)}setRelation(e,t){this.relations[e]=t}getRelation(e){return this.relations[e]}relationLoaded(e){return e in this.relations}toJSON(){let e=this.constructor,t={};for(let[s,r]of Object.entries(this.attributes))e.hidden.includes(s)||(t[s]=this.getAttribute(s));for(let[s,r]of Object.entries(this.relations))Array.isArray(r)?t[s]=r.map(n=>n instanceof c?n.toJSON():n):r instanceof c?t[s]=r.toJSON():t[s]=r;return t}toObject(){return this.toJSON()}static hydrate(e){let t=new this;return t.attributes={...e},t.syncOriginal(),t.exists=!0,t}static boot(e){this.hooks.set(this.name,e)}static observe(e){let t=this.observers.get(this.name)??[];t.push(e),this.observers.set(this.name,t)}static removeObservers(){this.observers.delete(this.name)}async fireHook(e){let t=this.constructor,s=c.hooks.get(t.name);s?.[e]&&await s[e](this),typeof this[e]=="function"&&await this[e]();let r=c.observers.get(t.name)??[];for(let o of r){let i=o[e];typeof i=="function"&&await i.call(o,this)}let n=t.name.toLowerCase();await re.emit(`${n}.${e}`,this)}async fireEvent(e){let t=this.constructor;if(!t.events.includes(e))throw new Error(`Event "${e}" is not declared in ${t.name}.events. Add it to: static events = ['${e}', ...];`);let s=c.observers.get(t.name)??[];for(let n of s){let o=n[e];typeof o=="function"&&await o.call(n,this)}let r=t.name.toLowerCase();await re.emit(`${r}.${e}`,this)}syncOriginal(){this.originalAttributes={...this.attributes}}getInsertableAttributes(){let e=this.constructor,t={...this.attributes};return e.incrementing&&t[e.primaryKey]===void 0&&delete t[e.primaryKey],t}static get tableName(){return this.table}}});var Je,Vr=y(()=>{"use strict";Je=class{async call(e){await new e().run()}}});var K,zr,Es=y(()=>{"use strict";C();K=class{bindings=new Map;aliases=new Map;resolved=new Set;bind(e,t){this.bindings.set(e,{factory:t,singleton:!1,tags:[]})}singleton(e,t){this.bindings.set(e,{factory:t,singleton:!0,tags:[]})}instance(e,t){this.bindings.set(e,{factory:()=>t,singleton:!0,instance:t,tags:[]})}alias(e,t){this.aliases.set(e,t)}async make(e){let t=this.resolveAlias(e),s=this.bindings.get(t);if(!s)throw new Error(`No binding found for "${e}" in the container.`);if(s.singleton&&s.instance!==void 0)return s.instance;let r=await s.factory(this);return s.singleton&&(s.instance=r),this.resolved.add(t),r}makeSync(e){let t=this.resolveAlias(e),s=this.bindings.get(t);if(!s)throw new Error(`No binding found for "${e}" in the container.`);if(s.singleton&&s.instance!==void 0)return s.instance;let r=s.factory(this);if(r instanceof Promise)throw new Error(`Binding "${e}" has an async factory. Use container.make() instead of container.makeSync().`);return s.singleton&&(s.instance=r),this.resolved.add(t),r}has(e){let t=this.resolveAlias(e);return this.bindings.has(t)}isResolved(e){return this.resolved.has(this.resolveAlias(e))}tag(e,t){for(let s of e){let r=this.bindings.get(s);r&&r.tags.push(t)}}async tagged(e){let t=[];for(let[s,r]of this.bindings)r.tags.includes(e)&&t.push(await this.make(s));return t}flush(){for(let e of this.bindings.values())e.singleton&&(e.instance=void 0);this.resolved.clear()}forget(e){this.bindings.delete(e),this.resolved.delete(e)}getBindings(){return[...this.bindings.keys()]}resolveAlias(e){return this.aliases.get(e)??e}},zr=b("svelar.container",()=>new K)});var Ve,Yr=y(()=>{"use strict";Es();Ve=class{container;providers=[];booted=!1;constructor(e){this.container=e??new K,this.container.instance("app",this),this.container.instance("container",this.container)}register(e){let t=new e(this.container);return this.providers.push(t),this}async bootstrap(){if(this.booted)return this;for(let e of this.providers)await e.register();for(let e of this.providers)await e.boot();return this.booted=!0,this}isBooted(){return this.booted}async make(e){return this.container.make(e)}getProviders(){return[...this.providers]}}});var x,q,ze,ne,Ye,ie,oe,Ge,ae,ce=y(()=>{"use strict";x=class{},q=class{middleware=[];namedMiddleware=new Map;use(e){return typeof e=="function"&&"prototype"in e&&typeof e.prototype?.handle=="function"?this.middleware.push(new e):this.middleware.push(e),this}register(e,t){return typeof t=="function"&&"prototype"in t&&typeof t.prototype?.handle=="function"?this.namedMiddleware.set(e,new t):this.namedMiddleware.set(e,t),this}get(e){return this.namedMiddleware.get(e)}async execute(e,t,s){let r=[...this.middleware];if(s)for(let o of s){let i=this.namedMiddleware.get(o);i&&r.push(i)}let n=t;for(let o=r.length-1;o>=0;o--){let i=r[o],a=n;typeof i.handle=="function"?n=()=>i.handle(e,a):n=()=>i(e,a)}return n()}count(){return this.middleware.length}},ze=class extends x{constructor(t={}){super();this.options=t}async handle(t,s){let r=await s();if(!r)return;let n=Array.isArray(this.options.origin)?this.options.origin.join(", "):this.options.origin??"*";return r.headers.set("Access-Control-Allow-Origin",n),r.headers.set("Access-Control-Allow-Methods",(this.options.methods??["GET","POST","PUT","DELETE","PATCH","OPTIONS"]).join(", ")),r.headers.set("Access-Control-Allow-Headers",(this.options.headers??["Content-Type","Authorization"]).join(", ")),this.options.credentials&&r.headers.set("Access-Control-Allow-Credentials","true"),this.options.maxAge&&r.headers.set("Access-Control-Max-Age",String(this.options.maxAge)),t.event.request.method==="OPTIONS"?new Response(null,{status:204,headers:r.headers}):r}},ne=class extends x{requests=new Map;maxRequests;windowMs;constructor(e={}){super(),this.maxRequests=e.maxRequests??60,this.windowMs=e.windowMs??6e4}async handle(e,t){let s=e.event.request.headers.get("x-forwarded-for")??e.event.getClientAddress?.()??"unknown",r=Date.now(),n=this.requests.get(s);if(n&&r<n.resetAt){if(n.count>=this.maxRequests)return new Response(JSON.stringify({error:"Too many requests"}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(Math.ceil((n.resetAt-r)/1e3))}});n.count++}else this.requests.set(s,{count:1,resetAt:r+this.windowMs});return t()}},Ye=class extends x{async handle(e,t){let s=Date.now(),r=e.event.request.method,n=e.event.url.pathname,o=await t(),i=Date.now()-s,a=o instanceof Response?o.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${n} \u2192 ${a} (${i}ms)`),o}},ie=class extends x{cookieName;headerName;fieldName;excludePaths;onlyPaths;constructor(e={}){super(),this.cookieName=e.cookieName??"XSRF-TOKEN",this.headerName=e.headerName??"X-CSRF-Token",this.fieldName=e.fieldName??"_csrf",this.excludePaths=e.excludePaths??[],this.onlyPaths=e.onlyPaths??null}async handle(e,t){let{event:s}=e,r=s.request.method.toUpperCase();if(["GET","HEAD","OPTIONS"].includes(r))return this.setTokenAndContinue(e,t);if((s.request.headers.get("authorization")??"").startsWith("Bearer "))return t();let o=s.url.pathname;if(this.onlyPaths&&!this.onlyPaths.some(l=>o.startsWith(l)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(l=>o.startsWith(l)))return t();let i=this.getCookieToken(s),a=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!i||!a||!this.timingSafeEqual(i,a)?new Response(JSON.stringify({message:"CSRF token mismatch"}),{status:419,headers:{"Content-Type":"application/json"}}):t()}async setTokenAndContinue(e,t){let s=await t();if(!(s instanceof Response))return s;let n=this.getCookieToken(e.event)||this.generateToken();return s.headers.append("Set-Cookie",`${this.cookieName}=${n}; Path=/; SameSite=Lax`),s}getCookieToken(e){let s=(e.request.headers.get("cookie")??"").match(new RegExp(`${this.cookieName}=([^;]+)`));return s?s[1]:null}async getBodyToken(e){try{let t=e.request.headers.get("content-type")??"";if(t.includes("application/x-www-form-urlencoded")||t.includes("multipart/form-data"))return(await e.request.clone().formData()).get(this.fieldName);if(t.includes("application/json"))return(await e.request.clone().json())[this.fieldName]??null}catch{}return null}generateToken(){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}timingSafeEqual(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),n=s.encode(t),o=0;for(let i=0;i<r.length;i++)o|=r[i]^n[i];return o===0}},oe=class extends x{allowedOrigins;constructor(e={}){super(),this.allowedOrigins=new Set(e.allowedOrigins??[])}async handle(e,t){let{event:s}=e,r=s.request.method.toUpperCase();if(["GET","HEAD","OPTIONS"].includes(r)||(s.request.headers.get("authorization")??"").startsWith("Bearer "))return t();let o=s.request.headers.get("origin");if(!o)return t();let i=s.url.origin;return o===i||this.allowedOrigins.has(o)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},Ge=class extends x{secret;tolerance;signatureHeader;timestampHeader;onlyPaths;constructor(e){super(),this.secret=e.secret,this.tolerance=e.tolerance??300,this.signatureHeader=e.signatureHeader??"X-Signature",this.timestampHeader=e.timestampHeader??"X-Timestamp",this.onlyPaths=e.onlyPaths??null}async handle(e,t){let{event:s}=e;if(this.onlyPaths){let E=s.url.pathname;if(!this.onlyPaths.some(T=>E.startsWith(T)))return t()}let r=s.request.headers.get(this.signatureHeader),n=s.request.headers.get(this.timestampHeader);if(!r||!n)return new Response(JSON.stringify({message:"Missing request signature"}),{status:401,headers:{"Content-Type":"application/json"}});let o=parseInt(n,10),i=Math.floor(Date.now()/1e3);if(isNaN(o)||Math.abs(i-o)>this.tolerance)return new Response(JSON.stringify({message:"Request signature expired"}),{status:401,headers:{"Content-Type":"application/json"}});let l=await s.request.clone().text(),{createHmac:u}=await import("crypto"),d=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,m=`${n}.${d}.${h}.${l}`,f=u("sha256",this.secret).update(m).digest("hex");return r.length!==f.length||!this.timingSafeCompare(r,f)?new Response(JSON.stringify({message:"Invalid request signature"}),{status:401,headers:{"Content-Type":"application/json"}}):t()}timingSafeCompare(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),n=s.encode(t),o=0;for(let i=0;i<r.length;i++)o|=r[i]^n[i];return o===0}static sign(e,t,s,r,n){let{createHmac:o}=je("crypto"),i=n??Math.floor(Date.now()/1e3),a=`${i}.${t.toUpperCase()}.${s}.${r}`;return{signature:o("sha256",e).update(a).digest("hex"),timestamp:i}}},ae=class extends x{attempts=new Map;maxAttempts;decayMinutes;constructor(e={}){super(),this.maxAttempts=e.maxAttempts??5,this.decayMinutes=e.decayMinutes??1}async handle(e,t){let r=`${e.event.request.headers.get("x-forwarded-for")??e.event.getClientAddress?.()??"unknown"}:${e.event.url.pathname}`,n=Date.now(),o=this.attempts.get(r);if(o){if(n<o.blockedUntil){let a=Math.ceil((o.blockedUntil-n)/1e3);return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}if(o.count>=this.maxAttempts){o.blockedUntil=n+this.decayMinutes*6e4,o.count=0;let a=this.decayMinutes*60;return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}}let i=await t();if(i instanceof Response&&i.status>=400&&i.status<500){let a=this.attempts.get(r)??{count:0,blockedUntil:0};if(a.count++,this.attempts.set(r,a),this.attempts.size>1e4)for(let[l,u]of this.attempts)n>u.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(l)}return i}}});import{z as le}from"zod";function Gr(c,e=!1){let t=new c;return e?{GET:t.handle("show"),PUT:t.handle("update"),PATCH:t.handle("update"),DELETE:t.handle("destroy")}:{GET:t.handle("index"),POST:t.handle("store")}}var Qe,U,$e,De,ke,Qr=y(()=>{"use strict";ce();Qe=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof x?s=new e:s=e,this.controllerMiddleware.push({middleware:s,only:t?.only,except:t?.except})}handle(e){return async t=>{try{let s=this.controllerMiddleware.filter(r=>!(r.only&&!r.only.includes(e)||r.except&&r.except.includes(e)));if(s.length>0){let r=new q;for(let{middleware:i}of s)r.use(i);let n={event:t,params:t.params,locals:t.locals},o=await r.execute(n,async()=>this.callMethod(e,t));if(o instanceof Response)return o}return await this.callMethod(e,t)}catch(s){return this.handleError(s,t)}}}json(e,t=200,s={}){let r=JSON.stringify(e,null,2);return new Response(r,{status:t,headers:{"Content-Type":"application/json",...s}})}text(e,t=200){return new Response(e,{status:t,headers:{"Content-Type":"text/plain"}})}html(e,t=200){return new Response(e,{status:t,headers:{"Content-Type":"text/html"}})}redirect(e,t=302){return new Response(null,{status:t,headers:{Location:e}})}noContent(){return new Response(null,{status:204})}created(e){return e?this.json(e,201):new Response(null,{status:201})}async validate(e,t){let s=t instanceof le.ZodObject?t:le.object(t),r,n=e.request.headers.get("content-type")??"";if(n.includes("application/json"))r=await e.request.json();else if(n.includes("multipart/form-data")||n.includes("application/x-www-form-urlencoded")){let i=await e.request.formData();r=Object.fromEntries(i)}else r=Object.fromEntries(e.url.searchParams);let o=s.safeParse(r);if(!o.success)throw new U(o.error);return o.data}validateQuery(e,t){let s=t instanceof le.ZodObject?t:le.object(t),r=Object.fromEntries(e.url.searchParams),n=s.safeParse(r);if(!n.success)throw new U(n.error);return n.data}validateParams(e,t){let r=(t instanceof le.ZodObject?t:le.object(t)).safeParse(e.params);if(!r.success)throw new U(r.error);return r.data}handleError(e,t){return e instanceof U?this.json({message:"Validation failed",errors:e.errors},422):e instanceof $e?this.json({message:e.message||"Not found"},404):e instanceof De?this.json({message:e.message||"Unauthorized"},401):e instanceof ke?this.json({message:e.message||"Forbidden"},403):(console.error("[Svelar] Controller error:",e),this.json({message:process.env.NODE_ENV==="production"?"Internal server error":e.message},500))}async callMethod(e,t){let s=this[e];if(typeof s!="function")throw new Error(`Method "${e}" not found on controller "${this.constructor.name}".`);let r=await s.call(this,t);return r instanceof Response?r:this.json(r)}};U=class extends Error{errors;constructor(e){super("Validation failed"),this.name="ValidationError",this.errors={};for(let t of e.issues){let s=t.path.join(".");this.errors[s]||(this.errors[s]=[]),this.errors[s].push(t.message)}}},$e=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},De=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},ke=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as Uo,createHmac as Xr,timingSafeEqual as Ho}from"crypto";import{promises as H}from"fs";import{join as Oe}from"path";var ue,Ae,W,Xe,Ze,et,de,Ts=y(()=>{"use strict";ce();ue=class c{constructor(e,t){this.id=e;t&&(this.data={...t},this.data._flash&&(this.previousFlashData=this.data._flash,delete this.data._flash))}data={};dirty=!1;flashData={};previousFlashData={};get(e,t){return e in this.flashData?this.flashData[e]:e in this.previousFlashData?this.previousFlashData[e]:e in this.data?this.data[e]:t}set(e,t){this.data[e]=t,this.dirty=!0}has(e){return e in this.data||e in this.flashData||e in this.previousFlashData}forget(e){delete this.data[e],this.dirty=!0}flush(){this.data={},this.dirty=!0}flash(e,t){this.flashData[e]=t,this.dirty=!0}all(){return{...this.data,...this.previousFlashData,...this.flashData}}isDirty(){return this.dirty||Object.keys(this.flashData).length>0}toPersist(){let e={...this.data};return Object.keys(this.flashData).length>0&&(e._flash=this.flashData),e}regenerateId(){let e=this.id,t=c.generateId();this.id=t,this.dirty=!0;let s=Ae.get(e);return s instanceof W&&s.markOldSessionId(e),Ae.delete(e),t}static generateId(){return Uo(32).toString("hex")}},Ae=new Map,W=class{sessions=new Map;oldSessionIds=new Set;async read(e){if(this.oldSessionIds.has(e))return null;let t=this.sessions.get(e);return t?Date.now()>t.expiresAt?(this.sessions.delete(e),null):t.data:null}async write(e,t,s){this.sessions.set(e,{data:t,expiresAt:Date.now()+s*1e3}),Ae.set(e,this)}async destroy(e){this.sessions.delete(e),Ae.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),Ae.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},Xe=class{constructor(e="sessions",t){this.tableName=e;this.connectionName=t}tableEnsured=!1;async ensureTable(){if(!this.tableEnsured)try{let{Connection:e}=await Promise.resolve().then(()=>(w(),v));switch(e.getDriver(this.connectionName)){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
40
+ ORDER BY created_at ASC LIMIT 1`,[e,s]);if(!r||r.length===0)return null;let i=r[0];await t.raw(`UPDATE ${this.table} SET reserved_at = ?, attempts = attempts + 1 WHERE id = ?`,[s,i.id]);let o=JSON.parse(i.payload),n=this.registry.resolve(o.jobClass,o.payload);return{id:i.id,jobClass:o.jobClass,payload:o.payload,queue:i.queue,attempts:i.attempts+1,maxAttempts:i.max_attempts,availableAt:i.available_at*1e3,createdAt:i.created_at*1e3,job:n}}async size(e="default"){return(await(await this.getConnection()).raw(`SELECT COUNT(*) as count FROM ${this.table} WHERE queue = ? AND reserved_at IS NULL`,[e]))?.[0]?.count??0}async clear(e){let t=await this.getConnection();e?await t.raw(`DELETE FROM ${this.table} WHERE queue = ?`,[e]):await t.raw(`DELETE FROM ${this.table}`,[])}async delete(e){await(await this.getConnection()).raw(`DELETE FROM ${this.table} WHERE id = ?`,[e])}async release(e,t=0){let s=await this.getConnection(),r=Math.floor(Date.now()/1e3)+t;await s.raw(`UPDATE ${this.table} SET reserved_at = NULL, available_at = ? WHERE id = ?`,[r,e])}},Ke=class{queues=new Map;config;registry;_bullmq=null;constructor(e,t){this.config=e,this.registry=t}async getBullMQ(){if(this._bullmq)return this._bullmq;try{return this._bullmq=await Function('return import("bullmq")')(),this._bullmq}catch{throw new Error("bullmq is required for the Redis queue driver. Install it with: npm install bullmq")}}getRedisConnection(){if(this.config.url){let e=new URL(this.config.url);return{host:e.hostname||"localhost",port:parseInt(e.port)||6379,password:e.password||this.config.password||void 0,db:parseInt(e.pathname?.slice(1)||"0")||this.config.db||0}}return{host:this.config.host??"localhost",port:this.config.port??6379,password:this.config.password,db:this.config.db??0}}async getQueue(e){if(this.queues.has(e))return this.queues.get(e);let t=await this.getBullMQ(),s=this.getRedisConnection(),r=this.config.prefix??"svelar",i=new t.Queue(e,{connection:s,prefix:r,defaultJobOptions:{removeOnComplete:this.config.defaultJobOptions?.removeOnComplete??100,removeOnFail:this.config.defaultJobOptions?.removeOnFail??500}});return this.queues.set(e,i),i}async push(e){let t=await this.getQueue(e.queue),s=Math.max(0,e.availableAt-Date.now());await t.add(e.jobClass,{jobClass:e.jobClass,payload:e.payload},{jobId:e.id,delay:s>0?s:void 0,attempts:e.maxAttempts,backoff:{type:"fixed",delay:(e.job.retryDelay??60)*1e3}})}async pop(e){return null}async size(e="default"){let s=await(await this.getQueue(e)).getJobCounts("waiting","delayed","active");return s.waiting+s.delayed+s.active}async clear(e){if(e)await(await this.getQueue(e)).obliterate({force:!0});else for(let t of this.queues.values())await t.obliterate({force:!0})}async createWorker(e,t,s,r){let i=await this.getBullMQ(),o=this.getRedisConnection(),n=this.config.prefix??"svelar",a=new i.Worker(e,async l=>{let u=l.data,d=t.resolve(u.jobClass,u.payload);d.attempts=l.attemptsMade+1,await d.handle()},{connection:o,prefix:n,concurrency:r?.concurrency??1});return a.on("failed",async(l,u)=>{let d=l?.data;if(d)try{let h=t.resolve(d.jobClass,d.payload);l.attemptsMade>=(l.opts?.attempts??3)&&(h.failed(u),await s.store({id:l.id,jobClass:d.jobClass,payload:d.payload,queue:e,attempts:l.attemptsMade,maxAttempts:l.opts?.attempts??3,availableAt:Date.now(),createdAt:l.timestamp??Date.now(),job:h},u))}catch{console.error("[Queue] Failed to resolve job for failure handler:",u.message)}}),a}},hs=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(v(),w));return e}async store(e,t){try{await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, job_class, payload, exception, failed_at)
41
+ VALUES (?, ?, ?, ?, ?, ?)`,[crypto.randomUUID(),e.queue,e.jobClass,e.payload,t.stack??t.message,Math.floor(Date.now()/1e3)])}catch{console.error("[Queue] Could not persist failed job (run migration to create svelar_failed_jobs table)")}}async all(){return(await(await this.getConnection()).raw(`SELECT * FROM ${this.table} ORDER BY failed_at DESC`,[])??[]).map(s=>({id:s.id,queue:s.queue,jobClass:s.job_class,payload:s.payload,exception:s.exception,failedAt:s.failed_at}))}async find(e){let s=await(await this.getConnection()).raw(`SELECT * FROM ${this.table} WHERE id = ? LIMIT 1`,[e]);if(!s||s.length===0)return null;let r=s[0];return{id:r.id,queue:r.queue,jobClass:r.job_class,payload:r.payload,exception:r.exception,failedAt:r.failed_at}}async forget(e){return await(await this.getConnection()).raw(`DELETE FROM ${this.table} WHERE id = ?`,[e]),!0}async flush(){let e=await this.getConnection(),s=(await e.raw(`SELECT COUNT(*) as count FROM ${this.table}`,[]))?.[0]?.count??0;return await e.raw(`DELETE FROM ${this.table}`,[]),s}},ps=class{jobs=new Map;register(e){this.jobs.set(e.name,e)}registerAll(e){for(let t of e)this.register(t)}resolve(e,t){let s=this.jobs.get(e);if(!s)throw new Error(`Job class "${e}" is not registered. Call Queue.register(${e}) in your app bootstrap. Registered jobs: [${[...this.jobs.keys()].join(", ")}]`);let r=Object.create(s.prototype);r.attempts=0,r.maxAttempts=3,r.retryDelay=60,r.queue="default";try{let i=JSON.parse(t);r.restore(i)}catch{}return r}has(e){return this.jobs.has(e)}},ms=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new ps;failedStore=new hs;_activeWorker=null;configure(e){this.config=e,this.drivers.clear()}register(e){this.jobRegistry.register(e)}registerAll(e){this.jobRegistry.registerAll(e)}async dispatch(e,t){let s=this.config.default,r=this.config.connections[s],i=this.resolveDriver(s);t?.queue&&(e.queue=t.queue),t?.maxAttempts!==void 0&&(e.maxAttempts=t.maxAttempts);let o={id:crypto.randomUUID(),jobClass:e.constructor.name,payload:e.serialize(),queue:e.queue??r?.queue??"default",attempts:0,maxAttempts:e.maxAttempts,availableAt:Date.now()+(t?.delay??0)*1e3,createdAt:Date.now(),job:e};await i.push(o)}async dispatchSync(e){let t=new Be,s={id:crypto.randomUUID(),jobClass:e.constructor.name,payload:e.serialize(),queue:e.queue,attempts:0,maxAttempts:e.maxAttempts,availableAt:Date.now(),createdAt:Date.now(),job:e};await t.push(s)}async chain(e,t){if(e.length===0)return;let s=new gs(e);t?.queue&&(s.queue=t.queue),t?.maxAttempts!==void 0&&(s.maxAttempts=t.maxAttempts),await this.dispatch(s,t)}async work(e){let t=this.config.default,s=this.resolveDriver(t),r=e?.queue??"default";if(s instanceof Ke){let a=await s.createWorker(r,this.jobRegistry,this.failedStore,{concurrency:e?.concurrency??1});return this.processing=!0,this._activeWorker=a,await new Promise(l=>{let u=()=>{this.processing?setTimeout(u,500):a.close().then(l).catch(l)};u()}),0}let i=e?.maxJobs??1/0,o=(e?.sleep??1)*1e3,n=0;for(this.processing=!0;this.processing&&n<i;){let a=await s.pop(r);if(!a){if(i===1/0){await new Promise(l=>setTimeout(l,o));continue}break}a.attempts++,a.job.attempts=a.attempts;try{await a.job.handle(),n++,s instanceof Q&&await s.delete(a.id)}catch(l){if(a.attempts<a.maxAttempts){a.job.retrying(a.attempts);let u=a.job.retryDelay??60;s instanceof Q?await s.release(a.id,u):(a.availableAt=Date.now()+u*1e3,await s.push(a))}else a.job.failed(l),await this.failedStore.store(a,l),s instanceof Q&&await s.delete(a.id)}}return n}async stop(){this.processing=!1,this._activeWorker&&(await this._activeWorker.close(),this._activeWorker=null)}async size(e){return this.resolveDriver(this.config.default).size(e)}async clear(e){return this.resolveDriver(this.config.default).clear(e)}async failed(){return this.failedStore.all()}async retry(e){let t=await this.failedStore.find(e);if(!t)return!1;let s=this.jobRegistry.resolve(t.jobClass,t.payload);return s.queue=t.queue,await this.dispatch(s,{queue:t.queue}),await this.failedStore.forget(e),!0}async retryAll(){let e=await this.failedStore.all(),t=0;for(let s of e)try{let r=this.jobRegistry.resolve(s.jobClass,s.payload);r.queue=s.queue,await this.dispatch(r,{queue:s.queue}),await this.failedStore.forget(s.id),t++}catch{}return t}async forgetFailed(e){return this.failedStore.forget(e)}async flushFailed(){return this.failedStore.flush()}resolveDriver(e){if(this.drivers.has(e))return this.drivers.get(e);let t=this.config.connections[e];if(!t)throw new Error(`Queue connection "${e}" is not defined.`);let s;switch(t.driver){case"sync":s=new Be;break;case"memory":s=new ds;break;case"database":s=new Q(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Ke(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},gs=class extends X{remainingJobs;constructor(e){super(),this.remainingJobs=[...e],this.maxAttempts=1}async handle(){for(let e of this.remainingJobs){let t=null,s=!1;for(let r=1;r<=e.maxAttempts;r++){e.attempts=r;try{await e.handle(),s=!0;break}catch(i){t=i,r<e.maxAttempts&&(e.retrying(r),e.retryDelay>0&&await new Promise(o=>setTimeout(o,e.retryDelay*1e3)))}}if(!s&&t)throw e.failed(t),new Error(`Chain stopped: ${e.constructor.name} failed after ${e.maxAttempts} attempt(s). Remaining jobs: [${this.remainingJobs.slice(this.remainingJobs.indexOf(e)+1).map(r=>r.constructor.name).join(", ")}]`)}}serialize(){return JSON.stringify({jobs:this.remainingJobs.map(e=>({jobClass:e.constructor.name,payload:e.serialize()}))})}},fs=b("svelar.queue",()=>new ms)});var A,vs=y(()=>{"use strict";v();A=class c{tableName;selectColumns=["*"];whereClauses=[];joinClauses=[];orderClauses=[];groupByColumns=[];havingClauses=[];limitValue=null;offsetValue=null;eagerLoads=[];isDistinct=!1;connectionName;cteClauses=[];unionClauses=[];modelClass;constructor(e,t,s){this.tableName=e,this.modelClass=t,this.connectionName=s}select(...e){return this.selectColumns=e.length>0?e:["*"],this}addSelect(...e){return this.selectColumns[0]==="*"?this.selectColumns=e:this.selectColumns.push(...e),this}distinct(){return this.isDistinct=!0,this}from(e){return this.tableName=e,this}where(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"AND"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}orWhere(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"OR"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"OR"}),this}whereIn(e,t){return this.whereClauses.push({type:"in",column:e,values:t,boolean:"AND"}),this}whereNotIn(e,t){return this.whereClauses.push({type:"notIn",column:e,values:t,boolean:"AND"}),this}whereNull(e){return this.whereClauses.push({type:"null",column:e,boolean:"AND"}),this}whereNotNull(e){return this.whereClauses.push({type:"notNull",column:e,boolean:"AND"}),this}whereBetween(e,t){return this.whereClauses.push({type:"between",column:e,values:t,boolean:"AND"}),this}whereRaw(e,t=[]){return this.whereClauses.push({type:"raw",raw:e,values:t,boolean:"AND"}),this}whereNested(e,t="AND"){let s=new c(this.tableName,this.modelClass,this.connectionName);if(e(s),s.whereClauses.length>0){let{whereSQL:r,whereBindings:i}=s.buildWhere(),o=r.replace(/^WHERE /,"");this.whereClauses.push({type:"raw",raw:`(${o})`,values:i,boolean:t})}return this}orWhereNested(e){return this.whereNested(e,"OR")}whereExists(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"exists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereNotExists(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"notExists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereSub(e,t,s){let r=new c("__placeholder__",void 0,this.connectionName);s(r);let{sql:i,bindings:o}=r.toSQL();return this.whereClauses.push({type:"sub",column:e,operator:t,subSQL:i,subBindings:o,boolean:"AND"}),this}orWhereRaw(e,t=[]){return this.whereClauses.push({type:"raw",raw:e,values:t,boolean:"OR"}),this}orWhereIn(e,t){return this.whereClauses.push({type:"in",column:e,values:t,boolean:"OR"}),this}orWhereNull(e){return this.whereClauses.push({type:"null",column:e,boolean:"OR"}),this}orWhereNotNull(e){return this.whereClauses.push({type:"notNull",column:e,boolean:"OR"}),this}withCTE(e,t,s=!1){let r=new c("__placeholder__",void 0,this.connectionName);t(r);let{sql:i,bindings:o}=r.toSQL();return this.cteClauses.push({name:e,sql:i,bindings:o,recursive:s}),this}withRecursiveCTE(e,t){return this.withCTE(e,t,!0)}withRawCTE(e,t,s=[],r=!1){return this.cteClauses.push({name:e,sql:t,bindings:s,recursive:r}),this}union(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!1}),this}unionAll(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!0}),this}join(e,t,s,r){return this.joinClauses.push({type:"INNER",table:e,first:t,operator:s,second:r}),this}leftJoin(e,t,s,r){return this.joinClauses.push({type:"LEFT",table:e,first:t,operator:s,second:r}),this}rightJoin(e,t,s,r){return this.joinClauses.push({type:"RIGHT",table:e,first:t,operator:s,second:r}),this}crossJoin(e){return this.joinClauses.push({type:"CROSS",table:e,first:"",operator:"",second:""}),this}orderBy(e,t="asc"){return this.orderClauses.push({column:e,direction:t}),this}latest(e="created_at"){return this.orderBy(e,"desc")}oldest(e="created_at"){return this.orderBy(e,"asc")}groupBy(...e){return this.groupByColumns.push(...e),this}having(e,t,s){return this.havingClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}limit(e){return this.limitValue=e,this}offset(e){return this.offsetValue=e,this}take(e){return this.limit(e)}skip(e){return this.offset(e)}with(...e){return this.eagerLoads.push(...e),this}async get(){let{sql:e,bindings:t}=this.toSQL(),s=await g.raw(e,t,this.connectionName),r=this.hydrateMany(s);return this.eagerLoads.length>0&&this.modelClass&&await this.loadRelations(r),r}async first(){return this.limitValue=1,(await this.get())[0]??null}async firstOrFail(){let e=await this.first();if(!e)throw new Error(`No results found for query on "${this.tableName}".`);return e}async find(e,t="id"){return this.where(t,e).first()}async findOrFail(e,t="id"){return this.where(t,e).firstOrFail()}async count(e="*"){let{sql:t,bindings:s}=this.buildAggregate(`COUNT(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async sum(e){let{sql:t,bindings:s}=this.buildAggregate(`SUM(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async avg(e){let{sql:t,bindings:s}=this.buildAggregate(`AVG(${e})`),r=await g.raw(t,s,this.connectionName);return Number(r[0]?.aggregate??0)}async max(e){let{sql:t,bindings:s}=this.buildAggregate(`MAX(${e})`);return(await g.raw(t,s,this.connectionName))[0]?.aggregate??null}async min(e){let{sql:t,bindings:s}=this.buildAggregate(`MIN(${e})`);return(await g.raw(t,s,this.connectionName))[0]?.aggregate??null}async exists(){return await this.count()>0}async doesntExist(){return!await this.exists()}async pluck(e){return this.selectColumns=[e],(await g.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName)).map(s=>s[e])}async value(e){return this.selectColumns=[e],this.limitValue=1,(await g.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName))[0]?.[e]??null}async chunk(e,t){let s=1,r=!0;for(;r;){let i=this.clone();i.limitValue=e,i.offsetValue=(s-1)*e;let o=await i.get();if(o.length===0||await t(o,s)===!1||o.length<e)break;s++}}when(e,t){return e&&t(this),this}selectRaw(e){return this.selectColumns[0]==="*"?this.selectColumns=[e]:this.selectColumns.push(e),this}async upsert(e,t,s){let r=g.getDriver(this.connectionName),i=Object.keys(e),o=Object.values(e),n=o.map(()=>"?").join(", "),a=s??i.filter(u=>!t.includes(u)),l;if(r==="postgres"){let u=a.map(d=>`${d} = EXCLUDED.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}else if(r==="mysql"){let u=a.map(d=>`${d} = VALUES(${d})`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON DUPLICATE KEY UPDATE ${u}`}else{let u=a.map(d=>`${d} = excluded.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}return g.raw(l,o,this.connectionName)}async insertMany(e){if(e.length===0)return;let t=Object.keys(e[0]),s=[],r=[];for(let o of e){let n=t.map(a=>o[a]);s.push(...n),r.push(`(${n.map(()=>"?").join(", ")})`)}let i=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES ${r.join(", ")}`;return g.raw(i,s,this.connectionName)}async firstOrCreate(e,t={}){for(let[o,n]of Object.entries(e))this.where(o,n);let s=await this.first();if(s)return s;let r={...e,...t},i=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new c(this.tableName,this.modelClass,this.connectionName).findOrFail(i)}async updateOrCreate(e,t){let s=new c(this.tableName,this.modelClass,this.connectionName);for(let[n,a]of Object.entries(e))s.where(n,a);let r=await s.first();if(r)return await new c(this.tableName,this.modelClass,this.connectionName).where(this.modelClass?.primaryKey??"id",r[this.modelClass?.primaryKey??"id"]).update(t),new c(this.tableName,this.modelClass,this.connectionName).findOrFail(r[this.modelClass?.primaryKey??"id"]);let i={...e,...t},o=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(i);return new c(this.tableName,this.modelClass,this.connectionName).findOrFail(o)}whereColumn(e,t,s){return s===void 0?this.whereClauses.push({type:"raw",raw:`${e} = ${t}`,values:[],boolean:"AND"}):this.whereClauses.push({type:"raw",raw:`${e} ${t} ${s}`,values:[],boolean:"AND"}),this}havingRaw(e,t=[]){return this.havingClauses.push({type:"raw",raw:e,values:t,boolean:"AND"}),this}orderByRaw(e){return this.orderClauses.push({column:e,direction:"asc"}),this.orderClauses[this.orderClauses.length-1].__raw=!0,this}selectSub(e,t){let s=new c("__placeholder__",void 0,this.connectionName);e(s);let{sql:r,bindings:i}=s.toSQL(),o=`(${r}) as ${t}`;return this.selectColumns[0]==="*"?this.selectColumns=[o]:this.selectColumns.push(o),this._selectBindings||(this._selectBindings=[]),this._selectBindings.push(...i),this}_selectBindings;async truncate(){g.getDriver(this.connectionName)==="sqlite"?(await g.raw(`DELETE FROM ${this.tableName}`,[],this.connectionName),await g.raw("DELETE FROM sqlite_sequence WHERE name = ?",[this.tableName],this.connectionName)):await g.raw(`TRUNCATE TABLE ${this.tableName}`,[],this.connectionName)}async paginate(e=1,t=15){let s=await this.clone().count(),r=Math.ceil(s/t);return this.limitValue=t,this.offsetValue=(e-1)*t,{data:await this.get(),total:s,page:e,perPage:t,lastPage:r,hasMore:e<r}}async insert(e){let t=Object.keys(e),s=Object.values(e),r=s.map(()=>"?").join(", "),i=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES (${r})`;return g.raw(i,s,this.connectionName)}async insertGetId(e,t="id"){let s=g.getDriver(this.connectionName),r=Object.keys(e),i=Object.values(e),o=i.map(()=>"?").join(", "),n=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${o})`;return s==="postgres"?(n+=` RETURNING ${t}`,(await g.raw(n,i,this.connectionName))[0]?.[t]):(await g.raw(n,i,this.connectionName),s==="sqlite"?(await g.raw("SELECT last_insert_rowid() as id",[],this.connectionName))[0]?.id:s==="mysql"?(await g.raw("SELECT LAST_INSERT_ID() as id",[],this.connectionName))[0]?.id:0)}async update(e){let t=Object.keys(e),s=Object.values(e),r=t.map(a=>`${a} = ?`).join(", "),{whereSQL:i,whereBindings:o}=this.buildWhere(),n=`UPDATE ${this.tableName} SET ${r}${i}`;return await g.raw(n,[...s,...o],this.connectionName),1}async delete(){let{whereSQL:e,whereBindings:t}=this.buildWhere(),s=`DELETE FROM ${this.tableName}${e}`;return await g.raw(s,t,this.connectionName),1}async increment(e,t=1){let{whereSQL:s,whereBindings:r}=this.buildWhere(),i=`UPDATE ${this.tableName} SET ${e} = ${e} + ?${s}`;await g.raw(i,[t,...r],this.connectionName)}async decrement(e,t=1){return this.increment(e,-t)}toSQL(){let e=[],t=[];if(this.cteClauses.length>0){let n=this.cteClauses.some(l=>l.recursive)?"WITH RECURSIVE":"WITH",a=this.cteClauses.map(l=>(t.push(...l.bindings),`${l.name} AS (${l.sql})`));e.push(`${n} ${a.join(", ")}`)}this._selectBindings?.length&&t.push(...this._selectBindings);let s=this.isDistinct?"DISTINCT ":"";e.push(`SELECT ${s}${this.selectColumns.join(", ")}`),e.push(`FROM ${this.tableName}`);for(let o of this.joinClauses)o.type==="CROSS"?e.push(`CROSS JOIN ${o.table}`):e.push(`${o.type} JOIN ${o.table} ON ${o.first} ${o.operator} ${o.second}`);let{whereSQL:r,whereBindings:i}=this.buildWhere();if(r&&(e.push(r.trim()),t.push(...i)),this.groupByColumns.length>0&&e.push(`GROUP BY ${this.groupByColumns.join(", ")}`),this.havingClauses.length>0){let o=[];for(let n of this.havingClauses)n.type==="raw"?(o.push(n.raw),n.values&&t.push(...n.values)):(o.push(`${n.column} ${n.operator} ?`),t.push(n.value));e.push(`HAVING ${o.join(" AND ")}`)}if(this.orderClauses.length>0){let o=this.orderClauses.map(n=>n.__raw?n.column:`${n.column} ${n.direction.toUpperCase()}`);e.push(`ORDER BY ${o.join(", ")}`)}if(this.limitValue!==null&&e.push(`LIMIT ${this.limitValue}`),this.offsetValue!==null&&e.push(`OFFSET ${this.offsetValue}`),this.unionClauses.length>0)for(let o of this.unionClauses)e.push(o.all?"UNION ALL":"UNION"),e.push(o.sql),t.push(...o.bindings);return{sql:e.join(" "),bindings:t}}clone(){let e=new c(this.tableName,this.modelClass,this.connectionName);return e.selectColumns=[...this.selectColumns],e.whereClauses=[...this.whereClauses],e.joinClauses=[...this.joinClauses],e.orderClauses=[...this.orderClauses],e.groupByColumns=[...this.groupByColumns],e.havingClauses=[...this.havingClauses],e.limitValue=this.limitValue,e.offsetValue=this.offsetValue,e.eagerLoads=[...this.eagerLoads],e.isDistinct=this.isDistinct,e.cteClauses=[...this.cteClauses],e.unionClauses=[...this.unionClauses],e}buildWhere(){if(this.whereClauses.length===0)return{whereSQL:"",whereBindings:[]};let e=[],t=[];for(let s=0;s<this.whereClauses.length;s++){let r=this.whereClauses[s],i=s===0?"WHERE":r.boolean;switch(r.type){case"basic":if((r.operator==="IS"||r.operator==="IS NOT")&&r.value===null){let a=(r.operator==="IS","null");e.push(`${i} ${r.column} ${r.operator} ${a}`)}else e.push(`${i} ${r.column} ${r.operator} ?`),t.push(r.value);break;case"in":let o=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} IN (${o})`),t.push(...r.values);break;case"notIn":let n=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} NOT IN (${n})`),t.push(...r.values);break;case"null":e.push(`${i} ${r.column} IS NULL`);break;case"notNull":e.push(`${i} ${r.column} IS NOT NULL`);break;case"between":e.push(`${i} ${r.column} BETWEEN ? AND ?`),t.push(r.values[0],r.values[1]);break;case"raw":e.push(`${i} ${r.raw}`),r.values&&t.push(...r.values);break;case"exists":e.push(`${i} EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"notExists":e.push(`${i} NOT EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"sub":e.push(`${i} ${r.column} ${r.operator} (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break}}return{whereSQL:e.join(" "),whereBindings:t}}buildAggregate(e){let t=this.selectColumns;this.selectColumns=[`${e} as aggregate`];let s=this.toSQL();return this.selectColumns=t,s}hydrateMany(e){return this.modelClass?e.map(t=>this.modelClass.hydrate(t)):e}async loadRelations(e){if(!(!this.modelClass||e.length===0))for(let t of this.eagerLoads){let r=new this.modelClass()[t]?.();r&&typeof r.eagerLoad=="function"&&await r.eagerLoad(e,t)}}}});var Z,ee,te,se,re,ws=y(()=>{"use strict";v();Z=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},ee=class extends Z{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.localKey=i}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).first()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),o=new Map;for(let n of i)o.set(n.getAttribute(this.foreignKey),n);for(let n of t){let a=n.getAttribute(this.localKey);n.setRelation(s,o.get(a)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},te=class extends Z{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.localKey=i}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).get()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),o=new Map;for(let n of i){let a=n.getAttribute(this.foreignKey);o.has(a)||o.set(a,[]),o.get(a).push(n)}for(let n of t){let a=n.getAttribute(this.localKey);n.setRelation(s,o.get(a)??[])}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}async createMany(t){let s=[];for(let r of t)s.push(await this.create(r));return s}},se=class extends Z{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.ownerKey=i}async load(t){let s=t.getAttribute(this.foreignKey);return s==null?null:this.relatedModel.query().where(this.ownerKey,s).first()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.foreignKey)).filter(n=>n!=null);if(r.length===0){for(let n of t)n.setRelation(s,null);return}let i=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),o=new Map;for(let n of i)o.set(n.getAttribute(this.ownerKey),n);for(let n of t){let a=n.getAttribute(this.foreignKey);n.setRelation(s,o.get(a)??null)}}associate(t){return this.parentModel.setAttribute(this.foreignKey,t.getAttribute(this.ownerKey)),this.parentModel}dissociate(){return this.parentModel.setAttribute(this.foreignKey,null),this.parentModel}},re=class extends Z{constructor(t,s,r,i,o,n="id",a="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=i;this.relatedPivotKey=o;this.parentKey=n;this.relatedKey=a}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,o=(await g.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(n=>n[this.relatedPivotKey]);return o.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,o).get()}async eagerLoad(t,s){let r=t.map(d=>d.getAttribute(this.parentKey));if(r.length===0){for(let d of t)d.setRelation(s,[]);return}let i=r.map(()=>"?").join(", "),o=await g.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${i})`,r),n=[...new Set(o.map(d=>d[this.relatedPivotKey]))],a=n.length>0?await this.relatedModel.query().whereIn(this.relatedKey,n).get():[],l=new Map;for(let d of a)l.set(d.getAttribute(this.relatedKey),d);let u=new Map;for(let d of o){let h=d[this.foreignPivotKey],m=d[this.relatedPivotKey],f=l.get(m);f&&(u.has(h)||u.set(h,[]),u.get(h).push(f))}for(let d of t){let h=d.getAttribute(this.parentKey);d.setRelation(s,u.get(h)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),i={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},o=Object.keys(i),n=Object.values(i),a=n.map(()=>"?").join(", ");await g.raw(`INSERT INTO ${this.pivotTable} (${o.join(", ")}) VALUES (${a})`,n)}async detach(t){let s=this.parentModel.getAttribute(this.parentKey);t?await g.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ?`,[s,t]):await g.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])}async sync(t){await this.detach();for(let s of t)await this.attach(s)}async toggle(t){let s=this.parentModel.getAttribute(this.parentKey);for(let r of t)(await g.raw(`SELECT 1 FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ? LIMIT 1`,[s,r])).length>0?await this.detach(r):await this.attach(r)}}});var Kr=y(()=>{"use strict"});var Re,Es=y(()=>{"use strict";Re=class{app;constructor(e){this.app=e}boot(){}}});var Wr=y(()=>{"use strict";Es();We()});var Pe,ne,We=y(()=>{"use strict";C();Kr();Wr();Pe=class{listeners=new Map;wildcardListeners=[];onceListeners=new Map;listen(e,t){let s=typeof e=="string"?e:e.name;return this.listeners.has(s)||this.listeners.set(s,[]),this.listeners.get(s).push(t),()=>{let r=this.listeners.get(s);if(r){let i=r.indexOf(t);i>=0&&r.splice(i,1)}}}once(e,t){let s=typeof e=="string"?e:e.name;return this.onceListeners.has(s)||this.onceListeners.set(s,[]),this.onceListeners.get(s).push(t),()=>{let r=this.onceListeners.get(s);if(r){let i=r.indexOf(t);i>=0&&r.splice(i,1)}}}onAny(e){return this.wildcardListeners.push(e),()=>{let t=this.wildcardListeners.indexOf(e);t>=0&&this.wildcardListeners.splice(t,1)}}async dispatch(e){let t=e.constructor.name,s=this.listeners.get(t)??[];for(let i of s)await i(e);let r=this.onceListeners.get(t)??[];for(let i of r)await i(e);this.onceListeners.delete(t);for(let i of this.wildcardListeners)await i(t,e)}async emit(e,t){let s=this.listeners.get(e)??[];for(let i of s)await i(t);let r=this.onceListeners.get(e)??[];for(let i of r)await i(t);this.onceListeners.delete(e);for(let i of this.wildcardListeners)await i(e,t)}subscribe(e){e.subscribe(this)}forget(e){let t=typeof e=="string"?e:e.name;this.listeners.delete(t),this.onceListeners.delete(t)}flush(){this.listeners.clear(),this.onceListeners.clear(),this.wildcardListeners=[]}hasListeners(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)>0||(this.onceListeners.get(t)?.length??0)>0||this.wildcardListeners.length>0}listenerCount(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)+(this.onceListeners.get(t)?.length??0)}},ne=b("svelar.event",()=>new Pe)});var ze,zr=y(()=>{"use strict";vs();ws();We();ze=class c{static table;static primaryKey="id";static incrementing=!0;static timestamps=!0;static createdAt="created_at";static updatedAt="updated_at";static casts={};static fillable=[];static hidden=[];static connection=void 0;static hooks=new Map;static observers=new Map;static events=[];attributes={};originalAttributes={};relations={};exists=!1;constructor(e){return e&&this.fill(e),new Proxy(this,{get(t,s,r){return typeof s=="symbol"||s in t||typeof s!="string"||["table","primaryKey","incrementing","timestamps","casts","fillable","hidden","connection"].includes(s)?Reflect.get(t,s,r):typeof t[s]=="function"?t[s].bind(t):t.getAttribute(s)},set(t,s,r){return typeof s=="symbol"||s in t?Reflect.set(t,s,r):(t.setAttribute(s,r),!0)}})}static query(){let e=new this,t=this;return new A(t.table,this,t.connection)}static async find(e){let t=this;return this.query().find(e,t.primaryKey)}static async findOrFail(e){let t=this;return this.query().findOrFail(e,t.primaryKey)}static async all(){return this.query().get()}static async first(){return this.query().first()}static async firstOrFail(){return this.query().firstOrFail()}static where(e,t,s){return this.query().where(e,t,s)}static whereIn(e,t){return this.query().whereIn(e,t)}static whereNull(e){return this.query().whereNull(e)}static whereNotNull(e){return this.query().whereNotNull(e)}static orderBy(e,t){return this.query().orderBy(e,t)}static latest(e){return this.query().latest(e)}static oldest(e){return this.query().oldest(e)}static with(...e){return this.query().with(...e)}static async count(){return this.query().count()}static async create(e){let t=new this,s=this;if(t.fill(e),await t.fireHook("creating"),await t.fireHook("saving"),s.timestamps){let n=new Date().toISOString();t.setAttribute(s.createdAt,n),t.setAttribute(s.updatedAt,n)}let r=t.getInsertableAttributes(),o=await new A(s.table,this,s.connection).insertGetId(r,s.primaryKey);return s.incrementing&&o&&t.setAttribute(s.primaryKey,o),t.syncOriginal(),t.exists=!0,await t.fireHook("created"),await t.fireHook("saved"),t}async save(){let e=this.constructor;if(this.exists){await this.fireHook("updating"),await this.fireHook("saving"),e.timestamps&&this.setAttribute(e.updatedAt,new Date().toISOString());let t=this.getDirty();if(Object.keys(t).length>0){let s=this.getAttribute(e.primaryKey);await new A(e.table,this.constructor,e.connection).where(e.primaryKey,s).update(t)}this.syncOriginal(),await this.fireHook("updated"),await this.fireHook("saved")}else{if(await this.fireHook("creating"),await this.fireHook("saving"),e.timestamps){let i=new Date().toISOString();this.getAttribute(e.createdAt)||this.setAttribute(e.createdAt,i),this.setAttribute(e.updatedAt,i)}let t=this.getInsertableAttributes(),r=await new A(e.table,this.constructor,e.connection).insertGetId(t,e.primaryKey);e.incrementing&&r&&this.setAttribute(e.primaryKey,r),this.syncOriginal(),this.exists=!0,await this.fireHook("created"),await this.fireHook("saved")}}async update(e){this.fill(e),await this.save()}async delete(){let e=this.constructor;await this.fireHook("deleting");let t=this.getAttribute(e.primaryKey);await new A(e.table,this.constructor,e.connection).where(e.primaryKey,t).delete(),this.exists=!1,await this.fireHook("deleted")}async refresh(){let e=this.constructor,t=this.getAttribute(e.primaryKey),s=await this.constructor.find(t);s&&(this.attributes={...s.attributes},this.syncOriginal())}getAttribute(e){let t=this.constructor,s=this.attributes[e],r=t.casts[e];if(r&&s!==void 0&&s!==null)switch(r){case"number":return Number(s);case"boolean":return!!s;case"string":return String(s);case"date":return new Date(s);case"json":return typeof s=="string"?JSON.parse(s):s}return s}setAttribute(e,t){this.constructor.casts[e]==="json"&&typeof t!="string"?this.attributes[e]=JSON.stringify(t):this.attributes[e]=t}fill(e){let t=this.constructor;for(let[s,r]of Object.entries(e))t.fillable.length>0&&!t.fillable.includes(s)||this.setAttribute(s,r)}getAttributes(){return{...this.attributes}}getOriginal(e){return e?this.originalAttributes[e]:{...this.originalAttributes}}getDirty(){let e={};for(let[t,s]of Object.entries(this.attributes))s!==this.originalAttributes[t]&&(e[t]=s);return e}isDirty(...e){let t=this.getDirty();return e.length===0?Object.keys(t).length>0:e.some(s=>s in t)}isClean(...e){return!this.isDirty(...e)}wasChanged(...e){return this.isDirty(...e)}hasOne(e,t,s){return new ee(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new te(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new se(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,i,o){return new re(this,e,t,s,r,i??this.constructor.primaryKey,o??e.primaryKey)}setRelation(e,t){this.relations[e]=t}getRelation(e){return this.relations[e]}relationLoaded(e){return e in this.relations}toJSON(){let e=this.constructor,t={};for(let[s,r]of Object.entries(this.attributes))e.hidden.includes(s)||(t[s]=this.getAttribute(s));for(let[s,r]of Object.entries(this.relations))Array.isArray(r)?t[s]=r.map(i=>i instanceof c?i.toJSON():i):r instanceof c?t[s]=r.toJSON():t[s]=r;return t}toObject(){return this.toJSON()}static hydrate(e){let t=new this;return t.attributes={...e},t.syncOriginal(),t.exists=!0,t}static boot(e){this.hooks.set(this.name,e)}static observe(e){let t=this.observers.get(this.name)??[];t.push(e),this.observers.set(this.name,t)}static removeObservers(){this.observers.delete(this.name)}async fireHook(e){let t=this.constructor,s=c.hooks.get(t.name);s?.[e]&&await s[e](this),typeof this[e]=="function"&&await this[e]();let r=c.observers.get(t.name)??[];for(let o of r){let n=o[e];typeof n=="function"&&await n.call(o,this)}let i=t.name.toLowerCase();await ne.emit(`${i}.${e}`,this)}async fireEvent(e){let t=this.constructor;if(!t.events.includes(e))throw new Error(`Event "${e}" is not declared in ${t.name}.events. Add it to: static events = ['${e}', ...];`);let s=c.observers.get(t.name)??[];for(let i of s){let o=i[e];typeof o=="function"&&await o.call(i,this)}let r=t.name.toLowerCase();await ne.emit(`${r}.${e}`,this)}syncOriginal(){this.originalAttributes={...this.attributes}}getInsertableAttributes(){let e=this.constructor,t={...this.attributes};return e.incrementing&&t[e.primaryKey]===void 0&&delete t[e.primaryKey],t}static get tableName(){return this.table}}});var Je,Jr=y(()=>{"use strict";Je=class{async call(e){await new e().run()}}});var W,Yr,Ts=y(()=>{"use strict";C();W=class{bindings=new Map;aliases=new Map;resolved=new Set;bind(e,t){this.bindings.set(e,{factory:t,singleton:!1,tags:[]})}singleton(e,t){this.bindings.set(e,{factory:t,singleton:!0,tags:[]})}instance(e,t){this.bindings.set(e,{factory:()=>t,singleton:!0,instance:t,tags:[]})}alias(e,t){this.aliases.set(e,t)}async make(e){let t=this.resolveAlias(e),s=this.bindings.get(t);if(!s)throw new Error(`No binding found for "${e}" in the container.`);if(s.singleton&&s.instance!==void 0)return s.instance;let r=await s.factory(this);return s.singleton&&(s.instance=r),this.resolved.add(t),r}makeSync(e){let t=this.resolveAlias(e),s=this.bindings.get(t);if(!s)throw new Error(`No binding found for "${e}" in the container.`);if(s.singleton&&s.instance!==void 0)return s.instance;let r=s.factory(this);if(r instanceof Promise)throw new Error(`Binding "${e}" has an async factory. Use container.make() instead of container.makeSync().`);return s.singleton&&(s.instance=r),this.resolved.add(t),r}has(e){let t=this.resolveAlias(e);return this.bindings.has(t)}isResolved(e){return this.resolved.has(this.resolveAlias(e))}tag(e,t){for(let s of e){let r=this.bindings.get(s);r&&r.tags.push(t)}}async tagged(e){let t=[];for(let[s,r]of this.bindings)r.tags.includes(e)&&t.push(await this.make(s));return t}flush(){for(let e of this.bindings.values())e.singleton&&(e.instance=void 0);this.resolved.clear()}forget(e){this.bindings.delete(e),this.resolved.delete(e)}getBindings(){return[...this.bindings.keys()]}resolveAlias(e){return this.aliases.get(e)??e}},Yr=b("svelar.container",()=>new W)});var Ye,Vr=y(()=>{"use strict";Ts();Ye=class{container;providers=[];booted=!1;constructor(e){this.container=e??new W,this.container.instance("app",this),this.container.instance("container",this.container)}register(e){let t=new e(this.container);return this.providers.push(t),this}async bootstrap(){if(this.booted)return this;for(let e of this.providers)await e.register();for(let e of this.providers)await e.boot();return this.booted=!0,this}isBooted(){return this.booted}async make(e){return this.container.make(e)}getProviders(){return[...this.providers]}}});var x,H,Ve,ie,Ge,oe,ae,Qe,ce,le=y(()=>{"use strict";x=class{},H=class{middleware=[];namedMiddleware=new Map;use(e){return typeof e=="function"&&"prototype"in e&&typeof e.prototype?.handle=="function"?this.middleware.push(new e):this.middleware.push(e),this}register(e,t){return typeof t=="function"&&"prototype"in t&&typeof t.prototype?.handle=="function"?this.namedMiddleware.set(e,new t):this.namedMiddleware.set(e,t),this}get(e){return this.namedMiddleware.get(e)}async execute(e,t,s){let r=[...this.middleware];if(s)for(let o of s){let n=this.namedMiddleware.get(o);n&&r.push(n)}let i=t;for(let o=r.length-1;o>=0;o--){let n=r[o],a=i;typeof n.handle=="function"?i=()=>n.handle(e,a):i=()=>n(e,a)}return i()}count(){return this.middleware.length}},Ve=class extends x{constructor(t={}){super();this.options=t}async handle(t,s){let r=await s();if(!r)return;let i=Array.isArray(this.options.origin)?this.options.origin.join(", "):this.options.origin??"*";return r.headers.set("Access-Control-Allow-Origin",i),r.headers.set("Access-Control-Allow-Methods",(this.options.methods??["GET","POST","PUT","DELETE","PATCH","OPTIONS"]).join(", ")),r.headers.set("Access-Control-Allow-Headers",(this.options.headers??["Content-Type","Authorization"]).join(", ")),this.options.credentials&&r.headers.set("Access-Control-Allow-Credentials","true"),this.options.maxAge&&r.headers.set("Access-Control-Max-Age",String(this.options.maxAge)),t.event.request.method==="OPTIONS"?new Response(null,{status:204,headers:r.headers}):r}},ie=class extends x{requests=new Map;maxRequests;windowMs;constructor(e={}){super(),this.maxRequests=e.maxRequests??60,this.windowMs=e.windowMs??6e4}async handle(e,t){let s=e.event.request.headers.get("x-forwarded-for")??e.event.getClientAddress?.()??"unknown",r=Date.now(),i=this.requests.get(s);if(i&&r<i.resetAt){if(i.count>=this.maxRequests)return new Response(JSON.stringify({error:"Too many requests"}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(Math.ceil((i.resetAt-r)/1e3))}});i.count++}else this.requests.set(s,{count:1,resetAt:r+this.windowMs});return t()}},Ge=class extends x{async handle(e,t){let s=Date.now(),r=e.event.request.method,i=e.event.url.pathname,o=await t(),n=Date.now()-s,a=o instanceof Response?o.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${i} \u2192 ${a} (${n}ms)`),o}},oe=class extends x{cookieName;headerName;fieldName;excludePaths;onlyPaths;constructor(e={}){super(),this.cookieName=e.cookieName??"XSRF-TOKEN",this.headerName=e.headerName??"X-CSRF-Token",this.fieldName=e.fieldName??"_csrf",this.excludePaths=e.excludePaths??[],this.onlyPaths=e.onlyPaths??null}async handle(e,t){let{event:s}=e,r=s.request.method.toUpperCase();if(["GET","HEAD","OPTIONS"].includes(r))return this.setTokenAndContinue(e,t);if((s.request.headers.get("authorization")??"").startsWith("Bearer "))return t();let o=s.url.pathname;if(this.onlyPaths&&!this.onlyPaths.some(l=>o.startsWith(l)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(l=>o.startsWith(l)))return t();let n=this.getCookieToken(s),a=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!n||!a||!this.timingSafeEqual(n,a)?new Response(JSON.stringify({message:"CSRF token mismatch"}),{status:419,headers:{"Content-Type":"application/json"}}):t()}async setTokenAndContinue(e,t){let s=await t();if(!(s instanceof Response))return s;let i=this.getCookieToken(e.event)||this.generateToken();return s.headers.append("Set-Cookie",`${this.cookieName}=${i}; Path=/; SameSite=Lax`),s}getCookieToken(e){let s=(e.request.headers.get("cookie")??"").match(new RegExp(`${this.cookieName}=([^;]+)`));return s?s[1]:null}async getBodyToken(e){try{let t=e.request.headers.get("content-type")??"";if(t.includes("application/x-www-form-urlencoded")||t.includes("multipart/form-data"))return(await e.request.clone().formData()).get(this.fieldName);if(t.includes("application/json"))return(await e.request.clone().json())[this.fieldName]??null}catch{}return null}generateToken(){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}timingSafeEqual(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),i=s.encode(t),o=0;for(let n=0;n<r.length;n++)o|=r[n]^i[n];return o===0}},ae=class extends x{allowedOrigins;constructor(e={}){super(),this.allowedOrigins=new Set(e.allowedOrigins??[])}async handle(e,t){let{event:s}=e,r=s.request.method.toUpperCase();if(["GET","HEAD","OPTIONS"].includes(r)||(s.request.headers.get("authorization")??"").startsWith("Bearer "))return t();let o=s.request.headers.get("origin");if(!o)return t();let n=s.url.origin;return o===n||this.allowedOrigins.has(o)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},Qe=class extends x{secret;tolerance;signatureHeader;timestampHeader;onlyPaths;constructor(e){super(),this.secret=e.secret,this.tolerance=e.tolerance??300,this.signatureHeader=e.signatureHeader??"X-Signature",this.timestampHeader=e.timestampHeader??"X-Timestamp",this.onlyPaths=e.onlyPaths??null}async handle(e,t){let{event:s}=e;if(this.onlyPaths){let E=s.url.pathname;if(!this.onlyPaths.some(T=>E.startsWith(T)))return t()}let r=s.request.headers.get(this.signatureHeader),i=s.request.headers.get(this.timestampHeader);if(!r||!i)return new Response(JSON.stringify({message:"Missing request signature"}),{status:401,headers:{"Content-Type":"application/json"}});let o=parseInt(i,10),n=Math.floor(Date.now()/1e3);if(isNaN(o)||Math.abs(n-o)>this.tolerance)return new Response(JSON.stringify({message:"Request signature expired"}),{status:401,headers:{"Content-Type":"application/json"}});let l=await s.request.clone().text(),{createHmac:u}=await import("crypto"),d=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,m=`${i}.${d}.${h}.${l}`,f=u("sha256",this.secret).update(m).digest("hex");return r.length!==f.length||!this.timingSafeCompare(r,f)?new Response(JSON.stringify({message:"Invalid request signature"}),{status:401,headers:{"Content-Type":"application/json"}}):t()}timingSafeCompare(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),i=s.encode(t),o=0;for(let n=0;n<r.length;n++)o|=r[n]^i[n];return o===0}static sign(e,t,s,r,i){let{createHmac:o}=je("crypto"),n=i??Math.floor(Date.now()/1e3),a=`${n}.${t.toUpperCase()}.${s}.${r}`;return{signature:o("sha256",e).update(a).digest("hex"),timestamp:n}}},ce=class extends x{attempts=new Map;maxAttempts;decayMinutes;constructor(e={}){super(),this.maxAttempts=e.maxAttempts??5,this.decayMinutes=e.decayMinutes??1}async handle(e,t){let r=`${e.event.request.headers.get("x-forwarded-for")??e.event.getClientAddress?.()??"unknown"}:${e.event.url.pathname}`,i=Date.now(),o=this.attempts.get(r);if(o){if(i<o.blockedUntil){let a=Math.ceil((o.blockedUntil-i)/1e3);return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}if(o.count>=this.maxAttempts){o.blockedUntil=i+this.decayMinutes*6e4,o.count=0;let a=this.decayMinutes*60;return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}}let n=await t();if(n instanceof Response&&n.status>=400&&n.status<500){let a=this.attempts.get(r)??{count:0,blockedUntil:0};if(a.count++,this.attempts.set(r,a),this.attempts.size>1e4)for(let[l,u]of this.attempts)i>u.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(l)}return n}}});import{z as ue}from"zod";function Gr(c,e=!1){let t=new c;return e?{GET:t.handle("show"),PUT:t.handle("update"),PATCH:t.handle("update"),DELETE:t.handle("destroy")}:{GET:t.handle("index"),POST:t.handle("store")}}var Xe,F,$e,De,ke,Qr=y(()=>{"use strict";le();Xe=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof x?s=new e:s=e,this.controllerMiddleware.push({middleware:s,only:t?.only,except:t?.except})}handle(e){return async t=>{try{let s=this.controllerMiddleware.filter(r=>!(r.only&&!r.only.includes(e)||r.except&&r.except.includes(e)));if(s.length>0){let r=new H;for(let{middleware:n}of s)r.use(n);let i={event:t,params:t.params,locals:t.locals},o=await r.execute(i,async()=>this.callMethod(e,t));if(o instanceof Response)return o}return await this.callMethod(e,t)}catch(s){return this.handleError(s,t)}}}json(e,t=200,s={}){let r=JSON.stringify(e,null,2);return new Response(r,{status:t,headers:{"Content-Type":"application/json",...s}})}text(e,t=200){return new Response(e,{status:t,headers:{"Content-Type":"text/plain"}})}html(e,t=200){return new Response(e,{status:t,headers:{"Content-Type":"text/html"}})}redirect(e,t=302){return new Response(null,{status:t,headers:{Location:e}})}noContent(){return new Response(null,{status:204})}created(e){return e?this.json(e,201):new Response(null,{status:201})}async validate(e,t){let s=t instanceof ue.ZodObject?t:ue.object(t),r,i=e.request.headers.get("content-type")??"";if(i.includes("application/json"))r=await e.request.json();else if(i.includes("multipart/form-data")||i.includes("application/x-www-form-urlencoded")){let n=await e.request.formData();r=Object.fromEntries(n)}else r=Object.fromEntries(e.url.searchParams);let o=s.safeParse(r);if(!o.success)throw new F(o.error);return o.data}validateQuery(e,t){let s=t instanceof ue.ZodObject?t:ue.object(t),r=Object.fromEntries(e.url.searchParams),i=s.safeParse(r);if(!i.success)throw new F(i.error);return i.data}validateParams(e,t){let r=(t instanceof ue.ZodObject?t:ue.object(t)).safeParse(e.params);if(!r.success)throw new F(r.error);return r.data}handleError(e,t){return e instanceof F?this.json({message:"Validation failed",errors:e.errors},422):e instanceof $e?this.json({message:e.message||"Not found"},404):e instanceof De?this.json({message:e.message||"Unauthorized"},401):e instanceof ke?this.json({message:e.message||"Forbidden"},403):(console.error("[Svelar] Controller error:",e),this.json({message:process.env.NODE_ENV==="production"?"Internal server error":e.message},500))}async callMethod(e,t){let s=this[e];if(typeof s!="function")throw new Error(`Method "${e}" not found on controller "${this.constructor.name}".`);let r=await s.call(this,t);return r instanceof Response?r:this.json(r)}};F=class extends Error{errors;constructor(e){super("Validation failed"),this.name="ValidationError",this.errors={};for(let t of e.issues){let s=t.path.join(".");this.errors[s]||(this.errors[s]=[]),this.errors[s].push(t.message)}}},$e=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},De=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},ke=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as Uo,createHmac as Xr,timingSafeEqual as Ho}from"crypto";import{promises as B}from"fs";import{join as _e}from"path";var de,Oe,z,Ze,et,tt,he,Ss=y(()=>{"use strict";le();de=class c{constructor(e,t){this.id=e;t&&(this.data={...t},this.data._flash&&(this.previousFlashData=this.data._flash,delete this.data._flash))}data={};dirty=!1;flashData={};previousFlashData={};get(e,t){return e in this.flashData?this.flashData[e]:e in this.previousFlashData?this.previousFlashData[e]:e in this.data?this.data[e]:t}set(e,t){this.data[e]=t,this.dirty=!0}has(e){return e in this.data||e in this.flashData||e in this.previousFlashData}forget(e){delete this.data[e],this.dirty=!0}flush(){this.data={},this.dirty=!0}flash(e,t){this.flashData[e]=t,this.dirty=!0}all(){return{...this.data,...this.previousFlashData,...this.flashData}}isDirty(){return this.dirty||Object.keys(this.flashData).length>0}toPersist(){let e={...this.data};return Object.keys(this.flashData).length>0&&(e._flash=this.flashData),e}regenerateId(){let e=this.id,t=c.generateId();this.id=t,this.dirty=!0;let s=Oe.get(e);return s instanceof z&&s.markOldSessionId(e),Oe.delete(e),t}static generateId(){return Uo(32).toString("hex")}},Oe=new Map,z=class{sessions=new Map;oldSessionIds=new Set;async read(e){if(this.oldSessionIds.has(e))return null;let t=this.sessions.get(e);return t?Date.now()>t.expiresAt?(this.sessions.delete(e),null):t.data:null}async write(e,t,s){this.sessions.set(e,{data:t,expiresAt:Date.now()+s*1e3}),Oe.set(e,this)}async destroy(e){this.sessions.delete(e),Oe.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),Oe.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},Ze=class{constructor(e="sessions",t){this.tableName=e;this.connectionName=t}tableEnsured=!1;async ensureTable(){if(!this.tableEnsured)try{let{Connection:e}=await Promise.resolve().then(()=>(v(),w));switch(e.getDriver(this.connectionName)){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
42
42
  id TEXT PRIMARY KEY,
43
43
  payload TEXT NOT NULL,
44
44
  expires_at TEXT NOT NULL
@@ -50,17 +50,17 @@ var zn=Object.defineProperty;var je=(c=>typeof require<"u"?require:typeof Proxy<
50
50
  id VARCHAR(255) PRIMARY KEY,
51
51
  payload TEXT NOT NULL,
52
52
  expires_at DATETIME NOT NULL
53
- ) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(w(),v)),s=await t.raw(`SELECT payload, expires_at FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName);if(s.length===0)return null;let r=s[0];if(new Date(r.expires_at)<new Date)return await this.destroy(e),null;try{return JSON.parse(r.payload)}catch{return null}}async write(e,t,s){await this.ensureTable();let{Connection:r}=await Promise.resolve().then(()=>(w(),v)),n=JSON.stringify(t),o=new Date(Date.now()+s*1e3).toISOString(),i=r.getDriver(this.connectionName);i==="sqlite"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
54
- ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,n,o],this.connectionName):i==="postgres"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES ($1, $2, $3)
55
- ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,n,o],this.connectionName):await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
56
- ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,n,o],this.connectionName)}async destroy(e){let{Connection:t}=await Promise.resolve().then(()=>(w(),v));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(w(),v));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},Ze=class{dir;constructor(e){this.dir=e??Oe(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return Oe(this.dir,`${t}.json`)}async ensureDir(){await H.mkdir(this.dir,{recursive:!0})}async read(e){try{let t=await H.readFile(this.filePath(e),"utf-8"),s=JSON.parse(t);return new Date(s.expiresAt)<new Date?(await this.destroy(e),null):s.data}catch{return null}}async write(e,t,s){await this.ensureDir();let r={data:t,expiresAt:new Date(Date.now()+s*1e3).toISOString()};await H.writeFile(this.filePath(e),JSON.stringify(r),"utf-8")}async destroy(e){try{await H.unlink(this.filePath(e))}catch{}}async gc(e){try{let t=await H.readdir(this.dir),s=new Date;for(let r of t)if(r.endsWith(".json"))try{let n=await H.readFile(Oe(this.dir,r),"utf-8"),o=JSON.parse(n);new Date(o.expiresAt)<s&&await H.unlink(Oe(this.dir,r))}catch{await H.unlink(Oe(this.dir,r)).catch(()=>{})}}catch{}}},et=class{redis;prefix;constructor(e){this.prefix=e?.prefix??"svelar_session:",e?.client?this.redis=e.client:this._url=e?.url}_url;_connecting;async getClient(){return this.redis?this.redis:(this._connecting||(this._connecting=(async()=>{try{let{default:e}=await import("ioredis");return this.redis=this._url?new e(this._url):new e,this.redis}catch{throw new Error('RedisSessionStore requires "ioredis" package. Install it: npm install ioredis')}})()),this._connecting)}async read(e){let s=await(await this.getClient()).get(this.prefix+e);if(!s)return null;try{return JSON.parse(s)}catch{return null}}async write(e,t,s){await(await this.getClient()).set(this.prefix+e,JSON.stringify(t),"EX",s)}async destroy(e){await(await this.getClient()).del(this.prefix+e)}async gc(e){}},de=class extends x{config;constructor(e){if(super(),this.config={cookieName:"svelar_session",lifetime:7200,secret:"",path:"/",domain:"",secure:process.env.NODE_ENV==="production",httpOnly:!0,sameSite:"lax",...e},!this.config.secret)throw new Error("APP_KEY is not set. Pass `secret` to createSvelarApp() \u2014 e.g. secret: env.APP_KEY (from $env/dynamic/private).")}async handle(e,t){let s=e.event.request.headers.get("cookie")??"",r=this.getSessionIdFromCookie(s),n=null;if(r){let a=this.verifySignedId(r);a?(n=await this.config.store.read(a),r=a):r=null}r||(r=ue.generateId());let o=new ue(r,n??{});e.event.locals.session=o,e.locals.session=o;let i=await t();if(o.isDirty()&&await this.config.store.write(o.id,o.toPersist(),this.config.lifetime),i instanceof Response){let a=this.signId(o.id),l=this.buildCookieString(a);i.headers.append("Set-Cookie",l)}return i}getSessionIdFromCookie(e){let t=e.split(";").map(s=>s.trim());for(let s of t){let[r,...n]=s.split("=");if(r===this.config.cookieName)return decodeURIComponent(n.join("="))}return null}signId(e){let t=Xr("sha256",this.config.secret).update(e).digest("base64url");return`${e}.${t}`}verifySignedId(e){let t=e.lastIndexOf(".");if(t===-1)return null;let s=e.slice(0,t),r=e.slice(t+1),n=Xr("sha256",this.config.secret).update(s).digest("base64url");if(r.length!==n.length)return null;let o=Buffer.from(r),i=Buffer.from(n);if(o.length!==i.length)return null;try{if(Ho(o,i))return s}catch{}return null}buildCookieString(e){let t=[`${this.config.cookieName}=${encodeURIComponent(e)}`];return t.push(`Path=${this.config.path}`),t.push(`Max-Age=${this.config.lifetime}`),this.config.domain&&t.push(`Domain=${this.config.domain}`),this.config.secure&&t.push("Secure"),this.config.httpOnly&&t.push("HttpOnly"),t.push(`SameSite=${this.config.sameSite}`),t.join("; ")}}});var Ne={};P(Ne,{Hash:()=>xs});import{randomBytes as Ss,scrypt as Zr,timingSafeEqual as Fo}from"crypto";async function Bo(c,e=16384){let t=Ss(16),s=64,r=await new Promise((n,o)=>{Zr(c,t,s,{N:e,r:8,p:1},(i,a)=>{i?o(i):n(a)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function Ko(c,e){let t=e.split("$");if(t.length!==5||t[1]!=="scrypt")return!1;let s=parseInt(t[2].replace("N=",""),10),r=Buffer.from(t[3],"base64"),n=Buffer.from(t[4],"base64"),o=n.length,i=await new Promise((a,l)=>{Zr(c,r,o,{N:s,r:8,p:1},(u,d)=>{u?l(u):a(d)})});return Fo(i,n)}var Cs,xs,he=y(()=>{"use strict";C();Cs=class{config={driver:"scrypt",scryptCost:16384,bcryptRounds:12};configure(e){Object.assign(this.config,e)}async make(e){switch(this.config.driver){case"scrypt":return Bo(e,this.config.scryptCost);case"bcrypt":try{return(await import("bcrypt")).default.hash(e,this.config.bcryptRounds??12)}catch{throw new Error('bcrypt driver requires the "bcrypt" package. Install it: npm install bcrypt')}case"argon2":try{return(await import("argon2")).default.hash(e)}catch{throw new Error('argon2 driver requires the "argon2" package. Install it: npm install argon2')}default:throw new Error(`Unsupported hash driver: ${this.config.driver}`)}}async verify(e,t){if(t.startsWith("$scrypt$"))return Ko(e,t);if(t.startsWith("$2b$")||t.startsWith("$2a$")||t.startsWith("$2y$"))try{return(await import("bcrypt")).default.compare(e,t)}catch{throw new Error("bcrypt package required to verify bcrypt hashes.")}if(t.startsWith("$argon2"))try{return(await import("argon2")).default.verify(t,e)}catch{throw new Error("argon2 package required to verify argon2 hashes.")}return!1}needsRehash(e){if(this.config.driver==="scrypt"&&e.startsWith("$scrypt$")){let t=e.match(/N=(\d+)/);if(t)return parseInt(t[1],10)!==this.config.scryptCost}if(this.config.driver==="bcrypt"&&(e.startsWith("$2b$")||e.startsWith("$2a$"))){let t=e.match(/\$2[aby]\$(\d+)\$/);if(t)return parseInt(t[1],10)!==this.config.bcryptRounds}return this.config.driver==="scrypt"&&!e.startsWith("$scrypt$")||this.config.driver==="bcrypt"&&!e.startsWith("$2")||this.config.driver==="argon2"&&!e.startsWith("$argon2")}randomString(e=32){return Ss(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return Ss(e).toString("base64url")}},xs=b("svelar.hash",()=>new Cs)});var en={};P(en,{EmailTemplates:()=>Wo});import{randomUUID as M}from"crypto";var Ps,Wo,tn=y(()=>{"use strict";C();Ps=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:M(),createdAt:Date.now(),updatedAt:Date.now()};if(this.config.driver==="memory")this.templates.set(e.name,t);else if(this.config.driver==="database")try{let{Connection:s}=await Promise.resolve().then(()=>(w(),v));await s.connection()}catch{this.templates.set(e.name,t)}return t}async render(e,t){let s=await this.get(e);if(!s)throw new Error(`Template "${e}" not found`);let r=this.interpolate(s.subject,t),n=this.interpolate(s.html,t),o=s.text?this.interpolate(s.text,t):void 0;return{subject:r,html:n,text:o}}async get(e){return this.templates.get(e)||null}async list(e){let t=Array.from(this.templates.values());return e&&(t=t.filter(s=>s.category===e)),t}async update(e,t){let s=this.templates.get(e);return s?(Object.assign(s,t,{updatedAt:Date.now()}),s):null}async delete(e){return this.templates.delete(e)}registerDefaults(){this.templates.set("welcome",{id:M(),name:"welcome",subject:"Welcome to {{appName}}, {{user.name}}!",html:`
53
+ ) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(v(),w)),s=await t.raw(`SELECT payload, expires_at FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName);if(s.length===0)return null;let r=s[0];if(new Date(r.expires_at)<new Date)return await this.destroy(e),null;try{return JSON.parse(r.payload)}catch{return null}}async write(e,t,s){await this.ensureTable();let{Connection:r}=await Promise.resolve().then(()=>(v(),w)),i=JSON.stringify(t),o=new Date(Date.now()+s*1e3).toISOString(),n=r.getDriver(this.connectionName);n==="sqlite"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
54
+ ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,i,o],this.connectionName):n==="postgres"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES ($1, $2, $3)
55
+ ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,i,o],this.connectionName):await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
56
+ ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,i,o],this.connectionName)}async destroy(e){let{Connection:t}=await Promise.resolve().then(()=>(v(),w));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(v(),w));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},et=class{dir;constructor(e){this.dir=e??_e(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return _e(this.dir,`${t}.json`)}async ensureDir(){await B.mkdir(this.dir,{recursive:!0})}async read(e){try{let t=await B.readFile(this.filePath(e),"utf-8"),s=JSON.parse(t);return new Date(s.expiresAt)<new Date?(await this.destroy(e),null):s.data}catch{return null}}async write(e,t,s){await this.ensureDir();let r={data:t,expiresAt:new Date(Date.now()+s*1e3).toISOString()};await B.writeFile(this.filePath(e),JSON.stringify(r),"utf-8")}async destroy(e){try{await B.unlink(this.filePath(e))}catch{}}async gc(e){try{let t=await B.readdir(this.dir),s=new Date;for(let r of t)if(r.endsWith(".json"))try{let i=await B.readFile(_e(this.dir,r),"utf-8"),o=JSON.parse(i);new Date(o.expiresAt)<s&&await B.unlink(_e(this.dir,r))}catch{await B.unlink(_e(this.dir,r)).catch(()=>{})}}catch{}}},tt=class{redis;prefix;constructor(e){this.prefix=e?.prefix??"svelar_session:",e?.client?this.redis=e.client:this._url=e?.url}_url;_connecting;async getClient(){return this.redis?this.redis:(this._connecting||(this._connecting=(async()=>{try{let{default:e}=await import("ioredis");return this.redis=this._url?new e(this._url):new e,this.redis}catch{throw new Error('RedisSessionStore requires "ioredis" package. Install it: npm install ioredis')}})()),this._connecting)}async read(e){let s=await(await this.getClient()).get(this.prefix+e);if(!s)return null;try{return JSON.parse(s)}catch{return null}}async write(e,t,s){await(await this.getClient()).set(this.prefix+e,JSON.stringify(t),"EX",s)}async destroy(e){await(await this.getClient()).del(this.prefix+e)}async gc(e){}},he=class extends x{config;constructor(e){if(super(),this.config={cookieName:"svelar_session",lifetime:7200,secret:"",path:"/",domain:"",secure:process.env.NODE_ENV==="production",httpOnly:!0,sameSite:"lax",...e},!this.config.secret)throw new Error("APP_KEY is not set. Pass `secret` to createSvelarApp() \u2014 e.g. secret: env.APP_KEY (from $env/dynamic/private).")}async handle(e,t){let s=e.event.request.headers.get("cookie")??"",r=this.getSessionIdFromCookie(s),i=null;if(r){let a=this.verifySignedId(r);a?(i=await this.config.store.read(a),r=a):r=null}r||(r=de.generateId());let o=new de(r,i??{});e.event.locals.session=o,e.locals.session=o;let n=await t();if(o.isDirty()&&await this.config.store.write(o.id,o.toPersist(),this.config.lifetime),n instanceof Response){let a=this.signId(o.id),l=this.buildCookieString(a);n.headers.append("Set-Cookie",l)}return n}getSessionIdFromCookie(e){let t=e.split(";").map(s=>s.trim());for(let s of t){let[r,...i]=s.split("=");if(r===this.config.cookieName)return decodeURIComponent(i.join("="))}return null}signId(e){let t=Xr("sha256",this.config.secret).update(e).digest("base64url");return`${e}.${t}`}verifySignedId(e){let t=e.lastIndexOf(".");if(t===-1)return null;let s=e.slice(0,t),r=e.slice(t+1),i=Xr("sha256",this.config.secret).update(s).digest("base64url");if(r.length!==i.length)return null;let o=Buffer.from(r),n=Buffer.from(i);if(o.length!==n.length)return null;try{if(Ho(o,n))return s}catch{}return null}buildCookieString(e){let t=[`${this.config.cookieName}=${encodeURIComponent(e)}`];return t.push(`Path=${this.config.path}`),t.push(`Max-Age=${this.config.lifetime}`),this.config.domain&&t.push(`Domain=${this.config.domain}`),this.config.secure&&t.push("Secure"),this.config.httpOnly&&t.push("HttpOnly"),t.push(`SameSite=${this.config.sameSite}`),t.join("; ")}}});var Ae={};P(Ae,{Hash:()=>Rs});import{randomBytes as Cs,scrypt as Zr,timingSafeEqual as Fo}from"crypto";async function Bo(c,e=16384){let t=Cs(16),s=64,r=await new Promise((i,o)=>{Zr(c,t,s,{N:e,r:8,p:1},(n,a)=>{n?o(n):i(a)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function Ko(c,e){let t=e.split("$");if(t.length!==5||t[1]!=="scrypt")return!1;let s=parseInt(t[2].replace("N=",""),10),r=Buffer.from(t[3],"base64"),i=Buffer.from(t[4],"base64"),o=i.length,n=await new Promise((a,l)=>{Zr(c,r,o,{N:s,r:8,p:1},(u,d)=>{u?l(u):a(d)})});return Fo(n,i)}var xs,Rs,pe=y(()=>{"use strict";C();xs=class{config={driver:"scrypt",scryptCost:16384,bcryptRounds:12};configure(e){Object.assign(this.config,e)}async make(e){switch(this.config.driver){case"scrypt":return Bo(e,this.config.scryptCost);case"bcrypt":try{return(await import("bcrypt")).default.hash(e,this.config.bcryptRounds??12)}catch{throw new Error('bcrypt driver requires the "bcrypt" package. Install it: npm install bcrypt')}case"argon2":try{return(await import("argon2")).default.hash(e)}catch{throw new Error('argon2 driver requires the "argon2" package. Install it: npm install argon2')}default:throw new Error(`Unsupported hash driver: ${this.config.driver}`)}}async verify(e,t){if(t.startsWith("$scrypt$"))return Ko(e,t);if(t.startsWith("$2b$")||t.startsWith("$2a$")||t.startsWith("$2y$"))try{return(await import("bcrypt")).default.compare(e,t)}catch{throw new Error("bcrypt package required to verify bcrypt hashes.")}if(t.startsWith("$argon2"))try{return(await import("argon2")).default.verify(t,e)}catch{throw new Error("argon2 package required to verify argon2 hashes.")}return!1}needsRehash(e){if(this.config.driver==="scrypt"&&e.startsWith("$scrypt$")){let t=e.match(/N=(\d+)/);if(t)return parseInt(t[1],10)!==this.config.scryptCost}if(this.config.driver==="bcrypt"&&(e.startsWith("$2b$")||e.startsWith("$2a$"))){let t=e.match(/\$2[aby]\$(\d+)\$/);if(t)return parseInt(t[1],10)!==this.config.bcryptRounds}return this.config.driver==="scrypt"&&!e.startsWith("$scrypt$")||this.config.driver==="bcrypt"&&!e.startsWith("$2")||this.config.driver==="argon2"&&!e.startsWith("$argon2")}randomString(e=32){return Cs(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return Cs(e).toString("base64url")}},Rs=b("svelar.hash",()=>new xs)});var en={};P(en,{EmailTemplates:()=>Wo});import{randomUUID as I}from"crypto";var Ps,Wo,tn=y(()=>{"use strict";C();Ps=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:I(),createdAt:Date.now(),updatedAt:Date.now()};if(this.config.driver==="memory")this.templates.set(e.name,t);else if(this.config.driver==="database")try{let{Connection:s}=await Promise.resolve().then(()=>(v(),w));await s.connection()}catch{this.templates.set(e.name,t)}return t}async render(e,t){let s=await this.get(e);if(!s)throw new Error(`Template "${e}" not found`);let r=this.interpolate(s.subject,t),i=this.interpolate(s.html,t),o=s.text?this.interpolate(s.text,t):void 0;return{subject:r,html:i,text:o}}async get(e){return this.templates.get(e)||null}async list(e){let t=Array.from(this.templates.values());return e&&(t=t.filter(s=>s.category===e)),t}async update(e,t){let s=this.templates.get(e);return s?(Object.assign(s,t,{updatedAt:Date.now()}),s):null}async delete(e){return this.templates.delete(e)}registerDefaults(){this.templates.set("welcome",{id:I(),name:"welcome",subject:"Welcome to {{appName}}, {{user.name}}!",html:`
57
57
  <h1>Welcome, {{user.name}}!</h1>
58
58
  <p>Thank you for joining {{appName}}.</p>
59
59
  <p>Your account has been created with the email: <strong>{{user.email}}</strong></p>
60
60
  <p><a href="{{confirmUrl}}">Confirm your email address</a></p>
61
61
  `,text:`Welcome, {{user.name}}!
62
62
 
63
- Confirm your email: {{confirmUrl}}`,variables:["appName","user.name","user.email","confirmUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("password-reset",{id:M(),name:"password-reset",subject:"Reset your {{appName}} password",html:`
63
+ Confirm your email: {{confirmUrl}}`,variables:["appName","user.name","user.email","confirmUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("password-reset",{id:I(),name:"password-reset",subject:"Reset your {{appName}} password",html:`
64
64
  <h1>Password Reset</h1>
65
65
  <p>Hi {{user.name}},</p>
66
66
  <p>Click the link below to reset your password. This link expires in 1 hour.</p>
@@ -68,18 +68,18 @@ Confirm your email: {{confirmUrl}}`,variables:["appName","user.name","user.email
68
68
  <p>If you didn't request this, you can ignore this email.</p>
69
69
  `,text:`Reset your password: {{resetUrl}}
70
70
 
71
- This link expires in 1 hour.`,variables:["appName","user.name","resetUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("email-verification",{id:M(),name:"email-verification",subject:"Verify your email address",html:`
71
+ This link expires in 1 hour.`,variables:["appName","user.name","resetUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("email-verification",{id:I(),name:"email-verification",subject:"Verify your email address",html:`
72
72
  <h1>Verify Your Email</h1>
73
73
  <p>Hi {{user.name}},</p>
74
74
  <p><a href="{{verifyUrl}}">Click here to verify your email address</a></p>
75
75
  <p>This link expires in 24 hours.</p>
76
- `,text:"Verify your email: {{verifyUrl}}",variables:["user.name","verifyUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("team-invitation",{id:M(),name:"team-invitation",subject:"{{inviter.name}} invited you to join {{team.name}}",html:`
76
+ `,text:"Verify your email: {{verifyUrl}}",variables:["user.name","verifyUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("team-invitation",{id:I(),name:"team-invitation",subject:"{{inviter.name}} invited you to join {{team.name}}",html:`
77
77
  <h1>Team Invitation</h1>
78
78
  <p>Hi {{user.name}},</p>
79
79
  <p><strong>{{inviter.name}}</strong> has invited you to join the team <strong>{{team.name}}</strong>.</p>
80
80
  <p><a href="{{acceptUrl}}">Accept Invitation</a></p>
81
81
  <p>This invitation expires in 3 days.</p>
82
- `,text:"Accept: {{acceptUrl}}",variables:["user.name","inviter.name","team.name","acceptUrl"],category:"notification",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("invoice",{id:M(),name:"invoice",subject:"Invoice #{{invoice.number}} from {{appName}}",html:`
82
+ `,text:"Accept: {{acceptUrl}}",variables:["user.name","inviter.name","team.name","acceptUrl"],category:"notification",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("invoice",{id:I(),name:"invoice",subject:"Invoice #{{invoice.number}} from {{appName}}",html:`
83
83
  <h1>Invoice #{{invoice.number}}</h1>
84
84
  <p>Hi {{customer.name}},</p>
85
85
  <p>Thank you for your purchase!</p>
@@ -87,14 +87,14 @@ This link expires in 1 hour.`,variables:["appName","user.name","resetUrl"],categ
87
87
  <p><strong>Date:</strong> {{invoice.date}}</p>
88
88
  <p><a href="{{invoiceUrl}}">View Invoice</a></p>
89
89
  `,text:`Invoice #{{invoice.number}}
90
- Amount: {{invoice.amount}}`,variables:["appName","customer.name","invoice.number","invoice.amount","invoice.date","invoiceUrl"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-confirmation",{id:M(),name:"subscription-confirmation",subject:"Subscription Confirmation",html:`
90
+ Amount: {{invoice.amount}}`,variables:["appName","customer.name","invoice.number","invoice.amount","invoice.date","invoiceUrl"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-confirmation",{id:I(),name:"subscription-confirmation",subject:"Subscription Confirmation",html:`
91
91
  <h1>Subscription Confirmed</h1>
92
92
  <p>Hi {{user.name}},</p>
93
93
  <p>Your {{plan.name}} plan is now active.</p>
94
94
  <p><strong>Price:</strong> {{plan.price}} / {{plan.interval}}</p>
95
95
  <p>Your next billing date is {{nextBillingDate}}.</p>
96
96
  `,text:`Your {{plan.name}} plan is active.
97
- Next billing: {{nextBillingDate}}`,variables:["user.name","plan.name","plan.price","plan.interval","nextBillingDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("otp-code",{id:M(),name:"otp-code",subject:"Your {{appName}} verification code: {{code}}",html:`
97
+ Next billing: {{nextBillingDate}}`,variables:["user.name","plan.name","plan.price","plan.interval","nextBillingDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("otp-code",{id:I(),name:"otp-code",subject:"Your {{appName}} verification code: {{code}}",html:`
98
98
  <h1>Your Verification Code</h1>
99
99
  <p>Hi {{user.name}},</p>
100
100
  <p>Your one-time verification code is:</p>
@@ -103,28 +103,28 @@ Next billing: {{nextBillingDate}}`,variables:["user.name","plan.name","plan.pric
103
103
  <p>If you didn't request this code, you can safely ignore this email.</p>
104
104
  `,text:`Your verification code: {{code}}
105
105
 
106
- This code expires in {{expiresMinutes}} minutes.`,variables:["appName","user.name","code","expiresMinutes","purpose"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-canceled",{id:M(),name:"subscription-canceled",subject:"Your subscription has been canceled",html:`
106
+ This code expires in {{expiresMinutes}} minutes.`,variables:["appName","user.name","code","expiresMinutes","purpose"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-canceled",{id:I(),name:"subscription-canceled",subject:"Your subscription has been canceled",html:`
107
107
  <h1>Subscription Canceled</h1>
108
108
  <p>Hi {{user.name}},</p>
109
109
  <p>Your {{plan.name}} subscription has been canceled.</p>
110
110
  <p>You have access until {{accessUntilDate}}.</p>
111
111
  `,text:`Your {{plan.name}} subscription is canceled.
112
- Access until: {{accessUntilDate}}`,variables:["user.name","plan.name","accessUntilDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()})}interpolate(e,t){let s=e;return s=s.replace(/\{\{#if\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/if\}\}/g,(r,n,o)=>this.getNestedValue(t,n)?o:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,n,o)=>{let i=this.getNestedValue(t,n);return Array.isArray(i)?i.map((a,l)=>{let u={...t,this:a,$index:l};return this.interpolate(o,u)}).join(""):""}),s=s.replace(/\{\{([\w.$]+)\}\}/g,(r,n)=>{let o=this.getNestedValue(t,n);return o!=null?String(o):""}),s}getNestedValue(e,t){return t.split(".").reduce((s,r)=>s?.[r],e)}},Wo=b("svelar.emailTemplates",()=>new Ps)});var _s={};P(_s,{Mailable:()=>_e,Mailer:()=>Ns});function As(c){return typeof c=="string"?c:`${c.name} <${c.address}>`}function D(c){return c?Array.isArray(c)?c:[c]:[]}function sn(c){return Buffer.isBuffer(c)?c.toString("base64"):Buffer.from(c).toString("base64")}var tt,Rs,$s,Ds,ks,_e,Os,Ns,st=y(()=>{"use strict";C();tt=class{async send(e){let t=D(e.to);return console.log(`[Mail] To: ${t.join(", ")} | Subject: ${e.subject}`),e.text&&console.log(`[Mail] Body: ${e.text.slice(0,200)}`),{accepted:t,rejected:[]}}},Rs=class{async send(e){return{accepted:D(e.to),rejected:[]}}},$s=class{constructor(e){this.config=e}async send(e){try{let r=await(await import("nodemailer")).createTransport({host:this.config.host,port:this.config.port??587,secure:this.config.secure??!1,auth:this.config.auth}).sendMail({from:e.from?As(e.from):void 0,to:D(e.to).join(", "),cc:D(e.cc).join(", ")||void 0,bcc:D(e.bcc).join(", ")||void 0,replyTo:e.replyTo,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments});return{accepted:r.accepted,rejected:r.rejected,messageId:r.messageId}}catch(t){throw t.code==="MODULE_NOT_FOUND"?new Error("SMTP driver requires nodemailer. Install: npm install nodemailer"):t}}},Ds=class{constructor(e){this.config=e}async send(e){let t=this.config.apiToken;if(!t)throw new Error("Postmark apiToken is required. Set it in your mailer config or POSTMARK_API_TOKEN env var.");let s=D(e.to),r=D(e.cc),n=D(e.bcc),o={From:e.from?As(e.from):void 0,To:s.join(", "),Subject:e.subject,MessageStream:this.config.messageStream||"outbound"};r.length>0&&(o.Cc=r.join(", ")),n.length>0&&(o.Bcc=n.join(", ")),e.replyTo&&(o.ReplyTo=e.replyTo),e.html&&(o.HtmlBody=e.html),e.text&&(o.TextBody=e.text),!o.HtmlBody&&!o.TextBody&&(o.TextBody=""),e.tags&&(o.Tag=Object.values(e.tags)[0]),e.attachments?.length&&(o.Attachments=e.attachments.map(l=>({Name:l.filename,Content:sn(l.content),ContentType:l.contentType||"application/octet-stream"})));let i=await fetch("https://api.postmarkapp.com/email",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","X-Postmark-Server-Token":t},body:JSON.stringify(o)});if(!i.ok){let l=await i.json().catch(()=>({Message:i.statusText}));throw new Error(`Postmark error ${i.status}: ${l.Message||JSON.stringify(l)}`)}let a=await i.json();return{accepted:s,rejected:[],messageId:a.MessageID}}},ks=class{constructor(e){this.config=e}async send(e){let t=this.config.apiKey;if(!t)throw new Error("Resend apiKey is required. Set it in your mailer config or RESEND_API_KEY env var.");let s=D(e.to),r=D(e.cc),n=D(e.bcc),o={from:e.from?As(e.from):void 0,to:s,subject:e.subject};r.length>0&&(o.cc=r),n.length>0&&(o.bcc=n),e.replyTo&&(o.reply_to=[e.replyTo]),e.html&&(o.html=e.html),e.text&&(o.text=e.text),e.tags&&(o.tags=Object.entries(e.tags).map(([l,u])=>({name:l,value:u}))),e.attachments?.length&&(o.attachments=e.attachments.map(l=>({filename:l.filename,content:sn(l.content),content_type:l.contentType||"application/octet-stream"})));let i=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!i.ok){let l=await i.json().catch(()=>({message:i.statusText}));throw new Error(`Resend error ${i.status}: ${l.message||JSON.stringify(l)}`)}let a=await i.json();return{accepted:s,rejected:[],messageId:a.id}}},_e=class{message={};to(e){return this.message.to=e,this}cc(e){return this.message.cc=e,this}bcc(e){return this.message.bcc=e,this}from(e){return this.message.from=e,this}replyTo(e){return this.message.replyTo=e,this}subject(e){return this.message.subject=e,this}text(e){return this.message.text=e,this}html(e){return this.message.html=e,this}attach(e,t,s){return this.message.attachments||(this.message.attachments=[]),this.message.attachments.push({filename:e,content:t,contentType:s}),this}tag(e,t){return this.message.tags||(this.message.tags={}),this.message.tags[e]=t,this}toMessage(){return this.message}},Os=class{config=null;transports=new Map;configure(e){this.config=e,this.transports.clear()}async send(e,t){let s=this.resolveTransport(t);return!e.from&&this.config?.from&&(e.from=this.config.from),s.send(e)}async sendMailable(e,t){e.build();let s=e.toMessage();return!s.from&&this.config?.from&&(s.from=this.config.from),this.send(s,t)}mailer(e){let t=this.resolveTransport(e);return{send:s=>(!s.from&&this.config?.from&&(s.from=this.config.from),t.send(s))}}resolveTransport(e){let t=e??this.config?.default??"log";if(this.transports.has(t))return this.transports.get(t);if(!this.config){let n=new tt;return this.transports.set(t,n),n}let s=this.config.mailers[t];if(!s)throw new Error(`Mailer "${t}" is not defined.`);let r;switch(s.driver){case"smtp":r=new $s(s);break;case"postmark":r=new Ds(s);break;case"resend":r=new ks(s);break;case"log":r=new tt;break;case"null":r=new Rs;break;case"custom":{if(!s.transport)throw new Error(`Custom mail driver "${t}" requires a "transport" instance.`);r=s.transport;break}default:throw new Error(`Unknown mail driver: ${s.driver}`)}return this.transports.set(t,r),r}},Ns=b("svelar.mail",()=>new Os)});import{createHmac as pe,randomBytes as Me}from"crypto";function rn(c){return(typeof c=="string"?Buffer.from(c):c).toString("base64url")}function nn(c){return Buffer.from(c,"base64url").toString("utf-8")}function on(c,e,t,s){return pe(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${c}.${e}`).digest("base64url")}function Ms(c,e,t="HS256"){let s=rn(JSON.stringify({alg:t,typ:"JWT"})),r=rn(JSON.stringify(c)),n=on(s,r,e,t);return`${s}.${r}.${n}`}function Ls(c,e){let t=c.split(".");if(t.length!==3)return null;let[s,r,n]=t,o;try{o=JSON.parse(nn(s))}catch{return null}let i=on(s,r,e,o.alg);if(n!==i)return null;try{let a=JSON.parse(nn(r));return a.exp&&Date.now()/1e3>a.exp?null:a}catch{return null}}var rt,me,nt,Is=y(()=>{"use strict";ce();rt=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(he(),Ne)),r=e[this.config.identifierColumn],n=e[this.config.passwordColumn];if(!r||!n)return null;let o=await this.config.model.where(this.config.identifierColumn,r).first();if(!o)return null;let i=o.getAttribute(this.config.passwordColumn);return await s.verify(n,i)?(this.currentUser=o,t&&(t.set("auth_user_id",o.getAttribute("id")),t.regenerateId()),o):null}async attemptJwt(e){let{Hash:t}=await Promise.resolve().then(()=>(he(),Ne));if(!this.config.jwt)throw new Error("JWT configuration required for JWT guard.");let s=e[this.config.identifierColumn],r=e[this.config.passwordColumn];if(!s||!r)return null;let n=await this.config.model.where(this.config.identifierColumn,s).first();if(!n)return null;let o=n.getAttribute(this.config.passwordColumn);return await t.verify(r,o)?(this.currentUser=n,this.issueTokenPair(n)):null}async issueTokenPair(e){let t=this.config.jwt,s=t.expiresIn??3600,r=Math.floor(Date.now()/1e3),n={sub:e.getAttribute("id"),iat:r,exp:r+s,...t.issuer?{iss:t.issuer}:{}},o=Ms(n,t.secret,t.algorithm),i=new Date((r+s)*1e3),a={user:e,token:o,expiresAt:i};if(t.refreshTokens){let l=t.refreshExpiresIn??604800,u=Me(32).toString("base64url"),d=pe("sha256",t.secret).update(u).digest("hex"),h=new Date((r+l)*1e3),{Connection:m}=await Promise.resolve().then(()=>(w(),v)),f=t.refreshTable??"refresh_tokens";await m.raw(`INSERT INTO ${f} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),d,h.toISOString(),new Date().toISOString()]),a.refreshToken=u,a.refreshExpiresAt=h}return a}async refreshJwt(e){if(!this.config.jwt)throw new Error("JWT configuration required.");if(!this.config.jwt.refreshTokens)throw new Error("Refresh tokens are not enabled. Set jwt.refreshTokens = true.");let t=this.config.jwt,s=pe("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(w(),v)),n=t.refreshTable??"refresh_tokens",o=await r.raw(`SELECT user_id, expires_at, revoked_at FROM ${n} WHERE token = ?`,[s]);if(o.length===0)return null;let i=o[0];if(i.revoked_at||new Date(i.expires_at)<new Date)return null;await r.raw(`UPDATE ${n} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let a=await this.config.model.find(i.user_id);return a?(this.currentUser=a,this.issueTokenPair(a)):null}async revokeRefreshTokens(e){if(!this.config.jwt?.refreshTokens)return;let{Connection:t}=await Promise.resolve().then(()=>(w(),v)),s=this.config.jwt.refreshTable??"refresh_tokens";await t.raw(`UPDATE ${s} SET revoked_at = ? WHERE user_id = ? AND revoked_at IS NULL`,[new Date().toISOString(),e])}async resolveFromToken(e){if(!this.config.jwt)throw new Error("JWT configuration required.");let t=Ls(e,this.config.jwt.secret);if(!t)return null;let s=await this.config.model.find(t.sub);return s&&(this.currentUser=s),s}async resolveFromSession(e){let t=e.get("auth_user_id");if(!t)return null;let s=await this.config.model.find(t);return s&&(this.currentUser=s),s}async register(e){let{Hash:t}=await Promise.resolve().then(()=>(he(),Ne));e[this.config.passwordColumn]&&(e[this.config.passwordColumn]=await t.make(e[this.config.passwordColumn]));let s=await this.config.model.create(e);return this.currentUser=s,s}async logout(e){this.currentUser=null,e&&(e.forget("auth_user_id"),e.regenerateId())}user(){return this.currentUser}check(){return this.currentUser!==null}id(){return this.currentUser?.getAttribute("id")??null}async generateApiToken(e,t="default"){let s=Me(32).toString("hex"),r=this.config.jwt?.secret??process.env.APP_KEY;if(!r)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");let n=pe("sha256",r).update(s).digest("hex"),{Connection:o}=await Promise.resolve().then(()=>(w(),v)),i=this.config.token?.table??"personal_access_tokens";return await o.raw(`INSERT INTO ${i} (user_id, name, token, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),t,n,new Date().toISOString()]),s}async resolveFromApiToken(e){let{Connection:t}=await Promise.resolve().then(()=>(w(),v)),s=this.config.token?.table??"personal_access_tokens",r=this.config.jwt?.secret??process.env.APP_KEY;if(!r)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");let n=pe("sha256",r).update(e).digest("hex"),o=await t.raw(`SELECT user_id FROM ${s} WHERE token = ?`,[n]);if(o.length===0)return null;let i=await this.config.model.find(o[0].user_id);return i&&(this.currentUser=i),i}async sendPasswordReset(e){let t=await this.config.model.where(this.config.identifierColumn,e).first();if(!t)return!1;let{Connection:s}=await Promise.resolve().then(()=>(w(),v)),r=this.config.passwordResets?.table??"password_resets",n=this.config.passwordResets?.expiresIn??3600;await this.ensureTable(r,`
112
+ Access until: {{accessUntilDate}}`,variables:["user.name","plan.name","accessUntilDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()})}interpolate(e,t){let s=e;return s=s.replace(/\{\{#if\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/if\}\}/g,(r,i,o)=>this.getNestedValue(t,i)?o:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,i,o)=>{let n=this.getNestedValue(t,i);return Array.isArray(n)?n.map((a,l)=>{let u={...t,this:a,$index:l};return this.interpolate(o,u)}).join(""):""}),s=s.replace(/\{\{([\w.$]+)\}\}/g,(r,i)=>{let o=this.getNestedValue(t,i);return o!=null?String(o):""}),s}getNestedValue(e,t){return t.split(".").reduce((s,r)=>s?.[r],e)}},Wo=b("svelar.emailTemplates",()=>new Ps)});var Ms={};P(Ms,{Mailable:()=>Ne,Mailer:()=>Ns});function As(c){return typeof c=="string"?c:`${c.name} <${c.address}>`}function k(c){return c?Array.isArray(c)?c:[c]:[]}function sn(c){return Buffer.isBuffer(c)?c.toString("base64"):Buffer.from(c).toString("base64")}var st,$s,Ds,ks,_s,Ne,Os,Ns,rt=y(()=>{"use strict";C();st=class{async send(e){let t=k(e.to);return console.log(`[Mail] To: ${t.join(", ")} | Subject: ${e.subject}`),e.text&&console.log(`[Mail] Body: ${e.text.slice(0,200)}`),{accepted:t,rejected:[]}}},$s=class{async send(e){return{accepted:k(e.to),rejected:[]}}},Ds=class{constructor(e){this.config=e}async send(e){try{let r=await(await import("nodemailer")).createTransport({host:this.config.host,port:this.config.port??587,secure:this.config.secure??!1,auth:this.config.auth}).sendMail({from:e.from?As(e.from):void 0,to:k(e.to).join(", "),cc:k(e.cc).join(", ")||void 0,bcc:k(e.bcc).join(", ")||void 0,replyTo:e.replyTo,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments});return{accepted:r.accepted,rejected:r.rejected,messageId:r.messageId}}catch(t){throw t.code==="MODULE_NOT_FOUND"?new Error("SMTP driver requires nodemailer. Install: npm install nodemailer"):t}}},ks=class{constructor(e){this.config=e}async send(e){let t=this.config.apiToken;if(!t)throw new Error("Postmark apiToken is required. Set it in your mailer config or POSTMARK_API_TOKEN env var.");let s=k(e.to),r=k(e.cc),i=k(e.bcc),o={From:e.from?As(e.from):void 0,To:s.join(", "),Subject:e.subject,MessageStream:this.config.messageStream||"outbound"};r.length>0&&(o.Cc=r.join(", ")),i.length>0&&(o.Bcc=i.join(", ")),e.replyTo&&(o.ReplyTo=e.replyTo),e.html&&(o.HtmlBody=e.html),e.text&&(o.TextBody=e.text),!o.HtmlBody&&!o.TextBody&&(o.TextBody=""),e.tags&&(o.Tag=Object.values(e.tags)[0]),e.attachments?.length&&(o.Attachments=e.attachments.map(l=>({Name:l.filename,Content:sn(l.content),ContentType:l.contentType||"application/octet-stream"})));let n=await fetch("https://api.postmarkapp.com/email",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","X-Postmark-Server-Token":t},body:JSON.stringify(o)});if(!n.ok){let l=await n.json().catch(()=>({Message:n.statusText}));throw new Error(`Postmark error ${n.status}: ${l.Message||JSON.stringify(l)}`)}let a=await n.json();return{accepted:s,rejected:[],messageId:a.MessageID}}},_s=class{constructor(e){this.config=e}async send(e){let t=this.config.apiKey;if(!t)throw new Error("Resend apiKey is required. Set it in your mailer config or RESEND_API_KEY env var.");let s=k(e.to),r=k(e.cc),i=k(e.bcc),o={from:e.from?As(e.from):void 0,to:s,subject:e.subject};r.length>0&&(o.cc=r),i.length>0&&(o.bcc=i),e.replyTo&&(o.reply_to=[e.replyTo]),e.html&&(o.html=e.html),e.text&&(o.text=e.text),e.tags&&(o.tags=Object.entries(e.tags).map(([l,u])=>({name:l,value:u}))),e.attachments?.length&&(o.attachments=e.attachments.map(l=>({filename:l.filename,content:sn(l.content),content_type:l.contentType||"application/octet-stream"})));let n=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!n.ok){let l=await n.json().catch(()=>({message:n.statusText}));throw new Error(`Resend error ${n.status}: ${l.message||JSON.stringify(l)}`)}let a=await n.json();return{accepted:s,rejected:[],messageId:a.id}}},Ne=class{message={};to(e){return this.message.to=e,this}cc(e){return this.message.cc=e,this}bcc(e){return this.message.bcc=e,this}from(e){return this.message.from=e,this}replyTo(e){return this.message.replyTo=e,this}subject(e){return this.message.subject=e,this}text(e){return this.message.text=e,this}html(e){return this.message.html=e,this}attach(e,t,s){return this.message.attachments||(this.message.attachments=[]),this.message.attachments.push({filename:e,content:t,contentType:s}),this}tag(e,t){return this.message.tags||(this.message.tags={}),this.message.tags[e]=t,this}toMessage(){return this.message}},Os=class{config=null;transports=new Map;configure(e){this.config=e,this.transports.clear()}async send(e,t){let s=this.resolveTransport(t);return!e.from&&this.config?.from&&(e.from=this.config.from),s.send(e)}async sendMailable(e,t){e.build();let s=e.toMessage();return!s.from&&this.config?.from&&(s.from=this.config.from),this.send(s,t)}mailer(e){let t=this.resolveTransport(e);return{send:s=>(!s.from&&this.config?.from&&(s.from=this.config.from),t.send(s))}}resolveTransport(e){let t=e??this.config?.default??"log";if(this.transports.has(t))return this.transports.get(t);if(!this.config){let i=new st;return this.transports.set(t,i),i}let s=this.config.mailers[t];if(!s)throw new Error(`Mailer "${t}" is not defined.`);let r;switch(s.driver){case"smtp":r=new Ds(s);break;case"postmark":r=new ks(s);break;case"resend":r=new _s(s);break;case"log":r=new st;break;case"null":r=new $s;break;case"custom":{if(!s.transport)throw new Error(`Custom mail driver "${t}" requires a "transport" instance.`);r=s.transport;break}default:throw new Error(`Unknown mail driver: ${s.driver}`)}return this.transports.set(t,r),r}},Ns=b("svelar.mail",()=>new Os)});import{createHmac as me,randomBytes as Me}from"crypto";function rn(c){return(typeof c=="string"?Buffer.from(c):c).toString("base64url")}function nn(c){return Buffer.from(c,"base64url").toString("utf-8")}function on(c,e,t,s){return me(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${c}.${e}`).digest("base64url")}function Ls(c,e,t="HS256"){let s=rn(JSON.stringify({alg:t,typ:"JWT"})),r=rn(JSON.stringify(c)),i=on(s,r,e,t);return`${s}.${r}.${i}`}function Is(c,e){let t=c.split(".");if(t.length!==3)return null;let[s,r,i]=t,o;try{o=JSON.parse(nn(s))}catch{return null}let n=on(s,r,e,o.alg);if(i!==n)return null;try{let a=JSON.parse(nn(r));return a.exp&&Date.now()/1e3>a.exp?null:a}catch{return null}}var nt,ge,it,js=y(()=>{"use strict";le();nt=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(pe(),Ae)),r=e[this.config.identifierColumn],i=e[this.config.passwordColumn];if(!r||!i)return null;let o=await this.config.model.where(this.config.identifierColumn,r).first();if(!o)return null;let n=o.getAttribute(this.config.passwordColumn);return await s.verify(i,n)?(this.currentUser=o,t&&(t.set("auth_user_id",o.getAttribute("id")),t.regenerateId()),o):null}async attemptJwt(e){let{Hash:t}=await Promise.resolve().then(()=>(pe(),Ae));if(!this.config.jwt)throw new Error("JWT configuration required for JWT guard.");let s=e[this.config.identifierColumn],r=e[this.config.passwordColumn];if(!s||!r)return null;let i=await this.config.model.where(this.config.identifierColumn,s).first();if(!i)return null;let o=i.getAttribute(this.config.passwordColumn);return await t.verify(r,o)?(this.currentUser=i,this.issueTokenPair(i)):null}async issueTokenPair(e){let t=this.config.jwt,s=t.expiresIn??3600,r=Math.floor(Date.now()/1e3),i={sub:e.getAttribute("id"),iat:r,exp:r+s,...t.issuer?{iss:t.issuer}:{}},o=Ls(i,t.secret,t.algorithm),n=new Date((r+s)*1e3),a={user:e,token:o,expiresAt:n};if(t.refreshTokens){let l=t.refreshExpiresIn??604800,u=Me(32).toString("base64url"),d=me("sha256",t.secret).update(u).digest("hex"),h=new Date((r+l)*1e3),{Connection:m}=await Promise.resolve().then(()=>(v(),w)),f=t.refreshTable??"refresh_tokens";await m.raw(`INSERT INTO ${f} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),d,h.toISOString(),new Date().toISOString()]),a.refreshToken=u,a.refreshExpiresAt=h}return a}async refreshJwt(e){if(!this.config.jwt)throw new Error("JWT configuration required.");if(!this.config.jwt.refreshTokens)throw new Error("Refresh tokens are not enabled. Set jwt.refreshTokens = true.");let t=this.config.jwt,s=me("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(v(),w)),i=t.refreshTable??"refresh_tokens",o=await r.raw(`SELECT user_id, expires_at, revoked_at FROM ${i} WHERE token = ?`,[s]);if(o.length===0)return null;let n=o[0];if(n.revoked_at||new Date(n.expires_at)<new Date)return null;await r.raw(`UPDATE ${i} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let a=await this.config.model.find(n.user_id);return a?(this.currentUser=a,this.issueTokenPair(a)):null}async revokeRefreshTokens(e){if(!this.config.jwt?.refreshTokens)return;let{Connection:t}=await Promise.resolve().then(()=>(v(),w)),s=this.config.jwt.refreshTable??"refresh_tokens";await t.raw(`UPDATE ${s} SET revoked_at = ? WHERE user_id = ? AND revoked_at IS NULL`,[new Date().toISOString(),e])}async resolveFromToken(e){if(!this.config.jwt)throw new Error("JWT configuration required.");let t=Is(e,this.config.jwt.secret);if(!t)return null;let s=await this.config.model.find(t.sub);return s&&(this.currentUser=s),s}async resolveFromSession(e){let t=e.get("auth_user_id");if(!t)return null;let s=await this.config.model.find(t);return s&&(this.currentUser=s),s}async register(e){let{Hash:t}=await Promise.resolve().then(()=>(pe(),Ae));e[this.config.passwordColumn]&&(e[this.config.passwordColumn]=await t.make(e[this.config.passwordColumn]));let s=await this.config.model.create(e);return this.currentUser=s,s}async logout(e){this.currentUser=null,e&&(e.forget("auth_user_id"),e.regenerateId())}user(){return this.currentUser}check(){return this.currentUser!==null}id(){return this.currentUser?.getAttribute("id")??null}async generateApiToken(e,t="default"){let s=Me(32).toString("hex"),r=this.config.jwt?.secret??process.env.APP_KEY;if(!r)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");let i=me("sha256",r).update(s).digest("hex"),{Connection:o}=await Promise.resolve().then(()=>(v(),w)),n=this.config.token?.table??"personal_access_tokens";return await o.raw(`INSERT INTO ${n} (user_id, name, token, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),t,i,new Date().toISOString()]),s}async resolveFromApiToken(e){let{Connection:t}=await Promise.resolve().then(()=>(v(),w)),s=this.config.token?.table??"personal_access_tokens",r=this.config.jwt?.secret??process.env.APP_KEY;if(!r)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");let i=me("sha256",r).update(e).digest("hex"),o=await t.raw(`SELECT user_id FROM ${s} WHERE token = ?`,[i]);if(o.length===0)return null;let n=await this.config.model.find(o[0].user_id);return n&&(this.currentUser=n),n}async sendPasswordReset(e){let t=await this.config.model.where(this.config.identifierColumn,e).first();if(!t)return!1;let{Connection:s}=await Promise.resolve().then(()=>(v(),w)),r=this.config.passwordResets?.table??"password_resets",i=this.config.passwordResets?.expiresIn??3600;await this.ensureTable(r,`
113
113
  CREATE TABLE IF NOT EXISTS ${r} (
114
114
  email TEXT NOT NULL,
115
115
  token TEXT NOT NULL,
116
116
  expires_at TEXT NOT NULL,
117
117
  created_at TEXT NOT NULL
118
118
  )
119
- `),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let o=Me(32).toString("base64url"),i=this.hashToken(o),a=new Date(Date.now()+n*1e3).toISOString();await s.raw(`INSERT INTO ${r} (email, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e,i,a,new Date().toISOString()]);let l=this.config.appUrl??process.env.APP_URL??"http://localhost:5173",u=this.config.appName??process.env.APP_NAME??"Svelar",d=`${l}/reset-password?token=${o}&email=${encodeURIComponent(e)}`;return await this.sendAuthEmail("password-reset",e,{appName:u,"user.name":t.getAttribute("name")??e,resetUrl:d}),!0}async resetPassword(e,t,s){let{Connection:r}=await Promise.resolve().then(()=>(w(),v)),{Hash:n}=await Promise.resolve().then(()=>(he(),Ne)),o=this.config.passwordResets?.table??"password_resets",i=this.hashToken(e),a=await r.raw(`SELECT email, expires_at FROM ${o} WHERE token = ? AND email = ?`,[i,t]);if(a.length===0)return!1;let l=a[0];if(new Date(l.expires_at)<new Date)return await r.raw(`DELETE FROM ${o} WHERE email = ?`,[t]),!1;let u=await this.config.model.where(this.config.identifierColumn,t).first();if(!u)return!1;let d=await n.make(s);return await this.config.model.where("id",u.getAttribute("id")).update({[this.config.passwordColumn]:d}),await r.raw(`DELETE FROM ${o} WHERE email = ?`,[t]),await this.revokeRefreshTokens(u.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(w(),v)),s=this.config.emailVerification?.table??"email_verifications",r=this.config.emailVerification?.expiresIn??86400,n=e.getAttribute(this.config.identifierColumn);await this.ensureTable(s,`
119
+ `),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let o=Me(32).toString("base64url"),n=this.hashToken(o),a=new Date(Date.now()+i*1e3).toISOString();await s.raw(`INSERT INTO ${r} (email, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e,n,a,new Date().toISOString()]);let l=this.config.appUrl??process.env.APP_URL??"http://localhost:5173",u=this.config.appName??process.env.APP_NAME??"Svelar",d=`${l}/reset-password?token=${o}&email=${encodeURIComponent(e)}`;return await this.sendAuthEmail("password-reset",e,{appName:u,"user.name":t.getAttribute("name")??e,resetUrl:d}),!0}async resetPassword(e,t,s){let{Connection:r}=await Promise.resolve().then(()=>(v(),w)),{Hash:i}=await Promise.resolve().then(()=>(pe(),Ae)),o=this.config.passwordResets?.table??"password_resets",n=this.hashToken(e),a=await r.raw(`SELECT email, expires_at FROM ${o} WHERE token = ? AND email = ?`,[n,t]);if(a.length===0)return!1;let l=a[0];if(new Date(l.expires_at)<new Date)return await r.raw(`DELETE FROM ${o} WHERE email = ?`,[t]),!1;let u=await this.config.model.where(this.config.identifierColumn,t).first();if(!u)return!1;let d=await i.make(s);return await this.config.model.where("id",u.getAttribute("id")).update({[this.config.passwordColumn]:d}),await r.raw(`DELETE FROM ${o} WHERE email = ?`,[t]),await this.revokeRefreshTokens(u.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(v(),w)),s=this.config.emailVerification?.table??"email_verifications",r=this.config.emailVerification?.expiresIn??86400,i=e.getAttribute(this.config.identifierColumn);await this.ensureTable(s,`
120
120
  CREATE TABLE IF NOT EXISTS ${s} (
121
121
  user_id TEXT NOT NULL,
122
122
  token TEXT NOT NULL,
123
123
  expires_at TEXT NOT NULL,
124
124
  created_at TEXT NOT NULL
125
125
  )
126
- `),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let o=Me(32).toString("base64url"),i=this.hashToken(o),a=new Date(Date.now()+r*1e3).toISOString();await t.raw(`INSERT INTO ${s} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),i,a,new Date().toISOString()]);let u=`${this.config.appUrl??process.env.APP_URL??"http://localhost:5173"}/verify-email?token=${o}&id=${e.getAttribute("id")}`;await this.sendAuthEmail("email-verification",n,{"user.name":e.getAttribute("name")??n,verifyUrl:u})}async verifyEmail(e,t){let{Connection:s}=await Promise.resolve().then(()=>(w(),v)),r=this.config.emailVerification?.table??"email_verifications",n=this.config.emailVerification?.verifiedColumn??"email_verified_at",o=this.hashToken(e),i=await s.raw(`SELECT user_id, expires_at FROM ${r} WHERE token = ? AND user_id = ?`,[o,t]);return i.length===0?!1:new Date(i[0].expires_at)<new Date?(await s.raw(`DELETE FROM ${r} WHERE user_id = ?`,[t]),!1):(await this.config.model.where("id",t).update({[n]:new Date().toISOString()}),await s.raw(`DELETE FROM ${r} WHERE user_id = ?`,[t]),!0)}isEmailVerified(e){let t=this.config.emailVerification?.verifiedColumn??"email_verified_at";return!!e.getAttribute(t)}async sendOtp(e,t="login"){let s=await this.config.model.where(this.config.identifierColumn,e).first();if(!s)return!1;let{Connection:r}=await Promise.resolve().then(()=>(w(),v)),n=this.config.otp?.table??"otp_codes",o=this.config.otp?.expiresIn??600,i=this.config.otp?.length??6;await this.ensureTable(n,`
127
- CREATE TABLE IF NOT EXISTS ${n} (
126
+ `),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let o=Me(32).toString("base64url"),n=this.hashToken(o),a=new Date(Date.now()+r*1e3).toISOString();await t.raw(`INSERT INTO ${s} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),n,a,new Date().toISOString()]);let u=`${this.config.appUrl??process.env.APP_URL??"http://localhost:5173"}/verify-email?token=${o}&id=${e.getAttribute("id")}`;await this.sendAuthEmail("email-verification",i,{"user.name":e.getAttribute("name")??i,verifyUrl:u})}async verifyEmail(e,t){let{Connection:s}=await Promise.resolve().then(()=>(v(),w)),r=this.config.emailVerification?.table??"email_verifications",i=this.config.emailVerification?.verifiedColumn??"email_verified_at",o=this.hashToken(e),n=await s.raw(`SELECT user_id, expires_at FROM ${r} WHERE token = ? AND user_id = ?`,[o,t]);return n.length===0?!1:new Date(n[0].expires_at)<new Date?(await s.raw(`DELETE FROM ${r} WHERE user_id = ?`,[t]),!1):(await this.config.model.where("id",t).update({[i]:new Date().toISOString()}),await s.raw(`DELETE FROM ${r} WHERE user_id = ?`,[t]),!0)}isEmailVerified(e){let t=this.config.emailVerification?.verifiedColumn??"email_verified_at";return!!e.getAttribute(t)}async sendOtp(e,t="login"){let s=await this.config.model.where(this.config.identifierColumn,e).first();if(!s)return!1;let{Connection:r}=await Promise.resolve().then(()=>(v(),w)),i=this.config.otp?.table??"otp_codes",o=this.config.otp?.expiresIn??600,n=this.config.otp?.length??6;await this.ensureTable(i,`
127
+ CREATE TABLE IF NOT EXISTS ${i} (
128
128
  email TEXT NOT NULL,
129
129
  code TEXT NOT NULL,
130
130
  purpose TEXT NOT NULL DEFAULT 'login',
@@ -132,35 +132,35 @@ Access until: {{accessUntilDate}}`,variables:["user.name","plan.name","accessUnt
132
132
  used_at TEXT,
133
133
  created_at TEXT NOT NULL
134
134
  )
135
- `),await r.raw(`DELETE FROM ${n} WHERE email = ? AND purpose = ?`,[e,t]);let a=this.generateOtpCode(i),l=this.hashToken(a),u=new Date(Date.now()+o*1e3).toISOString();await r.raw(`INSERT INTO ${n} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,l,t,u,new Date().toISOString()]);let d=this.config.appName??process.env.APP_NAME??"Svelar",h=Math.ceil(o/60);return await this.sendAuthEmail("otp-code",e,{appName:d,"user.name":s.getAttribute("name")??e,code:a,purpose:t,expiresMinutes:String(h)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(w(),v)),n=this.config.otp?.table??"otp_codes",o=this.hashToken(t),i=await r.raw(`SELECT email, expires_at, used_at FROM ${n} WHERE code = ? AND email = ? AND purpose = ? AND used_at IS NULL`,[o,e,s]);if(i.length===0)return null;if(new Date(i[0].expires_at)<new Date)return await r.raw(`DELETE FROM ${n} WHERE email = ? AND purpose = ?`,[e,s]),null;await r.raw(`UPDATE ${n} SET used_at = ? WHERE code = ? AND email = ? AND purpose = ?`,[new Date().toISOString(),o,e,s]);let a=await this.config.model.where(this.config.identifierColumn,e).first();return a&&(this.currentUser=a),a}async attemptOtp(e,t,s,r="login"){let n=await this.verifyOtp(e,t,r);return n?(s&&(s.set("auth_user_id",n.getAttribute("id")),s.regenerateId()),n):null}async cleanupExpiredTokens(){let{Connection:e}=await Promise.resolve().then(()=>(w(),v)),t=new Date().toISOString(),s=0,r=0,n=0,o=this.config.passwordResets?.table??"password_resets",i=this.config.emailVerification?.table??"email_verifications",a=this.config.otp?.table??"otp_codes";try{s=(await e.raw(`DELETE FROM ${o} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{r=(await e.raw(`DELETE FROM ${i} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{n=(await e.raw(`DELETE FROM ${a} WHERE expires_at < ? OR used_at IS NOT NULL`,[t]))?.changes??0}catch{}return{passwordResets:s,verifications:r,otpCodes:n}}hashToken(e){let t=this.config.jwt?.secret??process.env.APP_KEY;if(!t)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");return pe("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=Me(e);return Array.from(t).map(s=>(s%10).toString()).join("")}tablesEnsured=new Set;async ensureTable(e,t){if(this.tablesEnsured.has(e))return;let{Connection:s}=await Promise.resolve().then(()=>(w(),v));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(tn(),en)),{Mailer:n}=await Promise.resolve().then(()=>(st(),_s)),o=await r.render(e,s);await n.send({to:t,subject:o.subject,html:o.html,text:o.text})}catch(r){console.error(`[Auth] Failed to send ${e} email to ${t}:`,r.message)}}},me=class extends x{constructor(t){super();this.authManager=t}async handle(t,s){let r=null;if(t.event.locals.session&&(r=await this.authManager.resolveFromSession(t.event.locals.session)),!r){let n=t.event.request.headers.get("authorization");if(n?.startsWith("Bearer ")){let o=n.slice(7);try{r=await this.authManager.resolveFromToken(o)}catch{r=await this.authManager.resolveFromApiToken(o)}}}return t.event.locals.user=r,t.event.locals.auth=this.authManager,s()}},nt=class extends x{async handle(e,t){return e.event.locals.user?t():new Response(JSON.stringify({message:"Unauthenticated"}),{status:401,headers:{"Content-Type":"application/json"}})}}});import{appendFile as Jo,mkdir as Vo}from"fs/promises";import{dirname as zo}from"path";function _(){return new Date().toISOString()}var it,Le,js,qs,Us,Hs,Fs,ot,Bs=y(()=>{"use strict";C();it={debug:0,info:1,warn:2,error:3,fatal:4},Le=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(it[e.level]<it[this.minLevel])return;if(this.format==="json"){console.log(JSON.stringify(e));return}let t={debug:"\x1B[90m",info:"\x1B[34m",warn:"\x1B[33m",error:"\x1B[31m",fatal:"\x1B[35m"},s="\x1B[0m",r=t[e.level]??"",n=e.level.toUpperCase().padEnd(5),o=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"",i=e.level==="error"||e.level==="fatal"?"error":"log";console[i](`${r}[${e.timestamp}] ${n}${s} ${e.message}${o}`)}},js=class{minLevel;path;format;initialized=!1;constructor(e){this.minLevel=e.level??"info",this.path=e.path??"storage/logs/app.log",this.format=e.format??"text"}async write(e){if(it[e.level]<it[this.minLevel])return;this.initialized||(await Vo(zo(this.path),{recursive:!0}),this.initialized=!0);let t;if(this.format==="json")t=JSON.stringify(e)+`
135
+ `),await r.raw(`DELETE FROM ${i} WHERE email = ? AND purpose = ?`,[e,t]);let a=this.generateOtpCode(n),l=this.hashToken(a),u=new Date(Date.now()+o*1e3).toISOString();await r.raw(`INSERT INTO ${i} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,l,t,u,new Date().toISOString()]);let d=this.config.appName??process.env.APP_NAME??"Svelar",h=Math.ceil(o/60);return await this.sendAuthEmail("otp-code",e,{appName:d,"user.name":s.getAttribute("name")??e,code:a,purpose:t,expiresMinutes:String(h)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(v(),w)),i=this.config.otp?.table??"otp_codes",o=this.hashToken(t),n=await r.raw(`SELECT email, expires_at, used_at FROM ${i} WHERE code = ? AND email = ? AND purpose = ? AND used_at IS NULL`,[o,e,s]);if(n.length===0)return null;if(new Date(n[0].expires_at)<new Date)return await r.raw(`DELETE FROM ${i} WHERE email = ? AND purpose = ?`,[e,s]),null;await r.raw(`UPDATE ${i} SET used_at = ? WHERE code = ? AND email = ? AND purpose = ?`,[new Date().toISOString(),o,e,s]);let a=await this.config.model.where(this.config.identifierColumn,e).first();return a&&(this.currentUser=a),a}async attemptOtp(e,t,s,r="login"){let i=await this.verifyOtp(e,t,r);return i?(s&&(s.set("auth_user_id",i.getAttribute("id")),s.regenerateId()),i):null}async cleanupExpiredTokens(){let{Connection:e}=await Promise.resolve().then(()=>(v(),w)),t=new Date().toISOString(),s=0,r=0,i=0,o=this.config.passwordResets?.table??"password_resets",n=this.config.emailVerification?.table??"email_verifications",a=this.config.otp?.table??"otp_codes";try{s=(await e.raw(`DELETE FROM ${o} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{r=(await e.raw(`DELETE FROM ${n} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{i=(await e.raw(`DELETE FROM ${a} WHERE expires_at < ? OR used_at IS NOT NULL`,[t]))?.changes??0}catch{}return{passwordResets:s,verifications:r,otpCodes:i}}hashToken(e){let t=this.config.jwt?.secret??process.env.APP_KEY;if(!t)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");return me("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=Me(e);return Array.from(t).map(s=>(s%10).toString()).join("")}tablesEnsured=new Set;async ensureTable(e,t){if(this.tablesEnsured.has(e))return;let{Connection:s}=await Promise.resolve().then(()=>(v(),w));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(tn(),en)),{Mailer:i}=await Promise.resolve().then(()=>(rt(),Ms)),o=await r.render(e,s);await i.send({to:t,subject:o.subject,html:o.html,text:o.text})}catch(r){console.error(`[Auth] Failed to send ${e} email to ${t}:`,r.message)}}},ge=class extends x{constructor(t){super();this.authManager=t}async handle(t,s){let r=null;if(t.event.locals.session&&(r=await this.authManager.resolveFromSession(t.event.locals.session)),!r){let i=t.event.request.headers.get("authorization");if(i?.startsWith("Bearer ")){let o=i.slice(7);try{r=await this.authManager.resolveFromToken(o)}catch{r=await this.authManager.resolveFromApiToken(o)}}}return t.event.locals.user=r,t.event.locals.auth=this.authManager,s()}},it=class extends x{async handle(e,t){return e.event.locals.user?t():new Response(JSON.stringify({message:"Unauthenticated"}),{status:401,headers:{"Content-Type":"application/json"}})}}});import{appendFile as zo,mkdir as Jo}from"fs/promises";import{dirname as Yo}from"path";function N(){return new Date().toISOString()}var ot,Le,qs,Us,Hs,Fs,Bs,at,Ks=y(()=>{"use strict";C();ot={debug:0,info:1,warn:2,error:3,fatal:4},Le=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(ot[e.level]<ot[this.minLevel])return;if(this.format==="json"){console.log(JSON.stringify(e));return}let t={debug:"\x1B[90m",info:"\x1B[34m",warn:"\x1B[33m",error:"\x1B[31m",fatal:"\x1B[35m"},s="\x1B[0m",r=t[e.level]??"",i=e.level.toUpperCase().padEnd(5),o=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"",n=e.level==="error"||e.level==="fatal"?"error":"log";console[n](`${r}[${e.timestamp}] ${i}${s} ${e.message}${o}`)}},qs=class{minLevel;path;format;initialized=!1;constructor(e){this.minLevel=e.level??"info",this.path=e.path??"storage/logs/app.log",this.format=e.format??"text"}async write(e){if(ot[e.level]<ot[this.minLevel])return;this.initialized||(await Jo(Yo(this.path),{recursive:!0}),this.initialized=!0);let t;if(this.format==="json")t=JSON.stringify(e)+`
136
136
  `;else{let s=e.level.toUpperCase().padEnd(5),r=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"";t=`[${e.timestamp}] ${s} ${e.message}${r}
137
- `}await Jo(this.path,t)}},qs=class{minLevel="debug";channelNames;resolver;constructor(e,t){this.channelNames=e.channels??[],this.resolver=t,this.minLevel=e.level??"debug"}async write(e){for(let t of this.channelNames){let s=this.resolver(t);s&&await s.write(e)}}},Us=class{minLevel="debug";write(){}},Hs=class{config={default:"console",channels:{console:{driver:"console",level:"debug"}}};channels=new Map;configure(e){this.config=e,this.channels.clear()}channel(e){return new Fs(this.resolveChannel(e))}debug(e,t={}){this.writeToDefault({level:"debug",message:e,context:t,timestamp:_()})}info(e,t={}){this.writeToDefault({level:"info",message:e,context:t,timestamp:_()})}warn(e,t={}){this.writeToDefault({level:"warn",message:e,context:t,timestamp:_()})}error(e,t={}){this.writeToDefault({level:"error",message:e,context:t,timestamp:_()})}fatal(e,t={}){this.writeToDefault({level:"fatal",message:e,context:t,timestamp:_()})}writeToDefault(e){this.resolveChannel(this.config.default).write(e)}resolveChannel(e){if(this.channels.has(e))return this.channels.get(e);let t=this.config.channels[e];if(!t){let r=new Le({driver:"console"});return this.channels.set(e,r),r}let s=this.createChannel(t);return this.channels.set(e,s),s}createChannel(e){switch(e.driver){case"console":return new Le(e);case"file":return new js(e);case"stack":return new qs(e,t=>this.resolveChannel(t));case"null":return new Us;default:return new Le(e)}}},Fs=class{constructor(e){this.channel=e}debug(e,t={}){this.channel.write({level:"debug",message:e,context:t,timestamp:_()})}info(e,t={}){this.channel.write({level:"info",message:e,context:t,timestamp:_()})}warn(e,t={}){this.channel.write({level:"warn",message:e,context:t,timestamp:_()})}error(e,t={}){this.channel.write({level:"error",message:e,context:t,timestamp:_()})}fatal(e,t={}){this.channel.write({level:"fatal",message:e,context:t,timestamp:_()})}};ot=b("svelar.log",()=>new Hs)});function ut(c,e){throw new k(c,e??Yo(c))}function an(c,e,t){c&&ut(e,t)}function cn(c,e,t){c||ut(e,t)}function Yo(c){return{400:"Bad request",401:"Unauthenticated",403:"Forbidden",404:"Not found",405:"Method not allowed",409:"Conflict",419:"Page expired",422:"Unprocessable entity",429:"Too many requests",500:"Internal server error",502:"Bad gateway",503:"Service unavailable",504:"Gateway timeout"}[c]??"An error occurred"}var k,at,Ks,Ws,ct,lt,ge,Js=y(()=>{"use strict";Bs();k=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},at=class extends k{constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},Ks=class extends k{constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},Ws=class extends k{constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},ct=class extends k{constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},lt=class extends at{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};ge=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[ct,at,Ks,Ws],...e}}async handle(e,t){let s=e instanceof Error?e:new Error(String(e));return await this.reportError(s,t),this.config.render?this.config.render(s,t):this.renderError(s)}handleSvelteKitError(){return({error:e,event:t,status:s,message:r})=>{let n=e instanceof Error?e:new Error(String(e));return this.reportError(n,t),n instanceof k?{message:n.message,status:n.statusCode,...n.details??{},...this.config.debug?{stack:n.stack}:{}}:{message:this.config.debug?n.message:"An unexpected error occurred",status:s,...this.config.debug?{stack:n.stack}:{}}}}middleware(){let e=this;return async(t,s)=>{try{return await s()}catch(r){return e.handle(r,t.event)}}}async reportError(e,t){if(this.config.dontReport){for(let r of this.config.dontReport)if(e instanceof r)return}let s={error:e.name,...t?.url?{url:t.url.toString()}:{},...e.stack?{stack:e.stack}:{}};if(ot.error(e.message,s),this.config.report)try{await this.config.report(e,t?{url:t.url?.toString()}:void 0)}catch{}}renderError(e){if(e instanceof k){let s={message:e.message};return e instanceof ct&&(s.errors=e.errors),e.details&&Object.assign(s,e.details),this.config.debug&&(s.exception=e.name,s.stack=e.stack?.split(`
137
+ `}await zo(this.path,t)}},Us=class{minLevel="debug";channelNames;resolver;constructor(e,t){this.channelNames=e.channels??[],this.resolver=t,this.minLevel=e.level??"debug"}async write(e){for(let t of this.channelNames){let s=this.resolver(t);s&&await s.write(e)}}},Hs=class{minLevel="debug";write(){}},Fs=class{config={default:"console",channels:{console:{driver:"console",level:"debug"}}};channels=new Map;configure(e){this.config=e,this.channels.clear()}channel(e){return new Bs(this.resolveChannel(e))}debug(e,t={}){this.writeToDefault({level:"debug",message:e,context:t,timestamp:N()})}info(e,t={}){this.writeToDefault({level:"info",message:e,context:t,timestamp:N()})}warn(e,t={}){this.writeToDefault({level:"warn",message:e,context:t,timestamp:N()})}error(e,t={}){this.writeToDefault({level:"error",message:e,context:t,timestamp:N()})}fatal(e,t={}){this.writeToDefault({level:"fatal",message:e,context:t,timestamp:N()})}writeToDefault(e){this.resolveChannel(this.config.default).write(e)}resolveChannel(e){if(this.channels.has(e))return this.channels.get(e);let t=this.config.channels[e];if(!t){let r=new Le({driver:"console"});return this.channels.set(e,r),r}let s=this.createChannel(t);return this.channels.set(e,s),s}createChannel(e){switch(e.driver){case"console":return new Le(e);case"file":return new qs(e);case"stack":return new Us(e,t=>this.resolveChannel(t));case"null":return new Hs;default:return new Le(e)}}},Bs=class{constructor(e){this.channel=e}debug(e,t={}){this.channel.write({level:"debug",message:e,context:t,timestamp:N()})}info(e,t={}){this.channel.write({level:"info",message:e,context:t,timestamp:N()})}warn(e,t={}){this.channel.write({level:"warn",message:e,context:t,timestamp:N()})}error(e,t={}){this.channel.write({level:"error",message:e,context:t,timestamp:N()})}fatal(e,t={}){this.channel.write({level:"fatal",message:e,context:t,timestamp:N()})}};at=b("svelar.log",()=>new Fs)});function dt(c,e){throw new _(c,e??Vo(c))}function an(c,e,t){c&&dt(e,t)}function cn(c,e,t){c||dt(e,t)}function Vo(c){return{400:"Bad request",401:"Unauthenticated",403:"Forbidden",404:"Not found",405:"Method not allowed",409:"Conflict",419:"Page expired",422:"Unprocessable entity",429:"Too many requests",500:"Internal server error",502:"Bad gateway",503:"Service unavailable",504:"Gateway timeout"}[c]??"An error occurred"}var _,ct,Ws,zs,lt,ut,fe,Js=y(()=>{"use strict";Ks();_=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},ct=class extends _{constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},Ws=class extends _{constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},zs=class extends _{constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},lt=class extends _{constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},ut=class extends ct{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};fe=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[lt,ct,Ws,zs],...e}}async handle(e,t){let s=e instanceof Error?e:new Error(String(e));return await this.reportError(s,t),this.config.render?this.config.render(s,t):this.renderError(s)}handleSvelteKitError(){return({error:e,event:t,status:s,message:r})=>{let i=e instanceof Error?e:new Error(String(e));return this.reportError(i,t),i instanceof _?{message:i.message,status:i.statusCode,...i.details??{},...this.config.debug?{stack:i.stack}:{}}:{message:this.config.debug?i.message:"An unexpected error occurred",status:s,...this.config.debug?{stack:i.stack}:{}}}}middleware(){let e=this;return async(t,s)=>{try{return await s()}catch(r){return e.handle(r,t.event)}}}async reportError(e,t){if(this.config.dontReport){for(let r of this.config.dontReport)if(e instanceof r)return}let s={error:e.name,...t?.url?{url:t.url.toString()}:{},...e.stack?{stack:e.stack}:{}};if(at.error(e.message,s),this.config.report)try{await this.config.report(e,t?{url:t.url?.toString()}:void 0)}catch{}}renderError(e){if(e instanceof _){let s={message:e.message};return e instanceof lt&&(s.errors=e.errors),e.details&&Object.assign(s,e.details),this.config.debug&&(s.exception=e.name,s.stack=e.stack?.split(`
138
138
  `).map(r=>r.trim())),new Response(JSON.stringify(s),{status:e.statusCode,headers:{"Content-Type":"application/json"}})}let t={message:this.config.debug?e.message:"Internal server error"};return this.config.debug&&(t.exception=e.name,t.stack=e.stack?.split(`
139
- `).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function ln(c={}){let{auth:e,secret:t=(()=>{throw new Error("APP_KEY is not set. Pass `secret` to createSvelarApp() \u2014 e.g. secret: env.APP_KEY (from $env/dynamic/private).")})(),sessionStore:s,sessionLifetime:r=86400,rateLimit:n=100,rateLimitWindow:o=6e4,csrfPaths:i=["/api/"],csrfExcludePaths:a=["/api/webhooks"],authThrottleAttempts:l=5,authThrottleDecay:u=1,debug:d=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:m={},i18n:f,errorConfig:E={}}=c,T=[new oe,new ne({maxRequests:n,windowMs:o}),new ie({onlyPaths:i,excludePaths:a}),new de({store:s??new W,secret:t,lifetime:r})];e&&T.push(new me(e)),T.push(...h);let be={"auth-throttle":new ae({maxAttempts:l,decayMinutes:u}),...m},O=new ge({debug:d,...E}),z=Vs({middleware:T,namedMiddleware:be,onError:(wt,vt)=>O.handle(wt,vt)}),$;if(f){let{paraglideMiddleware:wt,getTextDirection:vt=()=>"ltr"}=f;$=zs(async({event:Et,resolve:Wn})=>wt(Et.request,({request:Jn,locale:Sr})=>(Et.request=Jn,Wn(Et,{transformPageChunk:({html:Vn})=>Vn.replace("%lang%",Sr).replace("%dir%",vt(Sr))}))),z)}else $=z;return{handle:$,handleError:O.handleSvelteKitError()}}function Vs(c={}){let e=new q;if(c.middleware)for(let t of c.middleware)e.use(t);if(c.namedMiddleware)for(let[t,s]of Object.entries(c.namedMiddleware))e.register(t,s);return async function({event:s,resolve:r}){let n={event:s,params:s.params??{},locals:s.locals??{}};try{c.app&&!c.app.isBooted()&&await c.app.bootstrap();let o=await e.execute(n,async()=>r(s));return o instanceof Response?o:r(s)}catch(o){if(c.onError){let i=await c.onError(o,s);if(i instanceof Response)return i}return console.error("[Svelar] Unhandled error in hooks:",o),new Response(JSON.stringify({message:process.env.NODE_ENV==="production"?"Internal server error":o.message}),{status:500,headers:{"Content-Type":"application/json"}})}}}function zs(...c){return async function({event:t,resolve:s}){let r=s;for(let n=c.length-1;n>=0;n--){let o=c[n],i=r;r=a=>o({event:a,resolve:i})}return r(t)}}var Ys=y(()=>{"use strict";ce();Ts();Is();Js()});function un(c,e){let t=process.env[c];return t===void 0?e!==void 0?e:"":t==="true"?!0:t==="false"?!1:t==="null"?null:/^\d+$/.test(t)?Number(t):t}var Gs,dn,hn=y(()=>{"use strict";C();Gs=class{items=new Map;clear(){this.items.clear()}load(e){for(let[t,s]of Object.entries(e))this.set(t,s)}async loadFromDirectory(e){let{resolve:t,basename:s,extname:r}=await import("path"),{existsSync:n,readdirSync:o}=await import("fs"),{pathToFileURL:i}=await import("url"),a=t(e);if(!n(a))return[];let l=o(a).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith(".")),u=[];for(let d of l){let h=s(d,r(d)),m=t(a,d);try{let E=await import(i(m).href),T=E.default??E.config??E;T&&typeof T=="object"&&!Array.isArray(T)&&(this.set(h,T),u.push(h))}catch{}}return u}get(e,t){let s=e.split("."),r=this.items.get(s[0]);for(let n=1;n<s.length;n++){if(r==null)return t;r=r[s[n]]}return r??t}set(e,t){let s=e.split(".");if(s.length===1){this.items.set(e,t);return}let r=this.items.get(s[0]);(r===void 0||typeof r!="object")&&(r={},this.items.set(s[0],r));let n=r;for(let o=1;o<s.length-1;o++)(n[s[o]]===void 0||typeof n[s[o]]!="object")&&(n[s[o]]={}),n=n[s[o]];n[s[s.length-1]]=t}has(e){return this.get(e)!==void 0}all(){let e={};for(let[t,s]of this.items)e[t]=s;return e}},dn=b("svelar.config",()=>new Gs)});import{z as S}from"zod";function mn(c,e){let t=c.safeParse(e);if(t.success)return{success:!0,data:t.data};let s={};for(let r of t.error.issues){let n=r.path.length>0?r.path:["_root"],o=s;for(let a=0;a<n.length-1;a++){let l=n[a];l in o||(o[l]={}),o=o[l]}let i=n[n.length-1];o[i]||(o[i]=[]),o[i].push(r.message)}return{success:!1,errors:s}}var pn,gn=y(()=>{"use strict";pn={required:()=>S.string().min(1,"This field is required"),email:()=>S.string().email("Must be a valid email address"),string:(c,e)=>{let t=S.string();return c!==void 0&&(t=t.min(c)),e!==void 0&&(t=t.max(e)),t},number:(c,e)=>{let t=S.number();return c!==void 0&&(t=t.min(c)),e!==void 0&&(t=t.max(e)),t},integer:()=>S.number().int(),boolean:()=>S.boolean(),date:()=>S.coerce.date(),url:()=>S.string().url(),uuid:()=>S.string().uuid(),enum:c=>S.enum(c),array:c=>S.array(c),nullable:c=>c.nullable(),optional:c=>c.optional(),confirmed:(c="password")=>S.object({[c]:S.string(),[`${c}_confirmation`]:S.string()}).refine(e=>e[c]===e[`${c}_confirmation`],{message:"Confirmation does not match",path:[`${c}_confirmation`]}),min:c=>S.number().min(c),max:c=>S.number().max(c),between:(c,e)=>S.number().min(c).max(e),regex:(c,e)=>S.string().regex(c,e),ip:()=>S.string().refine(c=>{let e=c.split(".");return e.length!==4?!1:e.every(t=>{let s=Number(t);return Number.isInteger(s)&&s>=0&&s<=255})},{message:"Must be a valid IP address"}),json:()=>S.string().refine(c=>{try{return JSON.parse(c),!0}catch{return!1}},{message:"Must be valid JSON"})}});var fn={};P(fn,{FormAuthorizationError:()=>V,FormRequest:()=>fe,FormValidationError:()=>J});var fe,J,V,dt=y(()=>{"use strict";fe=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new J(e)}failedAuthorization(){throw new V}async parseBody(e){let t=e.request.headers.get("content-type")??"";if(t.includes("application/json"))return e.request.json();if(t.includes("multipart/form-data")||t.includes("application/x-www-form-urlencoded")){let s=await e.request.formData();return Object.fromEntries(s)}return Object.fromEntries(e.url.searchParams)}static async validate(e){let t=new this;await t.authorize(e)||t.failedAuthorization();let r=await t.parseBody(e),n={...Object.fromEntries(e.url.searchParams),...e.params,...r},i=t.rules().safeParse(n);if(!i.success){let a={},l=t.messages(),u=t.attributes();for(let d of i.error.issues){let h=d.path.join("."),m=u[h]??h;a[m]||(a[m]=[]);let f=`${h}.${d.code}`,E=l[f]??l[h];a[m].push(E??d.message)}t.failedValidation(a)}return t.passedValidation(i.data)}},J=class extends Error{constructor(t){super("The given data was invalid.");this.errors=t;this.name="FormValidationError"}statusCode=422;toResponse(){return new Response(JSON.stringify({message:this.message,errors:this.errors}),{status:422,headers:{"Content-Type":"application/json"}})}},V=class extends Error{statusCode=403;constructor(e="This action is unauthorized."){super(e),this.name="FormAuthorizationError"}toResponse(){return new Response(JSON.stringify({message:this.message}),{status:403,headers:{"Content-Type":"application/json"}})}}});import{readFile as yn,writeFile as Go,unlink as Qo,mkdir as Ie,readdir as Qs,stat as bn,copyFile as Xo,rename as Zo}from"fs/promises";import{existsSync as ea}from"fs";import{join as ta,dirname as ht}from"path";var Xs,pt,Zs,wn,vn=y(()=>{"use strict";C();Xs=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return ta(this.config.root,e)}async get(e){return yn(this.resolve(e))}async getText(e){return yn(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await Ie(ht(s),{recursive:!0}),await Go(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await Ie(ht(r),{recursive:!0}),await s(r,t)}async exists(e){return ea(this.resolve(e))}async delete(e){try{return await Qo(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await Ie(ht(s),{recursive:!0}),await Xo(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await Ie(ht(s),{recursive:!0}),await Zo(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await Qs(t,{withFileTypes:!0})).filter(r=>r.isFile()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async allFiles(e=""){let t=[],s=this.resolve(e);try{let r=await Qs(s,{withFileTypes:!0});for(let n of r){let o=e?`${e}/${n.name}`:n.name;n.isFile()?t.push(o):n.isDirectory()&&t.push(...await this.allFiles(o))}}catch{}return t}async directories(e=""){let t=this.resolve(e);try{return(await Qs(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await Ie(this.resolve(e),{recursive:!0})}async deleteDirectory(e){let{rm:t}=await import("fs/promises");await t(this.resolve(e),{recursive:!0,force:!0})}async size(e){return(await bn(this.resolve(e))).size}async lastModified(e){return(await bn(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},pt=class{config;_client=null;_s3Module=null;constructor(e){if(!e.bucket)throw new Error('S3 disk requires a "bucket" name.');this.config=e}async getS3(){if(this._s3Module)return this._s3Module;try{return this._s3Module=await Function('return import("@aws-sdk/client-s3")')(),this._s3Module}catch{throw new Error("S3 storage driver requires @aws-sdk/client-s3. Install it with: npm install @aws-sdk/client-s3")}}async getClient(){if(this._client)return this._client;let e=await this.getS3();return this._client=new e.S3Client({region:this.config.region??"us-east-1",endpoint:this.config.endpoint,forcePathStyle:this.config.forcePathStyle??!0,credentials:{accessKeyId:this.config.accessKeyId??"",secretAccessKey:this.config.secretAccessKey??""}}),this._client}key(e){let t=this.config.prefix;return t?`${t}/${e}`:e}async get(e){let t=await this.getS3(),n=await(await(await this.getClient()).send(new t.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).Body.transformToByteArray();return Buffer.from(n)}async getText(e){return(await this.get(e)).toString("utf-8")}async put(e,t){let s=await this.getS3(),r=await this.getClient(),n=typeof t=="string"?Buffer.from(t,"utf-8"):t;await r.send(new s.PutObjectCommand({Bucket:this.config.bucket,Key:this.key(e),Body:n}))}async append(e,t){let s=null;try{s=await this.get(e)}catch{}let r=typeof t=="string"?Buffer.from(t,"utf-8"):t,n=s?Buffer.concat([s,r]):r;await this.put(e,n)}async exists(e){let t=await this.getS3(),s=await this.getClient();try{return await s.send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)})),!0}catch{return!1}}async delete(e){let t=await this.getS3(),s=await this.getClient();try{return await s.send(new t.DeleteObjectCommand({Bucket:this.config.bucket,Key:this.key(e)})),!0}catch{return!1}}async copy(e,t){let s=await this.getS3();await(await this.getClient()).send(new s.CopyObjectCommand({Bucket:this.config.bucket,CopySource:`${this.config.bucket}/${this.key(e)}`,Key:this.key(t)}))}async move(e,t){await this.copy(e,t),await this.delete(e)}async files(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:"");try{return((await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,Delimiter:"/"}))).Contents??[]).map(o=>o.Key).filter(o=>o!==r).map(o=>{let i=this.config.prefix;return i?o.slice(i.length+1):o})}catch{return[]}}async allFiles(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:""),n=[],o;do{let i=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:o}));for(let a of i.Contents??[]){let l=this.config.prefix,u=l?a.Key.slice(l.length+1):a.Key;u&&n.push(u)}o=i.IsTruncated?i.NextContinuationToken:void 0}while(o);return n}async directories(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:"");try{return((await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,Delimiter:"/"}))).CommonPrefixes??[]).map(o=>{let i=this.config.prefix;return(i?o.Prefix.slice(i.length+1):o.Prefix).replace(/\/$/,"")}).filter(o=>o.length>0)}catch{return[]}}async makeDirectory(e){}async deleteDirectory(e){let t=await this.allFiles(e);for(let s of t)await this.delete(s)}async size(e){let t=await this.getS3();return(await(await this.getClient()).send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).ContentLength??0}async lastModified(e){let t=await this.getS3();return(await(await this.getClient()).send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).LastModified??new Date}url(e){let t=this.config.urlPrefix;if(t)return`${t}/${e}`;let s=this.config.endpoint??`https://s3.${this.config.region??"us-east-1"}.amazonaws.com`;return this.config.forcePathStyle!==!1?`${s}/${this.config.bucket}/${this.key(e)}`:`${s.replace("://",`://${this.config.bucket}.`)}/${this.key(e)}`}async temporaryUrl(e,t=3600){try{let s=await Function('return import("@aws-sdk/s3-request-presigner")')(),r=await this.getS3(),n=await this.getClient(),o=new r.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)});return await s.getSignedUrl(n,o,{expiresIn:t})}catch{throw new Error("Pre-signed URLs require @aws-sdk/s3-request-presigner. Install it with: npm install @aws-sdk/s3-request-presigner")}}async ensureBucket(){let e=await this.getS3(),t=await this.getClient();try{await t.send(new e.HeadBucketCommand({Bucket:this.config.bucket}))}catch{await t.send(new e.CreateBucketCommand({Bucket:this.config.bucket}))}}},Zs=class{config=null;disks=new Map;configure(e){this.config=e}disk(e){let t=e??this.config?.default??"local";if(this.disks.has(t))return this.disks.get(t);if(!this.config)throw new Error("Storage not configured. Call Storage.configure() first.");let s=this.config.disks[t];if(!s)throw new Error(`Storage disk "${t}" is not defined.`);let r=this.createDisk(s);return this.disks.set(t,r),r}async get(e){return this.disk().get(e)}async getText(e){return this.disk().getText(e)}async put(e,t){return this.disk().put(e,t)}async append(e,t){return this.disk().append(e,t)}async exists(e){return this.disk().exists(e)}async delete(e){return this.disk().delete(e)}async copy(e,t){return this.disk().copy(e,t)}async move(e,t){return this.disk().move(e,t)}async files(e){return this.disk().files(e)}async allFiles(e){return this.disk().allFiles(e)}async directories(e){return this.disk().directories(e)}async makeDirectory(e){return this.disk().makeDirectory(e)}async deleteDirectory(e){return this.disk().deleteDirectory(e)}async size(e){return this.disk().size(e)}async lastModified(e){return this.disk().lastModified(e)}url(e){return this.disk().url(e)}createDisk(e){switch(e.driver){case"local":return new Xs(e);case"s3":return new pt(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof pt))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},wn=b("svelar.storage",()=>new Zs)});import{readFile as sa,writeFile as ra,unlink as En,mkdir as Tn}from"fs/promises";import{join as na,dirname as ia}from"path";import{createHash as oa}from"crypto";var er,tr,sr,rr,Sn,Cn=y(()=>{"use strict";C();er=class{store=new Map;async get(e){let t=this.store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.store.delete(e),null):t.value:null}async put(e,t,s){this.store.set(e,{value:t,expiresAt:s?Date.now()+s*1e3:null})}async forget(e){return this.store.delete(e)}async flush(){this.store.clear()}async has(e){let t=this.store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.store.delete(e),!1):!0:!1}async increment(e,t=1){let r=(await this.get(e)??0)+t,n=this.store.get(e);return await this.put(e,r,n?.expiresAt?Math.ceil((n.expiresAt-Date.now())/1e3):void 0),r}async decrement(e,t=1){return this.increment(e,-t)}},tr=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=oa("md5").update(e).digest("hex");return na(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await sa(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await En(t).catch(()=>{}),null):r.value}catch{return null}}async put(e,t,s){let r=this.filePath(e),n={value:t,expiresAt:s?Date.now()+s*1e3:null};await Tn(ia(r),{recursive:!0}),await ra(r,JSON.stringify(n))}async forget(e){try{return await En(this.filePath(e)),!0}catch{return!1}}async flush(){let{rm:e}=await import("fs/promises");await e(this.basePath,{recursive:!0,force:!0}),await Tn(this.basePath,{recursive:!0})}async has(e){return await this.get(e)!==null}async increment(e,t=1){let r=(await this.get(e)??0)+t;return await this.put(e,r),r}async decrement(e,t=1){return this.increment(e,-t)}},sr=class{async get(){return null}async put(){}async forget(){return!0}async flush(){}async has(){return!1}async increment(){return 0}async decrement(){return 0}},rr=class{config={default:"memory",stores:{memory:{driver:"memory"}}};stores=new Map;configure(e){this.config=e,this.stores.clear()}store(e){let t=e??this.config.default;if(this.stores.has(t))return this.stores.get(t);let s=this.config.stores[t];if(!s)throw new Error(`Cache store "${t}" is not defined.`);let r=this.createStore(s);return this.stores.set(t,r),r}async get(e,t){let s=this.store();return await s.has(e)?s.get(e):t??null}async put(e,t,s){return this.store().put(e,t,s??this.config.stores[this.config.default]?.ttl)}async forget(e){return this.store().forget(e)}async flush(){return this.store().flush()}async has(e){return this.store().has(e)}async increment(e,t){return this.store().increment(e,t)}async decrement(e,t){return this.store().decrement(e,t)}async remember(e,t,s){let r=await this.store().get(e);if(r!==null)return r;let n=await s();return await this.store().put(e,n,t),n}async rememberForever(e,t){let s=await this.store().get(e);if(s!==null)return s;let r=await t();return await this.store().put(e,r),r}async pull(e,t){let s=await this.get(e,t);return await this.forget(e),s}createStore(e){switch(e.driver){case"memory":return new er;case"file":return new tr(e);case"null":return new sr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},Sn=b("svelar.cache",()=>new rr)});var mt,nr,ir,or,xn,Pn=y(()=>{"use strict";C();mt=class{},nr=class{async send(e,t){if(!t.toMail)return;let s=t.toMail(e),r=e.routeNotificationForMail?.()??e.getAttribute("email");if(!r){console.warn("[Notifications] No email address for notifiable.");return}try{let{Mailer:n}=await Promise.resolve().then(()=>(st(),_s));await n.send({to:r,subject:s.subject,html:s.html,text:s.text,from:s.from})}catch(n){console.error("[Notifications] Failed to send mail notification:",n)}}},ir=class{table;constructor(e="notifications"){this.table=e}async send(e,t){if(!t.toDatabase)return;let s=t.toDatabase(e);try{let{Connection:r}=await Promise.resolve().then(()=>(w(),v));await r.raw(`INSERT INTO ${this.table} (id, notifiable_id, type, data, read_at, created_at)
140
- VALUES (?, ?, ?, ?, NULL, ?)`,[crypto.randomUUID(),e.getAttribute("id"),s.type,JSON.stringify(s.data),new Date().toISOString()])}catch(r){console.error("[Notifications] Failed to store database notification:",r)}}},or=class{channels=new Map;constructor(){this.channels.set("mail",new nr),this.channels.set("database",new ir)}extend(e,t){this.channels.set(e,t)}async send(e,t){let s=Array.isArray(e)?e:[e];for(let r of s){let n=t.via(r);for(let o of n){let i=this.channels.get(o);if(i)try{await i.send(r,t)}catch(a){console.error(`[Notifications] Channel "${o}" failed:`,a)}else console.warn(`[Notifications] Unknown channel: ${o}`)}}}async sendVia(e,t,s){for(let r of s){let n=this.channels.get(r);n&&await n.send(e,t)}}},xn=b("svelar.notifier",()=>new or)});function ar(c){return c.startsWith("private-")?"private":c.startsWith("presence-")?"presence":"public"}var cr,gt,lr,ur,Rn,$n=y(()=>{"use strict";C();cr=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=ar(e)}stream(e,t){let s=this,r=new ReadableStream({start(n){let o={channel:s.name};s.type==="presence"&&(o.members=s.getMembers());let i=`event: connected
139
+ `).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function ln(c={}){let{auth:e,secret:t=(()=>{throw new Error("APP_KEY is not set. Pass `secret` to createSvelarApp() \u2014 e.g. secret: env.APP_KEY (from $env/dynamic/private).")})(),sessionStore:s,sessionLifetime:r=86400,rateLimit:i=100,rateLimitWindow:o=6e4,csrfPaths:n=["/api/"],csrfExcludePaths:a=["/api/webhooks"],authThrottleAttempts:l=5,authThrottleDecay:u=1,debug:d=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:m={},i18n:f,errorConfig:E={}}=c,T=[new ae,new ie({maxRequests:i,windowMs:o}),new oe({onlyPaths:n,excludePaths:a}),new he({store:s??new z,secret:t,lifetime:r})];e&&T.push(new ge(e)),T.push(...h);let M={"auth-throttle":new ce({maxAttempts:l,decayMinutes:u}),...m},O=new fe({debug:d,...E}),V=Ys({middleware:T,namedMiddleware:M,onError:(wt,Et)=>O.handle(wt,Et)}),L;if(f){let{paraglideMiddleware:wt,getTextDirection:Et=()=>"ltr"}=f;L=Vs(async({event:Tt,resolve:Wn})=>wt(Tt.request,({request:zn,locale:Cr})=>(Tt.request=zn,Wn(Tt,{transformPageChunk:({html:Jn})=>Jn.replace("%lang%",Cr).replace("%dir%",Et(Cr))}))),V)}else L=V;return{handle:L,handleError:O.handleSvelteKitError()}}function Ys(c={}){let e=new H;if(c.middleware)for(let t of c.middleware)e.use(t);if(c.namedMiddleware)for(let[t,s]of Object.entries(c.namedMiddleware))e.register(t,s);return async function({event:s,resolve:r}){let i={event:s,params:s.params??{},locals:s.locals??{}};try{c.app&&!c.app.isBooted()&&await c.app.bootstrap();let o=await e.execute(i,async()=>r(s));return o instanceof Response?o:r(s)}catch(o){if(c.onError){let n=await c.onError(o,s);if(n instanceof Response)return n}return console.error("[Svelar] Unhandled error in hooks:",o),new Response(JSON.stringify({message:process.env.NODE_ENV==="production"?"Internal server error":o.message}),{status:500,headers:{"Content-Type":"application/json"}})}}}function Vs(...c){return async function({event:t,resolve:s}){let r=s;for(let i=c.length-1;i>=0;i--){let o=c[i],n=r;r=a=>o({event:a,resolve:n})}return r(t)}}var Gs=y(()=>{"use strict";le();Ss();js();Js()});function un(c,e){let t=process.env[c];return t===void 0?e!==void 0?e:"":t==="true"?!0:t==="false"?!1:t==="null"?null:/^\d+$/.test(t)?Number(t):t}var Qs,dn,hn=y(()=>{"use strict";C();Qs=class{items=new Map;clear(){this.items.clear()}load(e){for(let[t,s]of Object.entries(e))this.set(t,s)}async loadFromDirectory(e){let{resolve:t,basename:s,extname:r}=await import("path"),{existsSync:i,readdirSync:o}=await import("fs"),{pathToFileURL:n}=await import("url"),a=t(e);if(!i(a))return[];let l=o(a).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith(".")),u=[];for(let d of l){let h=s(d,r(d)),m=t(a,d);try{let E=await import(n(m).href),T=E.default??E.config??E;T&&typeof T=="object"&&!Array.isArray(T)&&(this.set(h,T),u.push(h))}catch{}}return u}get(e,t){let s=e.split("."),r=this.items.get(s[0]);for(let i=1;i<s.length;i++){if(r==null)return t;r=r[s[i]]}return r??t}set(e,t){let s=e.split(".");if(s.length===1){this.items.set(e,t);return}let r=this.items.get(s[0]);(r===void 0||typeof r!="object")&&(r={},this.items.set(s[0],r));let i=r;for(let o=1;o<s.length-1;o++)(i[s[o]]===void 0||typeof i[s[o]]!="object")&&(i[s[o]]={}),i=i[s[o]];i[s[s.length-1]]=t}has(e){return this.get(e)!==void 0}all(){let e={};for(let[t,s]of this.items)e[t]=s;return e}},dn=b("svelar.config",()=>new Qs)});import{z as S}from"zod";function mn(c,e){let t=c.safeParse(e);if(t.success)return{success:!0,data:t.data};let s={};for(let r of t.error.issues){let i=r.path.length>0?r.path:["_root"],o=s;for(let a=0;a<i.length-1;a++){let l=i[a];l in o||(o[l]={}),o=o[l]}let n=i[i.length-1];o[n]||(o[n]=[]),o[n].push(r.message)}return{success:!1,errors:s}}var pn,gn=y(()=>{"use strict";pn={required:()=>S.string().min(1,"This field is required"),email:()=>S.string().email("Must be a valid email address"),string:(c,e)=>{let t=S.string();return c!==void 0&&(t=t.min(c)),e!==void 0&&(t=t.max(e)),t},number:(c,e)=>{let t=S.number();return c!==void 0&&(t=t.min(c)),e!==void 0&&(t=t.max(e)),t},integer:()=>S.number().int(),boolean:()=>S.boolean(),date:()=>S.coerce.date(),url:()=>S.string().url(),uuid:()=>S.string().uuid(),enum:c=>S.enum(c),array:c=>S.array(c),nullable:c=>c.nullable(),optional:c=>c.optional(),confirmed:(c="password")=>S.object({[c]:S.string(),[`${c}_confirmation`]:S.string()}).refine(e=>e[c]===e[`${c}_confirmation`],{message:"Confirmation does not match",path:[`${c}_confirmation`]}),min:c=>S.number().min(c),max:c=>S.number().max(c),between:(c,e)=>S.number().min(c).max(e),regex:(c,e)=>S.string().regex(c,e),ip:()=>S.string().refine(c=>{let e=c.split(".");return e.length!==4?!1:e.every(t=>{let s=Number(t);return Number.isInteger(s)&&s>=0&&s<=255})},{message:"Must be a valid IP address"}),json:()=>S.string().refine(c=>{try{return JSON.parse(c),!0}catch{return!1}},{message:"Must be valid JSON"})}});var fn={};P(fn,{FormAuthorizationError:()=>Y,FormRequest:()=>ye,FormValidationError:()=>J});var ye,J,Y,ht=y(()=>{"use strict";ye=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new J(e)}failedAuthorization(){throw new Y}async parseBody(e){let t=e.request.headers.get("content-type")??"";if(t.includes("application/json"))return e.request.json();if(t.includes("multipart/form-data")||t.includes("application/x-www-form-urlencoded")){let s=await e.request.formData();return Object.fromEntries(s)}return Object.fromEntries(e.url.searchParams)}static async validate(e){let t=new this;await t.authorize(e)||t.failedAuthorization();let r=await t.parseBody(e),i={...Object.fromEntries(e.url.searchParams),...e.params,...r},n=t.rules().safeParse(i);if(!n.success){let a={},l=t.messages(),u=t.attributes();for(let d of n.error.issues){let h=d.path.join("."),m=u[h]??h;a[m]||(a[m]=[]);let f=`${h}.${d.code}`,E=l[f]??l[h];a[m].push(E??d.message)}t.failedValidation(a)}return t.passedValidation(n.data)}},J=class extends Error{constructor(t){super("The given data was invalid.");this.errors=t;this.name="FormValidationError"}statusCode=422;toResponse(){return new Response(JSON.stringify({message:this.message,errors:this.errors}),{status:422,headers:{"Content-Type":"application/json"}})}},Y=class extends Error{statusCode=403;constructor(e="This action is unauthorized."){super(e),this.name="FormAuthorizationError"}toResponse(){return new Response(JSON.stringify({message:this.message}),{status:403,headers:{"Content-Type":"application/json"}})}}});import{readFile as yn,writeFile as Go,unlink as Qo,mkdir as Ie,readdir as Xs,stat as bn,copyFile as Xo,rename as Zo}from"fs/promises";import{existsSync as ea}from"fs";import{join as ta,dirname as pt}from"path";var Zs,mt,er,vn,wn=y(()=>{"use strict";C();Zs=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return ta(this.config.root,e)}async get(e){return yn(this.resolve(e))}async getText(e){return yn(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await Ie(pt(s),{recursive:!0}),await Go(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await Ie(pt(r),{recursive:!0}),await s(r,t)}async exists(e){return ea(this.resolve(e))}async delete(e){try{return await Qo(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await Ie(pt(s),{recursive:!0}),await Xo(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await Ie(pt(s),{recursive:!0}),await Zo(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await Xs(t,{withFileTypes:!0})).filter(r=>r.isFile()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async allFiles(e=""){let t=[],s=this.resolve(e);try{let r=await Xs(s,{withFileTypes:!0});for(let i of r){let o=e?`${e}/${i.name}`:i.name;i.isFile()?t.push(o):i.isDirectory()&&t.push(...await this.allFiles(o))}}catch{}return t}async directories(e=""){let t=this.resolve(e);try{return(await Xs(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await Ie(this.resolve(e),{recursive:!0})}async deleteDirectory(e){let{rm:t}=await import("fs/promises");await t(this.resolve(e),{recursive:!0,force:!0})}async size(e){return(await bn(this.resolve(e))).size}async lastModified(e){return(await bn(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},mt=class{config;_client=null;_s3Module=null;constructor(e){if(!e.bucket)throw new Error('S3 disk requires a "bucket" name.');this.config=e}async getS3(){if(this._s3Module)return this._s3Module;try{return this._s3Module=await Function('return import("@aws-sdk/client-s3")')(),this._s3Module}catch{throw new Error("S3 storage driver requires @aws-sdk/client-s3. Install it with: npm install @aws-sdk/client-s3")}}async getClient(){if(this._client)return this._client;let e=await this.getS3();return this._client=new e.S3Client({region:this.config.region??"us-east-1",endpoint:this.config.endpoint,forcePathStyle:this.config.forcePathStyle??!0,credentials:{accessKeyId:this.config.accessKeyId??"",secretAccessKey:this.config.secretAccessKey??""}}),this._client}key(e){let t=this.config.prefix;return t?`${t}/${e}`:e}async get(e){let t=await this.getS3(),i=await(await(await this.getClient()).send(new t.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).Body.transformToByteArray();return Buffer.from(i)}async getText(e){return(await this.get(e)).toString("utf-8")}async put(e,t){let s=await this.getS3(),r=await this.getClient(),i=typeof t=="string"?Buffer.from(t,"utf-8"):t;await r.send(new s.PutObjectCommand({Bucket:this.config.bucket,Key:this.key(e),Body:i}))}async append(e,t){let s=null;try{s=await this.get(e)}catch{}let r=typeof t=="string"?Buffer.from(t,"utf-8"):t,i=s?Buffer.concat([s,r]):r;await this.put(e,i)}async exists(e){let t=await this.getS3(),s=await this.getClient();try{return await s.send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)})),!0}catch{return!1}}async delete(e){let t=await this.getS3(),s=await this.getClient();try{return await s.send(new t.DeleteObjectCommand({Bucket:this.config.bucket,Key:this.key(e)})),!0}catch{return!1}}async copy(e,t){let s=await this.getS3();await(await this.getClient()).send(new s.CopyObjectCommand({Bucket:this.config.bucket,CopySource:`${this.config.bucket}/${this.key(e)}`,Key:this.key(t)}))}async move(e,t){await this.copy(e,t),await this.delete(e)}async files(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:"");try{return((await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,Delimiter:"/"}))).Contents??[]).map(o=>o.Key).filter(o=>o!==r).map(o=>{let n=this.config.prefix;return n?o.slice(n.length+1):o})}catch{return[]}}async allFiles(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:""),i=[],o;do{let n=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:o}));for(let a of n.Contents??[]){let l=this.config.prefix,u=l?a.Key.slice(l.length+1):a.Key;u&&i.push(u)}o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return i}async directories(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:"");try{return((await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,Delimiter:"/"}))).CommonPrefixes??[]).map(o=>{let n=this.config.prefix;return(n?o.Prefix.slice(n.length+1):o.Prefix).replace(/\/$/,"")}).filter(o=>o.length>0)}catch{return[]}}async makeDirectory(e){}async deleteDirectory(e){let t=await this.allFiles(e);for(let s of t)await this.delete(s)}async size(e){let t=await this.getS3();return(await(await this.getClient()).send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).ContentLength??0}async lastModified(e){let t=await this.getS3();return(await(await this.getClient()).send(new t.HeadObjectCommand({Bucket:this.config.bucket,Key:this.key(e)}))).LastModified??new Date}url(e){let t=this.config.urlPrefix;if(t)return`${t}/${e}`;let s=this.config.endpoint??`https://s3.${this.config.region??"us-east-1"}.amazonaws.com`;return this.config.forcePathStyle!==!1?`${s}/${this.config.bucket}/${this.key(e)}`:`${s.replace("://",`://${this.config.bucket}.`)}/${this.key(e)}`}async temporaryUrl(e,t=3600){try{let s=await Function('return import("@aws-sdk/s3-request-presigner")')(),r=await this.getS3(),i=await this.getClient(),o=new r.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)});return await s.getSignedUrl(i,o,{expiresIn:t})}catch{throw new Error("Pre-signed URLs require @aws-sdk/s3-request-presigner. Install it with: npm install @aws-sdk/s3-request-presigner")}}async ensureBucket(){let e=await this.getS3(),t=await this.getClient();try{await t.send(new e.HeadBucketCommand({Bucket:this.config.bucket}))}catch{await t.send(new e.CreateBucketCommand({Bucket:this.config.bucket}))}}},er=class{config=null;disks=new Map;configure(e){this.config=e}disk(e){let t=e??this.config?.default??"local";if(this.disks.has(t))return this.disks.get(t);if(!this.config)throw new Error("Storage not configured. Call Storage.configure() first.");let s=this.config.disks[t];if(!s)throw new Error(`Storage disk "${t}" is not defined.`);let r=this.createDisk(s);return this.disks.set(t,r),r}async get(e){return this.disk().get(e)}async getText(e){return this.disk().getText(e)}async put(e,t){return this.disk().put(e,t)}async append(e,t){return this.disk().append(e,t)}async exists(e){return this.disk().exists(e)}async delete(e){return this.disk().delete(e)}async copy(e,t){return this.disk().copy(e,t)}async move(e,t){return this.disk().move(e,t)}async files(e){return this.disk().files(e)}async allFiles(e){return this.disk().allFiles(e)}async directories(e){return this.disk().directories(e)}async makeDirectory(e){return this.disk().makeDirectory(e)}async deleteDirectory(e){return this.disk().deleteDirectory(e)}async size(e){return this.disk().size(e)}async lastModified(e){return this.disk().lastModified(e)}url(e){return this.disk().url(e)}createDisk(e){switch(e.driver){case"local":return new Zs(e);case"s3":return new mt(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof mt))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},vn=b("svelar.storage",()=>new er)});import{readFile as sa,writeFile as ra,unlink as En,mkdir as Tn}from"fs/promises";import{join as na,dirname as ia}from"path";import{createHash as oa}from"crypto";var tr,sr,rr,nr,Sn,Cn=y(()=>{"use strict";C();tr=class{store=new Map;async get(e){let t=this.store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.store.delete(e),null):t.value:null}async put(e,t,s){this.store.set(e,{value:t,expiresAt:s?Date.now()+s*1e3:null})}async forget(e){return this.store.delete(e)}async flush(){this.store.clear()}async has(e){let t=this.store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.store.delete(e),!1):!0:!1}async increment(e,t=1){let r=(await this.get(e)??0)+t,i=this.store.get(e);return await this.put(e,r,i?.expiresAt?Math.ceil((i.expiresAt-Date.now())/1e3):void 0),r}async decrement(e,t=1){return this.increment(e,-t)}},sr=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=oa("md5").update(e).digest("hex");return na(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await sa(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await En(t).catch(()=>{}),null):r.value}catch{return null}}async put(e,t,s){let r=this.filePath(e),i={value:t,expiresAt:s?Date.now()+s*1e3:null};await Tn(ia(r),{recursive:!0}),await ra(r,JSON.stringify(i))}async forget(e){try{return await En(this.filePath(e)),!0}catch{return!1}}async flush(){let{rm:e}=await import("fs/promises");await e(this.basePath,{recursive:!0,force:!0}),await Tn(this.basePath,{recursive:!0})}async has(e){return await this.get(e)!==null}async increment(e,t=1){let r=(await this.get(e)??0)+t;return await this.put(e,r),r}async decrement(e,t=1){return this.increment(e,-t)}},rr=class{async get(){return null}async put(){}async forget(){return!0}async flush(){}async has(){return!1}async increment(){return 0}async decrement(){return 0}},nr=class{config={default:"memory",stores:{memory:{driver:"memory"}}};stores=new Map;configure(e){this.config=e,this.stores.clear()}store(e){let t=e??this.config.default;if(this.stores.has(t))return this.stores.get(t);let s=this.config.stores[t];if(!s)throw new Error(`Cache store "${t}" is not defined.`);let r=this.createStore(s);return this.stores.set(t,r),r}async get(e,t){let s=this.store();return await s.has(e)?s.get(e):t??null}async put(e,t,s){return this.store().put(e,t,s??this.config.stores[this.config.default]?.ttl)}async forget(e){return this.store().forget(e)}async flush(){return this.store().flush()}async has(e){return this.store().has(e)}async increment(e,t){return this.store().increment(e,t)}async decrement(e,t){return this.store().decrement(e,t)}async remember(e,t,s){let r=await this.store().get(e);if(r!==null)return r;let i=await s();return await this.store().put(e,i,t),i}async rememberForever(e,t){let s=await this.store().get(e);if(s!==null)return s;let r=await t();return await this.store().put(e,r),r}async pull(e,t){let s=await this.get(e,t);return await this.forget(e),s}createStore(e){switch(e.driver){case"memory":return new tr;case"file":return new sr(e);case"null":return new rr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},Sn=b("svelar.cache",()=>new nr)});var gt,ir,or,ar,xn,Rn=y(()=>{"use strict";C();gt=class{},ir=class{async send(e,t){if(!t.toMail)return;let s=t.toMail(e),r=e.routeNotificationForMail?.()??e.getAttribute("email");if(!r){console.warn("[Notifications] No email address for notifiable.");return}try{let{Mailer:i}=await Promise.resolve().then(()=>(rt(),Ms));await i.send({to:r,subject:s.subject,html:s.html,text:s.text,from:s.from})}catch(i){console.error("[Notifications] Failed to send mail notification:",i)}}},or=class{table;constructor(e="notifications"){this.table=e}async send(e,t){if(!t.toDatabase)return;let s=t.toDatabase(e);try{let{Connection:r}=await Promise.resolve().then(()=>(v(),w));await r.raw(`INSERT INTO ${this.table} (id, notifiable_id, type, data, read_at, created_at)
140
+ VALUES (?, ?, ?, ?, NULL, ?)`,[crypto.randomUUID(),e.getAttribute("id"),s.type,JSON.stringify(s.data),new Date().toISOString()])}catch(r){console.error("[Notifications] Failed to store database notification:",r)}}},ar=class{channels=new Map;constructor(){this.channels.set("mail",new ir),this.channels.set("database",new or)}extend(e,t){this.channels.set(e,t)}async send(e,t){let s=Array.isArray(e)?e:[e];for(let r of s){let i=t.via(r);for(let o of i){let n=this.channels.get(o);if(n)try{await n.send(r,t)}catch(a){console.error(`[Notifications] Channel "${o}" failed:`,a)}else console.warn(`[Notifications] Unknown channel: ${o}`)}}}async sendVia(e,t,s){for(let r of s){let i=this.channels.get(r);i&&await i.send(e,t)}}},xn=b("svelar.notifier",()=>new ar)});function cr(c){return c.startsWith("private-")?"private":c.startsWith("presence-")?"presence":"public"}var lr,ft,ur,dr,Pn,$n=y(()=>{"use strict";C();lr=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=cr(e)}stream(e,t){let s=this,r=new ReadableStream({start(i){let o={channel:s.name};s.type==="presence"&&(o.members=s.getMembers());let n=`event: connected
141
141
  data: ${JSON.stringify(o)}
142
142
  id: ${Date.now()}
143
143
 
144
- `;n.enqueue(new TextEncoder().encode(i));let a={controller:n,userId:e,userInfo:t};s.subscribers.push(a),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},a)},cancel(){let n=s.subscribers.findIndex(i=>i.controller===this._controller),o=s.subscribers.length;s.subscribers=s.subscribers.filter(i=>{try{return i.controller.enqueue(new TextEncoder().encode(`:
144
+ `;i.enqueue(new TextEncoder().encode(n));let a={controller:i,userId:e,userInfo:t};s.subscribers.push(a),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},a)},cancel(){let i=s.subscribers.findIndex(n=>n.controller===this._controller),o=s.subscribers.length;s.subscribers=s.subscribers.filter(n=>{try{return n.controller.enqueue(new TextEncoder().encode(`:
145
145
 
146
146
  `)),!0}catch{return!1}}),s.type==="presence"&&e!==void 0&&s.subscribers.length<o&&s.sendInternal("member:left",{id:e,...t})}});return new Response(r,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"}})}send(e,t,s){let r=`event: ${e}
147
147
  data: ${JSON.stringify(t)}
148
148
  id: ${Date.now()}
149
149
 
150
- `,n=new TextEncoder().encode(r);for(let o of this.subscribers)if(!(s!==void 0&&o.userId!==s))try{o.controller.enqueue(n)}catch{}}sendInternal(e,t,s){let r=`event: ${e}
150
+ `,i=new TextEncoder().encode(r);for(let o of this.subscribers)if(!(s!==void 0&&o.userId!==s))try{o.controller.enqueue(i)}catch{}}sendInternal(e,t,s){let r=`event: ${e}
151
151
  data: ${JSON.stringify(t)}
152
152
  id: ${Date.now()}
153
153
 
154
- `,n=new TextEncoder().encode(r);for(let o of this.subscribers)if(o!==s)try{o.controller.enqueue(n)}catch{}}toUser(e){return{send:(t,s)=>this.send(t,s,e)}}subscriberCount(){return this.subscribers.length}getMembers(){return this.type!=="presence"?[]:this.subscribers.filter(e=>e.userId!==void 0).map(e=>({id:e.userId,...e.userInfo??{}}))}hasMember(e){return this.subscribers.some(t=>t.userId===e)}whisper(e,t,s){let r=`event: client-${e}
154
+ `,i=new TextEncoder().encode(r);for(let o of this.subscribers)if(o!==s)try{o.controller.enqueue(i)}catch{}}toUser(e){return{send:(t,s)=>this.send(t,s,e)}}subscriberCount(){return this.subscribers.length}getMembers(){return this.type!=="presence"?[]:this.subscribers.filter(e=>e.userId!==void 0).map(e=>({id:e.userId,...e.userInfo??{}}))}hasMember(e){return this.subscribers.some(t=>t.userId===e)}whisper(e,t,s){let r=`event: client-${e}
155
155
  data: ${JSON.stringify(t)}
156
156
  id: ${Date.now()}
157
157
 
158
- `,n=new TextEncoder().encode(r);for(let o of this.subscribers)if(o.userId!==s)try{o.controller.enqueue(n)}catch{}}},gt=class{config;constructor(e){this.config=e}async send(e,t,s){let r=Array.isArray(e)?e:[e],n=JSON.stringify({name:t,channels:r,data:JSON.stringify(s)}),o=Math.floor(Date.now()/1e3).toString(),i=await this.md5(n),a=["POST",`/apps/${this.config.appId}/events`,[`auth_key=${this.config.key}`,`auth_timestamp=${o}`,"auth_version=1.0",`body_md5=${i}`].join("&")].join(`
159
- `),l=await this.hmacSha256(this.config.secret,a),u=this.config.useTLS!==!1?"https":"http",d=this.config.host??`api-${this.config.cluster??"mt1"}.pusher.com`,h=this.config.port??(this.config.useTLS!==!1?443:80),m=`${u}://${d}:${h}/apps/${this.config.appId}/events?auth_key=${this.config.key}&auth_timestamp=${o}&auth_version=1.0&body_md5=${i}&auth_signature=${l}`,f=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(!f.ok){let E=await f.text();throw new Error(`Pusher API error (${f.status}): ${E}`)}}async authenticate(e,t,s){let r=`${e}:${t}`,n;s&&(n=JSON.stringify(s),r+=`:${n}`);let o=await this.hmacSha256(this.config.secret,r),i=`${this.config.key}:${o}`;return n?{auth:i,channel_data:n}:{auth:i}}get key(){return this.config.key}clientConfig(){let e={key:this.config.key,cluster:this.config.cluster??"mt1"};return this.config.host&&(e.wsHost=this.config.host,e.wsPort=this.config.port??6001,e.wssPort=this.config.port??6001,e.forceTLS=this.config.useTLS??!1,e.enabledTransports=["ws","wss"],e.disableStats=!0),e}async md5(e){let{createHash:t}=await import("crypto");return t("md5").update(e).digest("hex")}async hmacSha256(e,t){let{createHmac:s}=await import("crypto");return s("sha256",e).update(t).digest("hex")}},lr=class{constructor(e,t,s){this.manager=e;this.eventName=t;this.eventData=s}channels=[];on(...e){return this.channels.push(...e),this}async send(){for(let e of this.channels)await this.manager.sendToChannel(e,this.eventName,this.eventData)}},ur=class{config={default:"sse",drivers:{sse:{driver:"sse"}}};sseChannels=new Map;channelAuth=new Map;pusherDriver=null;configure(e){this.config=e;let t=Object.values(e.drivers).find(s=>s.driver==="pusher");t&&t.driver==="pusher"&&(this.pusherDriver=new gt(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new cr(e)),this.sseChannels.get(e)}async authorize(e,t){if(ar(e)==="public")return!0;for(let[r,n]of this.channelAuth){let o=this.matchPattern(r,e);if(o!==null)return await n(t,o)}return!1}async authenticatePusher(e,t,s){if(!this.pusherDriver)throw new Error("Pusher driver is not configured. Call Broadcast.configure() first.");let r=ar(e);if(r==="public")return!1;let n=await this.authorize(e,s);if(n===!1)return!1;if(r==="presence"){let o=typeof n=="object"?{user_id:n.id??s.id,user_info:n}:{user_id:s.id,user_info:{id:s.id}};return this.pusherDriver.authenticate(t,e,o)}return this.pusherDriver.authenticate(t,e)}event(e,t){return new lr(this,e,t)}to(e,t){return{send:async(s,r)=>{await this.sendToChannel(e,s,r,t)}}}async sendToChannel(e,t,s,r){let n=this.config.drivers[this.config.default];switch(n?.driver){case"pusher":this.pusherDriver||(this.pusherDriver=new gt(n)),await this.pusherDriver.send(e,t,s);break;case"log":console.log(`[Broadcast] ${e} \u2192 ${t}:`,JSON.stringify(s));break;default:for(let[,o]of this.sseChannels)o.name===e&&o.send(t,s,r);break}}subscribe(e,t,s){return this.channel(e).stream(t,s)}members(e){let t=this.sseChannels.get(e);return t?t.getMembers():[]}pusher(){if(!this.pusherDriver)throw new Error("Pusher driver is not configured.");return this.pusherDriver}activeChannels(){return[...new Set([...this.sseChannels.values()].map(e=>e.name))]}totalSubscribers(){let e=0;for(let t of this.sseChannels.values())e+=t.subscriberCount();return e}prune(){for(let[e,t]of this.sseChannels)t.subscriberCount()===0&&this.sseChannels.delete(e)}matchPattern(e,t){let s=[],r=e.replace(/[.*+?^${}()|[\]\\]/g,a=>a==="{"||a==="}"?a:`\\${a}`).replace(/\\\{(\w+)\\\}/g,(a,l)=>(s.push(l),"([^.]+)")).replace(/\{(\w+)\}/g,(a,l)=>(s.push(l),"([^.]+)")),n=new RegExp(`^${r}$`),o=t.match(n);if(!o)return null;let i={};for(let a=0;a<s.length;a++)i[s[a]]=o[a+1];return i}},Rn=b("svelar.broadcast",()=>new ur)});function ft(c,e,t){Dn&&Dn(c,e,{description:t})}async function kn(c,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:n={},...o}=e,i=(o.method||"GET").toUpperCase(),a=new Headers(o.headers);if(["POST","PUT","PATCH","DELETE"].includes(i)){let l=hr(t);l&&a.set(s,l)}o.body&&typeof o.body=="string"&&!a.has("Content-Type")&&a.set("Content-Type","application/json"),a.has("Accept")||a.set("Accept","application/json");try{let l=await fetch(c,{...o,headers:a});return!l.ok&&r&&await ca(l,{...aa,...n}),l}catch(l){throw r&&ft("error","Network Error","Unable to connect. Check your internet connection."),l}}async function ca(c,e){let t="";try{if((c.headers.get("content-type")??"").includes("application/json")){let o=await c.clone().json();if(t=o.message??"",c.status===422&&o.errors){let i=Object.entries(o.errors).map(([a,l])=>`${a}: ${l.join(", ")}`).slice(0,3).join(`
160
- `);ft("warning",e[422]??"Validation Error",i);return}}}catch{}let s=t||e[c.status]||`Error ${c.status}`,r=c.status>=500?"error":c.status===429?"warning":"error";if(c.status===401){ft("warning",s,"Please sign in to continue.");return}ft(r,s)}function hr(c="XSRF-TOKEN"){if(typeof document>"u")return null;let e=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function On(c,e){if(!e)return c;let t=new URL(c,"http://localhost");for(let[s,r]of Object.entries(e))r!=null&&t.searchParams.set(s,String(r));return t.pathname+t.search}var aa,Dn,dr,ye,cd,An=y(()=>{"use strict";aa={400:"Invalid request. Please check your input.",401:"Your session has expired. Please sign in again.",403:"You don't have permission to do this.",404:"The requested resource was not found.",405:"This action is not allowed.",409:"A conflict occurred. Please refresh and try again.",419:"Page expired. Please refresh and try again.",422:"The submitted data is invalid.",429:"Too many requests. Please wait a moment.",500:"Something went wrong on our end.",502:"Service temporarily unavailable. Try again shortly.",503:"Service is under maintenance. Try again shortly.",504:"Request timed out. Please try again."},Dn=null;dr=class c{_baseUrl="";_headers={};_timeout=3e4;_retries=0;_retryDelay=1e3;_query={};constructor(e){e?.baseUrl&&(this._baseUrl=e.baseUrl),e?.headers&&(this._headers={...e.headers}),e?.timeout&&(this._timeout=e.timeout),e?.retries&&(this._retries=e.retries),e?.retryDelay&&(this._retryDelay=e.retryDelay)}clone(){let e=new c;return e._baseUrl=this._baseUrl,e._headers={...this._headers},e._timeout=this._timeout,e._retries=this._retries,e._retryDelay=this._retryDelay,e._query={...this._query},e}baseUrl(e){let t=this.clone();return t._baseUrl=e,t}withHeaders(e){let t=this.clone();return t._headers={...t._headers,...e},t}withToken(e,t="Bearer"){return this.withHeaders({Authorization:`${t} ${e}`})}withBasicAuth(e,t){let s=Buffer.from(`${e}:${t}`).toString("base64");return this.withHeaders({Authorization:`Basic ${s}`})}accept(e){return this.withHeaders({Accept:e})}contentType(e){return this.withHeaders({"Content-Type":e})}timeout(e){let t=this.clone();return t._timeout=e,t}retry(e,t=1e3){let s=this.clone();return s._retries=e,s._retryDelay=t,s}query(e){let t=this.clone();for(let[s,r]of Object.entries(e))r!=null&&(t._query[s]=String(r));return t}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async put(e,t){return this.request("PUT",e,t)}async patch(e,t){return this.request("PATCH",e,t)}async delete(e,t){return this.request("DELETE",e,t)}async request(e,t,s){let r=this.buildFullUrl(t),n={...this._headers},o;s!==void 0&&(n["Content-Type"]||(n["Content-Type"]="application/json"),o=typeof s=="string"?s:JSON.stringify(s)),n.Accept||(n.Accept="application/json");let i=null,a=1+this._retries;for(let l=0;l<a;l++){l>0&&await new Promise(u=>setTimeout(u,this._retryDelay*l));try{let u=new AbortController,d=setTimeout(()=>u.abort(),this._timeout),h=await fetch(r,{method:e,headers:n,body:o,signal:u.signal});if(clearTimeout(d),!h.ok&&h.status<500&&l<a-1,!h.ok&&h.status>=500&&l<a-1){i=new ye(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let m=h.headers.get("content-type")??"",f;if(m.includes("application/json")?f=await h.json():f=await h.text(),!h.ok)throw new ye(`HTTP ${h.status}: ${typeof f=="string"?f:JSON.stringify(f)}`,h.status,f);return{data:f,status:h.status,headers:h.headers,ok:!0}}catch(u){if(u instanceof ye)throw u;if(i=u,u.name==="AbortError"&&(i=new ye("Request timed out",0,null)),l>=a-1)break}}throw i??new Error("HTTP request failed")}buildFullUrl(e){let t=this._baseUrl?`${this._baseUrl.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`:e,s=Object.entries(this._query);if(s.length>0){let r=new URL(t);for(let[n,o]of s)r.searchParams.set(n,o);t=r.toString()}return t}},ye=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},cd=new dr});function Nn(c){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=c;return({event:n,resolve:o})=>e(n.request,({request:i,locale:a})=>(n.request=i,o(n,{transformPageChunk:({html:l})=>l.replace(s,a).replace(r,t(a))})))}function _n(c){return e=>c.deLocalizeUrl(e.url).pathname}var Mn=y(()=>{"use strict"});function Ln(c,e,t={}){return async s=>{let{superValidate:r,fail:n,message:o}=await import("sveltekit-superforms"),{zod:i}=await import("sveltekit-superforms/adapters"),a=await r(s,i(c));if(!a.valid)return n(400,{form:a});try{let l=await e(a.data,s);if(t.redirectTo){let{redirect:u}=await import("@sveltejs/kit");throw u(303,t.redirectTo)}return l??{form:a}}catch(l){if(l?.status>=300&&l?.status<400)throw l;return o(a,t.errorMessage||l.message||"An error occurred",{status:l.status||400})}}}async function In(c,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(c))}async function jn(c,e){let t=await c.request.formData(),s={};for(let[n,o]of t.entries())s[n]=o;let r=e.safeParse(s);if(!r.success){let{FormValidationError:n}=await Promise.resolve().then(()=>(dt(),fn));throw new n(r.error.flatten().fieldErrors)}return r.data}var qn=y(()=>{"use strict";dt()});var Un={};P(Un,{Application:()=>Ve,AuthManager:()=>rt,AuthenticateMiddleware:()=>me,BelongsTo:()=>te,BelongsToMany:()=>se,Broadcast:()=>Rn,Cache:()=>Sn,ColumnBuilder:()=>I,Connection:()=>g,Container:()=>K,Controller:()=>Qe,CorsMiddleware:()=>ze,CsrfMiddleware:()=>ie,DatabaseSessionStore:()=>Xe,ErrorHandler:()=>ge,Event:()=>re,EventDispatcher:()=>Re,FileSessionStore:()=>Ze,ForbiddenError:()=>ke,FormAuthorizationError:()=>V,FormRequest:()=>fe,FormValidationError:()=>J,HasMany:()=>ee,HasOne:()=>Z,Hash:()=>xs,HttpError:()=>k,Job:()=>Q,Log:()=>ot,LoggingMiddleware:()=>Ye,Mailable:()=>_e,Mailer:()=>Ns,MemorySessionStore:()=>W,Middleware:()=>x,MiddlewareStack:()=>q,Migration:()=>ve,Migrator:()=>Ee,Model:()=>We,ModelNotFoundError:()=>lt,NotFoundError:()=>$e,Notification:()=>mt,Notifier:()=>xn,OriginMiddleware:()=>oe,QueryBuilder:()=>N,Queue:()=>gs,RateLimitMiddleware:()=>ne,RedisSessionStore:()=>et,RequireAuthMiddleware:()=>nt,Schema:()=>j,Seeder:()=>Je,ServiceProvider:()=>Pe,Session:()=>ue,SessionMiddleware:()=>de,SignatureMiddleware:()=>Ge,Storage:()=>wn,TableBuilder:()=>Y,ThrottleMiddleware:()=>ae,UnauthorizedError:()=>De,ValidationError:()=>U,abort:()=>ut,abortIf:()=>an,abortUnless:()=>cn,apiFetch:()=>kn,buildUrl:()=>On,config:()=>dn,container:()=>zr,createFormAction:()=>Ln,createI18nHandle:()=>Nn,createReroute:()=>_n,createSvelarApp:()=>ln,createSvelarHooks:()=>Vs,env:()=>un,getCsrfToken:()=>hr,loadForm:()=>In,resource:()=>Gr,rules:()=>pn,schema:()=>Mr,sequence:()=>zs,signJwt:()=>Ms,validate:()=>mn,validateForm:()=>jn,verifyJwt:()=>Ls,z:()=>S});var Hn=y(()=>{"use strict";Jr();bs();ws();w();ts();ss();Vr();Es();vs();Yr();ce();Qr();Ys();hn();gn();Is();he();Ts();Js();Ke();dt();vn();Bs();Cn();fs();st();Pn();$n();An();Mn();qn();Ys()});var gr={};P(gr,{PluginRegistry:()=>yt});var mr,yt,bt=y(()=>{"use strict";C();mr=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:e}=await import("path"),{existsSync:t,readdirSync:s}=await import("fs"),{readFile:r}=await import("fs/promises"),n=[],o=e(process.cwd(),"node_modules");if(!t(o))return n;let i=async(a,l="")=>{if(t(a))try{let u=s(a,{withFileTypes:!0});for(let d of u){if(!d.isDirectory()||d.name.startsWith("."))continue;if(d.name.startsWith("@")){let E=e(a,d.name);await i(E,d.name+"/");continue}let h=l+d.name,m=d.name.startsWith("svelar-");if(!m)continue;let f=e(a,d.name,"package.json");if(t(f))try{let E=await r(f,"utf-8"),T=JSON.parse(E),be=T.keywords?.includes("svelar-plugin");if(!m&&!be)continue;let O={name:T.name||h,version:T.version||"0.0.0",description:T.description||"",packageName:h,installed:!0,enabled:!1,hasConfig:!!T.svelar?.config,hasMigrations:!!T.svelar?.migrations};n.push(O),this.plugins.set(O.name,O)}catch{}}}catch{}};return await i(o),n}enable(e){let t=this.plugins.get(e);if(!t)throw new Error(`Plugin "${e}" not found in registry.`);this.enabledPlugins.add(e),t.enabled=!0}disable(e){this.enabledPlugins.delete(e);let t=this.plugins.get(e);t&&(t.enabled=!1)}isEnabled(e){return this.enabledPlugins.has(e)}list(){return[...this.plugins.values()]}listEnabled(){return[...this.plugins.values()].filter(e=>this.enabledPlugins.has(e.name))}get(e){return this.plugins.get(e)}register(e){this.plugins.set(e.name,e)}},yt=b("svelar.pluginRegistry",()=>new mr)});var Fn={};P(Fn,{PluginPublisher:()=>br});var yr,br,wr=y(()=>{"use strict";C();yr=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:n,dirname:o}=await import("path"),{existsSync:i}=await import("fs"),a={configs:[],migrations:[],assets:[]},l=e.publishables?.()||{};for(let[u,d]of Object.entries(l))for(let h of d){if(t?.only&&h.type!==t.only)continue;let m=n(process.cwd(),h.dest),f=o(m);if(!(i(m)&&!t?.force))try{await s(f,{recursive:!0}),await r(h.source,m),h.type==="config"?a.configs.push(m):h.type==="migration"?a.migrations.push(m):h.type==="asset"&&a.assets.push(m)}catch(E){console.warn(`Failed to publish ${h.source} to ${m}:`,E)}}return a}async preview(e){let t={configs:[],migrations:[],assets:[]},s=e.publishables?.()||{};for(let[r,n]of Object.entries(s))for(let o of n){let i=je("path").join(process.cwd(),o.dest);o.type==="config"?t.configs.push(i):o.type==="migration"?t.migrations.push(i):o.type==="asset"&&t.assets.push(i)}return t}},br=b("svelar.pluginPublisher",()=>new yr)});var Bn={};P(Bn,{PluginInstaller:()=>la});var Er,la,Kn=y(()=>{"use strict";C();bt();wr();Er=class{async install(e,t){let{spawn:s}=await import("child_process"),{promisify:r}=await import("util"),{join:n}=await import("path"),{readFile:o}=await import("fs/promises"),{existsSync:i}=await import("fs");try{await this.runNpmInstall(e);let a=yt,l=await a.discover(),u;for(let h of l)if(h.packageName===e||h.name===e){u=h;break}if(!u)return{success:!1,pluginName:e,version:"0.0.0",published:null,error:`Plugin not found after installation. Make sure ${e} is a valid Svelar plugin.`};a.enable(u.name);let d=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(u.packageName);h&&(d=await br.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:u.name,version:u.version,published:d}}catch(a){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:a?.message??String(a)}}}async uninstall(e){try{let t=yt,s=t.get(e);return s?(t.disable(e),await this.runNpmUninstall(s.packageName),!0):!1}catch(t){return console.error("Failed to uninstall plugin:",t),!1}}async runNpmInstall(e){return new Promise((t,s)=>{let{spawn:r}=je("child_process"),n=r("npm",["install",e],{cwd:process.cwd(),stdio:"inherit"});n.on("close",o=>{o===0?t():s(new Error(`npm install exited with code ${o}`))}),n.on("error",s)})}async runNpmUninstall(e){return new Promise((t,s)=>{let{spawn:r}=je("child_process"),n=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});n.on("close",o=>{o===0?t():s(new Error(`npm uninstall exited with code ${o}`))}),n.on("error",s)})}async loadPluginClass(e){try{let t=await import(`${e}/plugin`);return t.default||Object.values(t)[0]}catch{try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}}},la=b("svelar.pluginInstaller",()=>new Er)});var Tt=class{commands=new Map;version;constructor(e="0.1.0"){this.version=e}register(e){let t=new e;return this.commands.set(t.name,t),this}add(e){return this.commands.set(e.name,e),this}async run(e=process.argv.slice(2)){let[t,...s]=e;if(!t||t==="--help"||t==="-h"){this.showHelp();return}if(t==="--version"||t==="-v"){console.log(`Svelar v${this.version}`);return}let r=this.commands.get(t);if(r||(console.error(`\x1B[31mUnknown command:\x1B[0m ${t}`),console.log("Run \x1B[36msvelar --help\x1B[0m for available commands."),process.exit(1)),s.includes("--help")||s.includes("-h")){this.showCommandHelp(r);return}let{args:n,flags:o}=this.parseArgs(s,r);try{await r.handle(n,o)}catch(i){let a=i instanceof Error?i.message:String(i);console.error(`\x1B[31mError:\x1B[0m ${a}`),i?.stack&&console.error(i.stack),process.exit(1)}}parseArgs(e,t){let s=[],r={};for(let n of t.flags)n.default!==void 0&&(r[n.name]=n.default);for(let n=0;n<e.length;n++){let o=e[n];if(o.startsWith("--")){let i=o.slice(2),a=i.indexOf("=");if(a!==-1){let d=i.slice(0,a);r[d]=i.slice(a+1);continue}let l=i;t.flags.find(d=>d.name===l)?.type==="boolean"?r[l]=!0:n+1<e.length&&!e[n+1].startsWith("-")?r[l]=e[++n]:r[l]=!0}else if(o.startsWith("-")&&o.length===2){let i=o.slice(1),a=t.flags.find(l=>l.alias===i);a&&(a.type==="boolean"?r[a.name]=!0:n+1<e.length&&(r[a.name]=e[++n]))}else s.push(o)}return{args:s,flags:r}}showCommandHelp(e){if(console.log(`
158
+ `,i=new TextEncoder().encode(r);for(let o of this.subscribers)if(o.userId!==s)try{o.controller.enqueue(i)}catch{}}},ft=class{config;constructor(e){this.config=e}async send(e,t,s){let r=Array.isArray(e)?e:[e],i=JSON.stringify({name:t,channels:r,data:JSON.stringify(s)}),o=Math.floor(Date.now()/1e3).toString(),n=await this.md5(i),a=["POST",`/apps/${this.config.appId}/events`,[`auth_key=${this.config.key}`,`auth_timestamp=${o}`,"auth_version=1.0",`body_md5=${n}`].join("&")].join(`
159
+ `),l=await this.hmacSha256(this.config.secret,a),u=this.config.useTLS!==!1?"https":"http",d=this.config.host??`api-${this.config.cluster??"mt1"}.pusher.com`,h=this.config.port??(this.config.useTLS!==!1?443:80),m=`${u}://${d}:${h}/apps/${this.config.appId}/events?auth_key=${this.config.key}&auth_timestamp=${o}&auth_version=1.0&body_md5=${n}&auth_signature=${l}`,f=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:i});if(!f.ok){let E=await f.text();throw new Error(`Pusher API error (${f.status}): ${E}`)}}async authenticate(e,t,s){let r=`${e}:${t}`,i;s&&(i=JSON.stringify(s),r+=`:${i}`);let o=await this.hmacSha256(this.config.secret,r),n=`${this.config.key}:${o}`;return i?{auth:n,channel_data:i}:{auth:n}}get key(){return this.config.key}clientConfig(){let e={key:this.config.key,cluster:this.config.cluster??"mt1"};return this.config.host&&(e.wsHost=this.config.host,e.wsPort=this.config.port??6001,e.wssPort=this.config.port??6001,e.forceTLS=this.config.useTLS??!1,e.enabledTransports=["ws","wss"],e.disableStats=!0),e}async md5(e){let{createHash:t}=await import("crypto");return t("md5").update(e).digest("hex")}async hmacSha256(e,t){let{createHmac:s}=await import("crypto");return s("sha256",e).update(t).digest("hex")}},ur=class{constructor(e,t,s){this.manager=e;this.eventName=t;this.eventData=s}channels=[];on(...e){return this.channels.push(...e),this}async send(){for(let e of this.channels)await this.manager.sendToChannel(e,this.eventName,this.eventData)}},dr=class{config={default:"sse",drivers:{sse:{driver:"sse"}}};sseChannels=new Map;channelAuth=new Map;pusherDriver=null;configure(e){this.config=e;let t=Object.values(e.drivers).find(s=>s.driver==="pusher");t&&t.driver==="pusher"&&(this.pusherDriver=new ft(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new lr(e)),this.sseChannels.get(e)}async authorize(e,t){if(cr(e)==="public")return!0;for(let[r,i]of this.channelAuth){let o=this.matchPattern(r,e);if(o!==null)return await i(t,o)}return!1}async authenticatePusher(e,t,s){if(!this.pusherDriver)throw new Error("Pusher driver is not configured. Call Broadcast.configure() first.");let r=cr(e);if(r==="public")return!1;let i=await this.authorize(e,s);if(i===!1)return!1;if(r==="presence"){let o=typeof i=="object"?{user_id:i.id??s.id,user_info:i}:{user_id:s.id,user_info:{id:s.id}};return this.pusherDriver.authenticate(t,e,o)}return this.pusherDriver.authenticate(t,e)}event(e,t){return new ur(this,e,t)}to(e,t){return{send:async(s,r)=>{await this.sendToChannel(e,s,r,t)}}}async sendToChannel(e,t,s,r){let i=this.config.drivers[this.config.default];switch(i?.driver){case"pusher":this.pusherDriver||(this.pusherDriver=new ft(i)),await this.pusherDriver.send(e,t,s);break;case"log":console.log(`[Broadcast] ${e} \u2192 ${t}:`,JSON.stringify(s));break;default:for(let[,o]of this.sseChannels)o.name===e&&o.send(t,s,r);break}}subscribe(e,t,s){return this.channel(e).stream(t,s)}members(e){let t=this.sseChannels.get(e);return t?t.getMembers():[]}pusher(){if(!this.pusherDriver)throw new Error("Pusher driver is not configured.");return this.pusherDriver}activeChannels(){return[...new Set([...this.sseChannels.values()].map(e=>e.name))]}totalSubscribers(){let e=0;for(let t of this.sseChannels.values())e+=t.subscriberCount();return e}prune(){for(let[e,t]of this.sseChannels)t.subscriberCount()===0&&this.sseChannels.delete(e)}matchPattern(e,t){let s=[],r=e.replace(/[.*+?^${}()|[\]\\]/g,a=>a==="{"||a==="}"?a:`\\${a}`).replace(/\\\{(\w+)\\\}/g,(a,l)=>(s.push(l),"([^.]+)")).replace(/\{(\w+)\}/g,(a,l)=>(s.push(l),"([^.]+)")),i=new RegExp(`^${r}$`),o=t.match(i);if(!o)return null;let n={};for(let a=0;a<s.length;a++)n[s[a]]=o[a+1];return n}},Pn=b("svelar.broadcast",()=>new dr)});function yt(c,e,t){Dn&&Dn(c,e,{description:t})}async function kn(c,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:i={},...o}=e,n=(o.method||"GET").toUpperCase(),a=new Headers(o.headers);if(["POST","PUT","PATCH","DELETE"].includes(n)){let l=pr(t);l&&a.set(s,l)}o.body&&typeof o.body=="string"&&!a.has("Content-Type")&&a.set("Content-Type","application/json"),a.has("Accept")||a.set("Accept","application/json");try{let l=await fetch(c,{...o,headers:a});return!l.ok&&r&&await ca(l,{...aa,...i}),l}catch(l){throw r&&yt("error","Network Error","Unable to connect. Check your internet connection."),l}}async function ca(c,e){let t="";try{if((c.headers.get("content-type")??"").includes("application/json")){let o=await c.clone().json();if(t=o.message??"",c.status===422&&o.errors){let n=Object.entries(o.errors).map(([a,l])=>`${a}: ${l.join(", ")}`).slice(0,3).join(`
160
+ `);yt("warning",e[422]??"Validation Error",n);return}}}catch{}let s=t||e[c.status]||`Error ${c.status}`,r=c.status>=500?"error":c.status===429?"warning":"error";if(c.status===401){yt("warning",s,"Please sign in to continue.");return}yt(r,s)}function pr(c="XSRF-TOKEN"){if(typeof document>"u")return null;let e=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function _n(c,e){if(!e)return c;let t=new URL(c,"http://localhost");for(let[s,r]of Object.entries(e))r!=null&&t.searchParams.set(s,String(r));return t.pathname+t.search}var aa,Dn,hr,be,cd,On=y(()=>{"use strict";aa={400:"Invalid request. Please check your input.",401:"Your session has expired. Please sign in again.",403:"You don't have permission to do this.",404:"The requested resource was not found.",405:"This action is not allowed.",409:"A conflict occurred. Please refresh and try again.",419:"Page expired. Please refresh and try again.",422:"The submitted data is invalid.",429:"Too many requests. Please wait a moment.",500:"Something went wrong on our end.",502:"Service temporarily unavailable. Try again shortly.",503:"Service is under maintenance. Try again shortly.",504:"Request timed out. Please try again."},Dn=null;hr=class c{_baseUrl="";_headers={};_timeout=3e4;_retries=0;_retryDelay=1e3;_query={};constructor(e){e?.baseUrl&&(this._baseUrl=e.baseUrl),e?.headers&&(this._headers={...e.headers}),e?.timeout&&(this._timeout=e.timeout),e?.retries&&(this._retries=e.retries),e?.retryDelay&&(this._retryDelay=e.retryDelay)}clone(){let e=new c;return e._baseUrl=this._baseUrl,e._headers={...this._headers},e._timeout=this._timeout,e._retries=this._retries,e._retryDelay=this._retryDelay,e._query={...this._query},e}baseUrl(e){let t=this.clone();return t._baseUrl=e,t}withHeaders(e){let t=this.clone();return t._headers={...t._headers,...e},t}withToken(e,t="Bearer"){return this.withHeaders({Authorization:`${t} ${e}`})}withBasicAuth(e,t){let s=Buffer.from(`${e}:${t}`).toString("base64");return this.withHeaders({Authorization:`Basic ${s}`})}accept(e){return this.withHeaders({Accept:e})}contentType(e){return this.withHeaders({"Content-Type":e})}timeout(e){let t=this.clone();return t._timeout=e,t}retry(e,t=1e3){let s=this.clone();return s._retries=e,s._retryDelay=t,s}query(e){let t=this.clone();for(let[s,r]of Object.entries(e))r!=null&&(t._query[s]=String(r));return t}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async put(e,t){return this.request("PUT",e,t)}async patch(e,t){return this.request("PATCH",e,t)}async delete(e,t){return this.request("DELETE",e,t)}async request(e,t,s){let r=this.buildFullUrl(t),i={...this._headers},o;s!==void 0&&(i["Content-Type"]||(i["Content-Type"]="application/json"),o=typeof s=="string"?s:JSON.stringify(s)),i.Accept||(i.Accept="application/json");let n=null,a=1+this._retries;for(let l=0;l<a;l++){l>0&&await new Promise(u=>setTimeout(u,this._retryDelay*l));try{let u=new AbortController,d=setTimeout(()=>u.abort(),this._timeout),h=await fetch(r,{method:e,headers:i,body:o,signal:u.signal});if(clearTimeout(d),!h.ok&&h.status<500&&l<a-1,!h.ok&&h.status>=500&&l<a-1){n=new be(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let m=h.headers.get("content-type")??"",f;if(m.includes("application/json")?f=await h.json():f=await h.text(),!h.ok)throw new be(`HTTP ${h.status}: ${typeof f=="string"?f:JSON.stringify(f)}`,h.status,f);return{data:f,status:h.status,headers:h.headers,ok:!0}}catch(u){if(u instanceof be)throw u;if(n=u,u.name==="AbortError"&&(n=new be("Request timed out",0,null)),l>=a-1)break}}throw n??new Error("HTTP request failed")}buildFullUrl(e){let t=this._baseUrl?`${this._baseUrl.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`:e,s=Object.entries(this._query);if(s.length>0){let r=new URL(t);for(let[i,o]of s)r.searchParams.set(i,o);t=r.toString()}return t}},be=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},cd=new hr});function An(c){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=c;return({event:i,resolve:o})=>e(i.request,({request:n,locale:a})=>(i.request=n,o(i,{transformPageChunk:({html:l})=>l.replace(s,a).replace(r,t(a))})))}function Nn(c){return e=>c.deLocalizeUrl(e.url).pathname}var Mn=y(()=>{"use strict"});function Ln(c,e,t={}){return async s=>{let{superValidate:r,fail:i,message:o}=await import("sveltekit-superforms"),{zod:n}=await import("sveltekit-superforms/adapters"),a=await r(s,n(c));if(!a.valid)return i(400,{form:a});try{let l=await e(a.data,s);if(t.redirectTo){let{redirect:u}=await import("@sveltejs/kit");throw u(303,t.redirectTo)}return l??{form:a}}catch(l){if(l?.status>=300&&l?.status<400)throw l;return o(a,t.errorMessage||l.message||"An error occurred",{status:l.status||400})}}}async function In(c,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(c))}async function jn(c,e){let t=await c.request.formData(),s={};for(let[i,o]of t.entries())s[i]=o;let r=e.safeParse(s);if(!r.success){let{FormValidationError:i}=await Promise.resolve().then(()=>(ht(),fn));throw new i(r.error.flatten().fieldErrors)}return r.data}var qn=y(()=>{"use strict";ht()});var Un={};P(Un,{Application:()=>Ye,AuthManager:()=>nt,AuthenticateMiddleware:()=>ge,BelongsTo:()=>se,BelongsToMany:()=>re,Broadcast:()=>Pn,Cache:()=>Sn,ColumnBuilder:()=>q,Connection:()=>g,Container:()=>W,Controller:()=>Xe,CorsMiddleware:()=>Ve,CsrfMiddleware:()=>oe,DatabaseSessionStore:()=>Ze,ErrorHandler:()=>fe,Event:()=>ne,EventDispatcher:()=>Pe,FileSessionStore:()=>et,ForbiddenError:()=>ke,FormAuthorizationError:()=>Y,FormRequest:()=>ye,FormValidationError:()=>J,HasMany:()=>te,HasOne:()=>ee,Hash:()=>Rs,HttpError:()=>_,Job:()=>X,Log:()=>at,LoggingMiddleware:()=>Ge,Mailable:()=>Ne,Mailer:()=>Ns,MemorySessionStore:()=>z,Middleware:()=>x,MiddlewareStack:()=>H,Migration:()=>we,Migrator:()=>Ee,Model:()=>ze,ModelNotFoundError:()=>ut,NotFoundError:()=>$e,Notification:()=>gt,Notifier:()=>xn,OriginMiddleware:()=>ae,QueryBuilder:()=>A,Queue:()=>fs,RateLimitMiddleware:()=>ie,RedisSessionStore:()=>tt,RequireAuthMiddleware:()=>it,Schema:()=>U,Seeder:()=>Je,ServiceProvider:()=>Re,Session:()=>de,SessionMiddleware:()=>he,SignatureMiddleware:()=>Qe,Storage:()=>vn,TableBuilder:()=>G,ThrottleMiddleware:()=>ce,UnauthorizedError:()=>De,ValidationError:()=>F,abort:()=>dt,abortIf:()=>an,abortUnless:()=>cn,apiFetch:()=>kn,buildUrl:()=>_n,config:()=>dn,container:()=>Yr,createFormAction:()=>Ln,createI18nHandle:()=>An,createReroute:()=>Nn,createSvelarApp:()=>ln,createSvelarHooks:()=>Ys,env:()=>un,getCsrfToken:()=>pr,loadForm:()=>In,resource:()=>Gr,rules:()=>pn,schema:()=>Mr,sequence:()=>Vs,signJwt:()=>Ls,validate:()=>mn,validateForm:()=>jn,verifyJwt:()=>Is,z:()=>S});var Hn=y(()=>{"use strict";zr();vs();ws();v();ss();rs();Jr();Ts();Es();Vr();le();Qr();Gs();hn();gn();js();pe();Ss();Js();We();ht();wn();Ks();Cn();ys();rt();Rn();$n();On();Mn();qn();Gs()});var fr={};P(fr,{PluginRegistry:()=>bt});var gr,bt,vt=y(()=>{"use strict";C();gr=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:e}=await import("path"),{existsSync:t,readdirSync:s}=await import("fs"),{readFile:r}=await import("fs/promises"),i=[],o=e(process.cwd(),"node_modules");if(!t(o))return i;let n=async(a,l="")=>{if(t(a))try{let u=s(a,{withFileTypes:!0});for(let d of u){if(!d.isDirectory()||d.name.startsWith("."))continue;if(d.name.startsWith("@")){let E=e(a,d.name);await n(E,d.name+"/");continue}let h=l+d.name,m=d.name.startsWith("svelar-");if(!m)continue;let f=e(a,d.name,"package.json");if(t(f))try{let E=await r(f,"utf-8"),T=JSON.parse(E),M=T.keywords?.includes("svelar-plugin");if(!m&&!M)continue;let O={name:T.name||h,version:T.version||"0.0.0",description:T.description||"",packageName:h,installed:!0,enabled:!1,hasConfig:!!T.svelar?.config,hasMigrations:!!T.svelar?.migrations};i.push(O),this.plugins.set(O.name,O)}catch{}}}catch{}};return await n(o),i}enable(e){let t=this.plugins.get(e);if(!t)throw new Error(`Plugin "${e}" not found in registry.`);this.enabledPlugins.add(e),t.enabled=!0}disable(e){this.enabledPlugins.delete(e);let t=this.plugins.get(e);t&&(t.enabled=!1)}isEnabled(e){return this.enabledPlugins.has(e)}list(){return[...this.plugins.values()]}listEnabled(){return[...this.plugins.values()].filter(e=>this.enabledPlugins.has(e.name))}get(e){return this.plugins.get(e)}register(e){this.plugins.set(e.name,e)}},bt=b("svelar.pluginRegistry",()=>new gr)});var Fn={};P(Fn,{PluginPublisher:()=>vr});var br,vr,wr=y(()=>{"use strict";C();br=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:i,dirname:o}=await import("path"),{existsSync:n}=await import("fs"),a={configs:[],migrations:[],assets:[]},l=e.publishables?.()||{};for(let[u,d]of Object.entries(l))for(let h of d){if(t?.only&&h.type!==t.only)continue;let m=i(process.cwd(),h.dest),f=o(m);if(!(n(m)&&!t?.force))try{await s(f,{recursive:!0}),await r(h.source,m),h.type==="config"?a.configs.push(m):h.type==="migration"?a.migrations.push(m):h.type==="asset"&&a.assets.push(m)}catch(E){console.warn(`Failed to publish ${h.source} to ${m}:`,E)}}return a}async preview(e){let t={configs:[],migrations:[],assets:[]},s=e.publishables?.()||{};for(let[r,i]of Object.entries(s))for(let o of i){let n=je("path").join(process.cwd(),o.dest);o.type==="config"?t.configs.push(n):o.type==="migration"?t.migrations.push(n):o.type==="asset"&&t.assets.push(n)}return t}},vr=b("svelar.pluginPublisher",()=>new br)});var Bn={};P(Bn,{PluginInstaller:()=>la});var Tr,la,Kn=y(()=>{"use strict";C();vt();wr();Tr=class{async install(e,t){let{spawn:s}=await import("child_process"),{promisify:r}=await import("util"),{join:i}=await import("path"),{readFile:o}=await import("fs/promises"),{existsSync:n}=await import("fs");try{await this.runNpmInstall(e);let a=bt,l=await a.discover(),u;for(let h of l)if(h.packageName===e||h.name===e){u=h;break}if(!u)return{success:!1,pluginName:e,version:"0.0.0",published:null,error:`Plugin not found after installation. Make sure ${e} is a valid Svelar plugin.`};a.enable(u.name);let d=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(u.packageName);h&&(d=await vr.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:u.name,version:u.version,published:d}}catch(a){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:a?.message??String(a)}}}async uninstall(e){try{let t=bt,s=t.get(e);return s?(t.disable(e),await this.runNpmUninstall(s.packageName),!0):!1}catch(t){return console.error("Failed to uninstall plugin:",t),!1}}async runNpmInstall(e){return new Promise((t,s)=>{let{spawn:r}=je("child_process"),i=r("npm",["install",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",o=>{o===0?t():s(new Error(`npm install exited with code ${o}`))}),i.on("error",s)})}async runNpmUninstall(e){return new Promise((t,s)=>{let{spawn:r}=je("child_process"),i=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",o=>{o===0?t():s(new Error(`npm uninstall exited with code ${o}`))}),i.on("error",s)})}async loadPluginClass(e){try{let t=await import(`${e}/plugin`);return t.default||Object.values(t)[0]}catch{try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}}},la=b("svelar.pluginInstaller",()=>new Tr)});var St=class{commands=new Map;version;constructor(e="0.1.0"){this.version=e}register(e){let t=new e;return this.commands.set(t.name,t),this}add(e){return this.commands.set(e.name,e),this}async run(e=process.argv.slice(2)){let[t,...s]=e;if(!t||t==="--help"||t==="-h"){this.showHelp();return}if(t==="--version"||t==="-v"){console.log(`Svelar v${this.version}`);return}let r=this.commands.get(t);if(r||(console.error(`\x1B[31mUnknown command:\x1B[0m ${t}`),console.log("Run \x1B[36msvelar --help\x1B[0m for available commands."),process.exit(1)),s.includes("--help")||s.includes("-h")){this.showCommandHelp(r);return}let{args:i,flags:o}=this.parseArgs(s,r);try{await r.handle(i,o)}catch(n){let a=n instanceof Error?n.message:String(n);console.error(`\x1B[31mError:\x1B[0m ${a}`),n?.stack&&console.error(n.stack),process.exit(1)}}parseArgs(e,t){let s=[],r={};for(let i of t.flags)i.default!==void 0&&(r[i.name]=i.default);for(let i=0;i<e.length;i++){let o=e[i];if(o.startsWith("--")){let n=o.slice(2),a=n.indexOf("=");if(a!==-1){let d=n.slice(0,a);r[d]=n.slice(a+1);continue}let l=n;t.flags.find(d=>d.name===l)?.type==="boolean"?r[l]=!0:i+1<e.length&&!e[i+1].startsWith("-")?r[l]=e[++i]:r[l]=!0}else if(o.startsWith("-")&&o.length===2){let n=o.slice(1),a=t.flags.find(l=>l.alias===n);a&&(a.type==="boolean"?r[a.name]=!0:i+1<e.length&&(r[a.name]=e[++i]))}else s.push(o)}return{args:s,flags:r}}showCommandHelp(e){if(console.log(`
161
161
  \x1B[33mDescription:\x1B[0m`),console.log(` ${e.description}
162
162
  `),console.log("\x1B[33mUsage:\x1B[0m"),console.log(` svelar ${e.name} [options]
163
- `),e.flags.length>0){console.log("\x1B[33mOptions:\x1B[0m");for(let t of e.flags){let s=t.alias?`-${t.alias}, `:" ",r=`--${t.name}`,n=24-s.length-r.length;console.log(` ${s}${r}${" ".repeat(Math.max(1,n))}${t.description}`)}console.log()}}showHelp(){console.log(`
163
+ `),e.flags.length>0){console.log("\x1B[33mOptions:\x1B[0m");for(let t of e.flags){let s=t.alias?`-${t.alias}, `:" ",r=`--${t.name}`,i=24-s.length-r.length;console.log(` ${s}${r}${" ".repeat(Math.max(1,i))}${t.description}`)}console.log()}}showHelp(){console.log(`
164
164
  \x1B[36m ____ _
165
165
  / ___|_ _____| | __ _ _ __
166
166
  \\___ \\ \\ / / _ \\ |/ _\` | '__|
@@ -171,7 +171,7 @@ id: ${Date.now()}
171
171
  svelar <command> [arguments] [options]
172
172
 
173
173
  \x1B[33mAvailable Commands:\x1B[0m`);let e=new Map;for(let[,t]of this.commands){let s=t.name.includes(":")?t.name.split(":")[0]:"general";e.has(s)||e.set(s,[]),e.get(s).push(t)}for(let[t,s]of e){console.log(`
174
- \x1B[32m${t}\x1B[0m`);for(let r of s){let n=30-r.name.length;console.log(` \x1B[36m${r.name}\x1B[0m${" ".repeat(Math.max(1,n))}${r.description}`)}}console.log()}};import{existsSync as Yn}from"fs";import{join as we}from"path";var p=class{arguments=[];flags=[];async bootstrap(){let{join:e}=await import("path"),{existsSync:t,readFileSync:s}=await import("fs"),{Connection:r}=await Promise.resolve().then(()=>(w(),v)),n=process.cwd();try{r.getDriver();return}catch{}let o=e(n,"svelar.database.json");if(t(o))try{let l=s(o,"utf-8"),u=JSON.parse(l);r.configure(u),this.info("Database configured from svelar.database.json");return}catch(l){this.warn(`Failed to parse svelar.database.json: ${String(l?.message??l)}`)}let i=process.env.DB_DRIVER??"sqlite",a=process.env.DB_PATH??"database.db";r.configure({default:i,connections:{[i]:{driver:i,filename:a,host:process.env.DB_HOST,port:process.env.DB_PORT?parseInt(process.env.DB_PORT):void 0,database:process.env.DB_NAME,user:process.env.DB_USER,password:process.env.DB_PASSWORD}}}),this.info(`Using ${i} database${i==="sqlite"?`: ${a}`:""}`)}log(e){console.log(e)}info(e){console.log(`\x1B[34mINFO\x1B[0m ${e}`)}success(e){console.log(`\x1B[32m\u2713\x1B[0m ${e}`)}warn(e){console.log(`\x1B[33mWARN\x1B[0m ${e}`)}error(e){console.error(`\x1B[31mERROR\x1B[0m ${e}`)}table(e,t){let s=e.map((o,i)=>Math.max(o.length,...t.map(a=>(a[i]??"").length))),r=s.map(o=>"\u2500".repeat(o+2)).join("\u253C"),n=o=>o.map((i,a)=>` ${(i??"").padEnd(s[a])} `).join("\u2502");console.log(n(e)),console.log(r);for(let o of t)console.log(n(o))}newLine(){console.log()}isDDD(){return Yn(we(process.cwd(),"src","lib","modules"))}sharedDir(e){return this.isDDD()?we(process.cwd(),"src","lib","shared",e):we(process.cwd(),"src","lib",e)}moduleDir(e,t){return this.isDDD()?we(process.cwd(),"src","lib","modules",e):we(process.cwd(),"src","lib",t)}};import{writeFileSync as Ct,mkdirSync as xt,existsSync as Gn}from"fs";import{join as qe}from"path";var Pt=class extends p{name="make:model";description="Create a new model class";arguments=["name"];flags=[{name:"migration",alias:"m",description:"Also create a migration",type:"boolean"},{name:"controller",alias:"c",description:"Also create a controller",type:"boolean"},{name:"resource",alias:"r",description:"Create a resource controller",type:"boolean"},{name:"all",alias:"a",description:"Create model, migration, and controller",type:"boolean"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a model name.");return}let r=this.toSnakeCase(this.pluralize(s)),n=t.module||this.toSnakeCase(this.pluralize(s));!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=this.moduleDir(n,"models");xt(o,{recursive:!0});let i=qe(o,`${s}.ts`);if(Gn(i)){this.warn(`Model ${s} already exists at ${i}`);return}let a=`import { Model } from '@beeblock/svelar/orm';
174
+ \x1B[32m${t}\x1B[0m`);for(let r of s){let i=30-r.name.length;console.log(` \x1B[36m${r.name}\x1B[0m${" ".repeat(Math.max(1,i))}${r.description}`)}}console.log()}};import{existsSync as Vn}from"fs";import{join as ve}from"path";var p=class{arguments=[];flags=[];async bootstrap(){let{join:e}=await import("path"),{existsSync:t,readFileSync:s}=await import("fs"),{Connection:r}=await Promise.resolve().then(()=>(v(),w)),i=process.cwd();try{r.getDriver();return}catch{}let o=e(i,"svelar.database.json");if(t(o))try{let l=s(o,"utf-8"),u=JSON.parse(l);r.configure(u),this.info("Database configured from svelar.database.json");return}catch(l){this.warn(`Failed to parse svelar.database.json: ${String(l?.message??l)}`)}let n=process.env.DB_DRIVER??"sqlite",a=process.env.DB_PATH??"database.db";r.configure({default:n,connections:{[n]:{driver:n,filename:a,host:process.env.DB_HOST,port:process.env.DB_PORT?parseInt(process.env.DB_PORT):void 0,database:process.env.DB_NAME,user:process.env.DB_USER,password:process.env.DB_PASSWORD}}}),this.info(`Using ${n} database${n==="sqlite"?`: ${a}`:""}`)}log(e){console.log(e)}info(e){console.log(`\x1B[34mINFO\x1B[0m ${e}`)}success(e){console.log(`\x1B[32m\u2713\x1B[0m ${e}`)}warn(e){console.log(`\x1B[33mWARN\x1B[0m ${e}`)}error(e){console.error(`\x1B[31mERROR\x1B[0m ${e}`)}table(e,t){let s=e.map((o,n)=>Math.max(o.length,...t.map(a=>(a[n]??"").length))),r=s.map(o=>"\u2500".repeat(o+2)).join("\u253C"),i=o=>o.map((n,a)=>` ${(n??"").padEnd(s[a])} `).join("\u2502");console.log(i(e)),console.log(r);for(let o of t)console.log(i(o))}newLine(){console.log()}isDDD(){return Vn(ve(process.cwd(),"src","lib","modules"))}sharedDir(e){return this.isDDD()?ve(process.cwd(),"src","lib","shared",e):ve(process.cwd(),"src","lib",e)}moduleDir(e,t){return this.isDDD()?ve(process.cwd(),"src","lib","modules",e):ve(process.cwd(),"src","lib",t)}};import{writeFileSync as xt,mkdirSync as Rt,existsSync as Gn}from"fs";import{join as qe}from"path";var Pt=class extends p{name="make:model";description="Create a new model class";arguments=["name"];flags=[{name:"migration",alias:"m",description:"Also create a migration",type:"boolean"},{name:"controller",alias:"c",description:"Also create a controller",type:"boolean"},{name:"resource",alias:"r",description:"Create a resource controller",type:"boolean"},{name:"all",alias:"a",description:"Create model, migration, and controller",type:"boolean"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a model name.");return}let r=this.toSnakeCase(this.pluralize(s)),i=t.module||this.toSnakeCase(this.pluralize(s));!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let o=this.moduleDir(i,"models");Rt(o,{recursive:!0});let n=qe(o,`${s}.ts`);if(Gn(n)){this.warn(`Model ${s} already exists at ${n}`);return}let a=`import { Model } from '@beeblock/svelar/orm';
175
175
 
176
176
  export class ${s} extends Model {
177
177
  static table = '${r}';
@@ -188,7 +188,7 @@ export class ${s} extends Model {
188
188
  // return this.hasMany(Post, 'user_id');
189
189
  // }
190
190
  }
191
- `;Ct(i,a);let l=this.isDDD()?`src/lib/modules/${n}`:"src/lib/models";if(this.success(`Model created: ${l}/${s}.ts`),t.migration||t.all){let d=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,h=qe(process.cwd(),"src","lib","database","migrations");xt(h,{recursive:!0});let m=`import { Migration } from '@beeblock/svelar/database';
191
+ `;xt(n,a);let l=this.isDDD()?`src/lib/modules/${i}`:"src/lib/models";if(this.success(`Model created: ${l}/${s}.ts`),t.migration||t.all){let d=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,h=qe(process.cwd(),"src","lib","database","migrations");Rt(h,{recursive:!0});let m=`import { Migration } from '@beeblock/svelar/database';
192
192
 
193
193
  export default class Create${s}sTable extends Migration {
194
194
  async up() {
@@ -205,7 +205,7 @@ export default class Create${s}sTable extends Migration {
205
205
  await this.schema.dropTable('${r}');
206
206
  }
207
207
  }
208
- `;Ct(qe(h,`${d}.ts`),m),this.success(`Migration created: src/lib/database/migrations/${d}.ts`)}if(t.controller||t.resource||t.all){let u=`${s}Controller`,d=this.moduleDir(n,"controllers");xt(d,{recursive:!0});let h=t.resource||t.all,m=this.isDDD()?`./${s}.js`:`../models/${s}.js`,f=h?this.generateResourceController(s,u,m):this.generateBasicController(s,u,m);Ct(qe(d,`${u}.ts`),f);let E=this.isDDD()?`src/lib/modules/${n}`:"src/lib/controllers";this.success(`Controller created: ${E}/${u}.ts`)}}generateResourceController(e,t,s=`./${e}.js`){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
208
+ `;xt(qe(h,`${d}.ts`),m),this.success(`Migration created: src/lib/database/migrations/${d}.ts`)}if(t.controller||t.resource||t.all){let u=`${s}Controller`,d=this.moduleDir(i,"controllers");Rt(d,{recursive:!0});let h=t.resource||t.all,m=this.isDDD()?`./${s}.js`:`../models/${s}.js`,f=h?this.generateResourceController(s,u,m):this.generateBasicController(s,u,m);xt(qe(d,`${u}.ts`),f);let E=this.isDDD()?`src/lib/modules/${i}`:"src/lib/controllers";this.success(`Controller created: ${E}/${u}.ts`)}}generateResourceController(e,t,s=`./${e}.js`){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
209
209
  import { z } from '@beeblock/svelar/validation';
210
210
  import { ${e} } from '${s}';
211
211
 
@@ -257,9 +257,9 @@ export class ${t} extends Controller {
257
257
  return this.json(items);
258
258
  }
259
259
  }
260
- `}toSnakeCase(e){return e.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}pluralize(e){return e.endsWith("y")?e.slice(0,-1)+"ies":e.endsWith("s")||e.endsWith("x")||e.endsWith("z")||e.endsWith("ch")||e.endsWith("sh")?e+"es":e+"s"}};import{writeFileSync as Qn,mkdirSync as Xn}from"fs";import{join as Cr}from"path";var Rt=class extends p{name="make:migration";description="Create a new migration file";arguments=["name"];flags=[{name:"create",description:"Table to create",type:"string"},{name:"table",description:"Table to modify",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a migration name (e.g. create_users_table).");return}let r=Cr(process.cwd(),"src","lib","database","migrations");Xn(r,{recursive:!0});let o=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_${s}`,i=this.toPascalCase(s),a=t.create??this.detectTableName(s,"create"),l=t.table??this.detectTableName(s,"add"),u;a?u=`import { Migration } from '@beeblock/svelar/database';
260
+ `}toSnakeCase(e){return e.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}pluralize(e){return e.endsWith("y")?e.slice(0,-1)+"ies":e.endsWith("s")||e.endsWith("x")||e.endsWith("z")||e.endsWith("ch")||e.endsWith("sh")?e+"es":e+"s"}};import{writeFileSync as Qn,mkdirSync as Xn}from"fs";import{join as xr}from"path";var $t=class extends p{name="make:migration";description="Create a new migration file";arguments=["name"];flags=[{name:"create",description:"Table to create",type:"string"},{name:"table",description:"Table to modify",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a migration name (e.g. create_users_table).");return}let r=xr(process.cwd(),"src","lib","database","migrations");Xn(r,{recursive:!0});let o=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_${s}`,n=this.toPascalCase(s),a=t.create??this.detectTableName(s,"create"),l=t.table??this.detectTableName(s,"add"),u;a?u=`import { Migration } from '@beeblock/svelar/database';
261
261
 
262
- export default class ${i} extends Migration {
262
+ export default class ${n} extends Migration {
263
263
  async up() {
264
264
  await this.schema.createTable('${a}', (table) => {
265
265
  table.increments('id');
@@ -274,7 +274,7 @@ export default class ${i} extends Migration {
274
274
  }
275
275
  `:l?u=`import { Migration } from '@beeblock/svelar/database';
276
276
 
277
- export default class ${i} extends Migration {
277
+ export default class ${n} extends Migration {
278
278
  async up() {
279
279
  await this.schema.addColumn('${l}', (table) => {
280
280
  // Add new columns here
@@ -288,7 +288,7 @@ export default class ${i} extends Migration {
288
288
  }
289
289
  `:u=`import { Migration } from '@beeblock/svelar/database';
290
290
 
291
- export default class ${i} extends Migration {
291
+ export default class ${n} extends Migration {
292
292
  async up() {
293
293
  // Write your migration here
294
294
  }
@@ -297,7 +297,7 @@ export default class ${i} extends Migration {
297
297
  // Reverse the migration
298
298
  }
299
299
  }
300
- `,Qn(Cr(r,`${o}.ts`),u),this.success(`Migration created: src/lib/database/migrations/${o}.ts`)}detectTableName(e,t){let s=e.match(new RegExp(`${t}_(.+?)_table`));return s?s[1]:null}toPascalCase(e){return e.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join("")}};import{writeFileSync as Zn,mkdirSync as ei,existsSync as ti}from"fs";import{join as si}from"path";var $t=class extends p{name="make:controller";description="Create a new controller class";arguments=["name"];flags=[{name:"resource",alias:"r",description:"Create a resource controller with CRUD methods",type:"boolean"},{name:"model",alias:"m",description:"Model name for resource controller",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a controller name.");return}let r=s.endsWith("Controller")?s:`${s}Controller`,n=r.replace(/Controller$/,""),o=t.module||n.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let i=this.moduleDir(o,"controllers");ei(i,{recursive:!0});let a=si(i,`${r}.ts`);if(ti(a)){this.warn(`Controller ${r} already exists.`);return}let l=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,u=t.resource?this.generateResourceController(r,t.model,l):this.generateBasicController(r);Zn(a,u);let d=this.isDDD()?`src/lib/modules/${o}`:"src/lib/controllers";this.success(`Controller created: ${d}/${r}.ts`)}generateResourceController(e,t,s){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
300
+ `,Qn(xr(r,`${o}.ts`),u),this.success(`Migration created: src/lib/database/migrations/${o}.ts`)}detectTableName(e,t){let s=e.match(new RegExp(`${t}_(.+?)_table`));return s?s[1]:null}toPascalCase(e){return e.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join("")}};import{writeFileSync as Zn,mkdirSync as ei,existsSync as ti}from"fs";import{join as si}from"path";var Dt=class extends p{name="make:controller";description="Create a new controller class";arguments=["name"];flags=[{name:"resource",alias:"r",description:"Create a resource controller with CRUD methods",type:"boolean"},{name:"model",alias:"m",description:"Model name for resource controller",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a controller name.");return}let r=s.endsWith("Controller")?s:`${s}Controller`,i=r.replace(/Controller$/,""),o=t.module||i.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let n=this.moduleDir(o,"controllers");ei(n,{recursive:!0});let a=si(n,`${r}.ts`);if(ti(a)){this.warn(`Controller ${r} already exists.`);return}let l=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,u=t.resource?this.generateResourceController(r,t.model,l):this.generateBasicController(r);Zn(a,u);let d=this.isDDD()?`src/lib/modules/${o}`:"src/lib/controllers";this.success(`Controller created: ${d}/${r}.ts`)}generateResourceController(e,t,s){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
301
301
  import { z } from '@beeblock/svelar/validation';
302
302
  ${t&&s?`import { ${t} } from '${s}';
303
303
  `:""}
@@ -343,7 +343,7 @@ export class ${e} extends Controller {
343
343
  return this.json({ message: 'Hello from ${e}' });
344
344
  }
345
345
  }
346
- `}};import{writeFileSync as ri,mkdirSync as ni,existsSync as ii}from"fs";import{join as oi}from"path";var Dt=class extends p{name="make:middleware";description="Create a new middleware class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a middleware name.");return}let s=t.endsWith("Middleware")?t:`${t}Middleware`,r=this.sharedDir("middleware");ni(r,{recursive:!0});let n=oi(r,`${s}.ts`);if(ii(n)){this.warn(`Middleware ${s} already exists.`);return}let o=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
346
+ `}};import{writeFileSync as ri,mkdirSync as ni,existsSync as ii}from"fs";import{join as oi}from"path";var kt=class extends p{name="make:middleware";description="Create a new middleware class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a middleware name.");return}let s=t.endsWith("Middleware")?t:`${t}Middleware`,r=this.sharedDir("middleware");ni(r,{recursive:!0});let i=oi(r,`${s}.ts`);if(ii(i)){this.warn(`Middleware ${s} already exists.`);return}let o=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
347
347
 
348
348
  export class ${s} extends Middleware {
349
349
  async handle(ctx: MiddlewareContext, next: NextFunction): Promise<Response | void> {
@@ -356,7 +356,7 @@ export class ${s} extends Middleware {
356
356
  return response;
357
357
  }
358
358
  }
359
- `;ri(n,o);let i=this.isDDD()?`src/lib/shared/middleware/${s}.ts`:`src/lib/middleware/${s}.ts`;this.success(`Middleware created: ${i}`)}};import{writeFileSync as ai,mkdirSync as ci,existsSync as li}from"fs";import{join as ui}from"path";var kt=class extends p{name="make:provider";description="Create a new service provider class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a provider name.");return}let s=t.endsWith("ServiceProvider")?t:`${t}ServiceProvider`,r=this.sharedDir("providers");ci(r,{recursive:!0});let n=ui(r,`${s}.ts`);if(li(n)){this.warn(`Provider ${s} already exists.`);return}let o=`import { ServiceProvider } from '@beeblock/svelar/container';
359
+ `;ri(i,o);let n=this.isDDD()?`src/lib/shared/middleware/${s}.ts`:`src/lib/middleware/${s}.ts`;this.success(`Middleware created: ${n}`)}};import{writeFileSync as ai,mkdirSync as ci,existsSync as li}from"fs";import{join as ui}from"path";var _t=class extends p{name="make:provider";description="Create a new service provider class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a provider name.");return}let s=t.endsWith("ServiceProvider")?t:`${t}ServiceProvider`,r=this.sharedDir("providers");ci(r,{recursive:!0});let i=ui(r,`${s}.ts`);if(li(i)){this.warn(`Provider ${s} already exists.`);return}let o=`import { ServiceProvider } from '@beeblock/svelar/container';
360
360
  import type { Container } from '@beeblock/svelar/container';
361
361
 
362
362
  export class ${s} extends ServiceProvider {
@@ -377,7 +377,7 @@ export class ${s} extends ServiceProvider {
377
377
  // Initialization logic here
378
378
  }
379
379
  }
380
- `;ai(n,o);let i=this.isDDD()?`src/lib/shared/providers/${s}.ts`:`src/lib/providers/${s}.ts`;this.success(`Provider created: ${i}`)}};import{writeFileSync as di,mkdirSync as hi,existsSync as pi}from"fs";import{join as xr}from"path";var Ot=class extends p{name="make:seeder";description="Create a new database seeder class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a seeder name.");return}let s=t.endsWith("Seeder")?t:`${t}Seeder`,r=xr(process.cwd(),"src","lib","database","seeders");hi(r,{recursive:!0});let n=xr(r,`${s}.ts`);if(pi(n)){this.warn(`Seeder ${s} already exists.`);return}let o=`import { Seeder } from '@beeblock/svelar/database';
380
+ `;ai(i,o);let n=this.isDDD()?`src/lib/shared/providers/${s}.ts`:`src/lib/providers/${s}.ts`;this.success(`Provider created: ${n}`)}};import{writeFileSync as di,mkdirSync as hi,existsSync as pi}from"fs";import{join as Rr}from"path";var Ot=class extends p{name="make:seeder";description="Create a new database seeder class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a seeder name.");return}let s=t.endsWith("Seeder")?t:`${t}Seeder`,r=Rr(process.cwd(),"src","lib","database","seeders");hi(r,{recursive:!0});let i=Rr(r,`${s}.ts`);if(pi(i)){this.warn(`Seeder ${s} already exists.`);return}let o=`import { Seeder } from '@beeblock/svelar/database';
381
381
 
382
382
  export class ${s} extends Seeder {
383
383
  async run(): Promise<void> {
@@ -386,8 +386,8 @@ export class ${s} extends Seeder {
386
386
  // await User.create({ name: 'Admin', email: 'admin@example.com' });
387
387
  }
388
388
  }
389
- `;di(n,o),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as mi,mkdirSync as gi,existsSync as fi}from"fs";import{join as yi}from"path";var At=class extends p{name="make:service";description="Create a new service class";arguments=["name"];flags=[{name:"crud",description:"Create a CRUD service with model",type:"boolean"},{name:"model",alias:"m",description:"Model name for CRUD service",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a service name.");return}let r=s.endsWith("Service")?s:`${s}Service`,n=r.replace(/Service$/,""),o=t.module||n.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let i=this.moduleDir(o,"services");gi(i,{recursive:!0});let a=yi(i,`${r}.ts`);if(fi(a)){this.warn(`Service ${r} already exists.`);return}let l=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,u=t.crud?this.generateCrudService(r,t.model,l):this.generateBasicService(r);mi(a,u);let d=this.isDDD()?`src/lib/modules/${o}`:"src/lib/services";this.success(`Service created: ${d}/${r}.ts`)}generateCrudService(e,t,s){let r=t||"Model",n=s||`./${r}.js`;return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
390
- import { ${r} } from '${n}';
389
+ `;di(i,o),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as mi,mkdirSync as gi,existsSync as fi}from"fs";import{join as yi}from"path";var At=class extends p{name="make:service";description="Create a new service class";arguments=["name"];flags=[{name:"crud",description:"Create a CRUD service with model",type:"boolean"},{name:"model",alias:"m",description:"Model name for CRUD service",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a service name.");return}let r=s.endsWith("Service")?s:`${s}Service`,i=r.replace(/Service$/,""),o=t.module||i.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let n=this.moduleDir(o,"services");gi(n,{recursive:!0});let a=yi(n,`${r}.ts`);if(fi(a)){this.warn(`Service ${r} already exists.`);return}let l=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,u=t.crud?this.generateCrudService(r,t.model,l):this.generateBasicService(r);mi(a,u);let d=this.isDDD()?`src/lib/modules/${o}`:"src/lib/services";this.success(`Service created: ${d}/${r}.ts`)}generateCrudService(e,t,s){let r=t||"Model",i=s||`./${r}.js`;return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
390
+ import { ${r} } from '${i}';
391
391
 
392
392
  export class ${e} extends CrudService<${r}> {
393
393
  protected model = ${r};
@@ -411,7 +411,7 @@ export class ${e} extends Service {
411
411
  }
412
412
  }
413
413
  }
414
- `}};import{writeFileSync as bi,mkdirSync as wi,existsSync as vi}from"fs";import{join as Ei}from"path";var Nt=class extends p{name="make:repository";description="Create a new repository class";arguments=["name"];flags=[{name:"model",alias:"m",description:"Model name for the repository",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a repository name.");return}let r=s.endsWith("Repository")?s:`${s}Repository`,n=r.replace(/Repository$/,""),o=t.module||n.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let i=this.moduleDir(o,"repositories");wi(i,{recursive:!0});let a=Ei(i,`${r}.ts`);if(vi(a)){this.warn(`Repository ${r} already exists.`);return}let l=t.model||this.inferModelName(r),u=this.isDDD()?`./${l}.js`:`../models/${l}.js`,d=`import { Repository } from '@beeblock/svelar/repositories';
414
+ `}};import{writeFileSync as bi,mkdirSync as vi,existsSync as wi}from"fs";import{join as Ei}from"path";var Nt=class extends p{name="make:repository";description="Create a new repository class";arguments=["name"];flags=[{name:"model",alias:"m",description:"Model name for the repository",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a repository name.");return}let r=s.endsWith("Repository")?s:`${s}Repository`,i=r.replace(/Repository$/,""),o=t.module||i.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let n=this.moduleDir(o,"repositories");vi(n,{recursive:!0});let a=Ei(n,`${r}.ts`);if(wi(a)){this.warn(`Repository ${r} already exists.`);return}let l=t.model||this.inferModelName(r),u=this.isDDD()?`./${l}.js`:`../models/${l}.js`,d=`import { Repository } from '@beeblock/svelar/repositories';
415
415
  import { ${l} } from '${u}';
416
416
 
417
417
  export class ${r} extends Repository<${l}> {
@@ -428,7 +428,7 @@ export class ${r} extends Repository<${l}> {
428
428
  // return ${l}.where('active', true).orderBy('name').get();
429
429
  // }
430
430
  }
431
- `;bi(a,d);let h=this.isDDD()?`src/lib/modules/${o}`:"src/lib/repositories";this.success(`Repository created: ${h}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as Ti,mkdirSync as Si,existsSync as Ci}from"fs";import{join as xi}from"path";var _t=class extends p{name="make:action";description="Create a new action class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an action name.");return}let r=s.endsWith("Action")?s:`${s}Action`,n=r.replace(/Action$/,""),o=t.module||n.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let i=this.moduleDir(o,"actions");Si(i,{recursive:!0});let a=xi(i,`${r}.ts`);if(Ci(a)){this.warn(`Action ${r} already exists.`);return}let l=`import { Action } from '@beeblock/svelar/actions';
431
+ `;bi(a,d);let h=this.isDDD()?`src/lib/modules/${o}`:"src/lib/repositories";this.success(`Repository created: ${h}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as Ti,mkdirSync as Si,existsSync as Ci}from"fs";import{join as xi}from"path";var Mt=class extends p{name="make:action";description="Create a new action class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an action name.");return}let r=s.endsWith("Action")?s:`${s}Action`,i=r.replace(/Action$/,""),o=t.module||i.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let n=this.moduleDir(o,"actions");Si(n,{recursive:!0});let a=xi(n,`${r}.ts`);if(Ci(a)){this.warn(`Action ${r} already exists.`);return}let l=`import { Action } from '@beeblock/svelar/actions';
432
432
 
433
433
  interface ${r}Input {
434
434
  // Define input type
@@ -444,7 +444,7 @@ export class ${r} extends Action<${r}Input, ${r}Output> {
444
444
  throw new Error('Not implemented');
445
445
  }
446
446
  }
447
- `;Ti(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/actions";this.success(`Action created: ${u}/${r}.ts`)}};import{writeFileSync as Pi,mkdirSync as Ri,existsSync as $i}from"fs";import{join as Di}from"path";var Mt=class extends p{name="make:request";description="Create a new FormRequest validation class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a request name.");return}let r=s.endsWith("Request")?s:`${s}Request`,n=r.replace(/Request$/,""),o=t.module||n.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let i=this.moduleDir(o,"dtos");Ri(i,{recursive:!0});let a=Di(i,`${r}.ts`);if($i(a)){this.warn(`Request ${r} already exists.`);return}let l=`import { FormRequest } from '@beeblock/svelar/routing';
447
+ `;Ti(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/actions";this.success(`Action created: ${u}/${r}.ts`)}};import{writeFileSync as Ri,mkdirSync as Pi,existsSync as $i}from"fs";import{join as Di}from"path";var Lt=class extends p{name="make:request";description="Create a new FormRequest validation class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a request name.");return}let r=s.endsWith("Request")?s:`${s}Request`,i=r.replace(/Request$/,""),o=t.module||i.toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${o}" as module. Consider: --module ${o}`);let n=this.moduleDir(o,"dtos");Pi(n,{recursive:!0});let a=Di(n,`${r}.ts`);if($i(a)){this.warn(`Request ${r} already exists.`);return}let l=`import { FormRequest } from '@beeblock/svelar/routing';
448
448
  import { z } from '@beeblock/svelar/validation';
449
449
 
450
450
  export class ${r} extends FormRequest {
@@ -473,7 +473,7 @@ export class ${r} extends FormRequest {
473
473
  return data;
474
474
  }
475
475
  }
476
- `;Pi(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/dtos";this.success(`Request created: ${u}/${r}.ts`)}};import{writeFileSync as ki,mkdirSync as Oi,existsSync as Ai}from"fs";import{join as Ni}from"path";var Lt=class extends p{name="make:plugin";description="Create a new plugin class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a plugin name.");return}let s=t.endsWith("Plugin")?t:`${t}Plugin`,r=this.sharedDir("plugins");Oi(r,{recursive:!0});let n=Ni(r,`${s}.ts`);if(Ai(n)){this.warn(`Plugin ${s} already exists.`);return}let o=s.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,""),i=`import { Plugin } from '@beeblock/svelar/plugins';
476
+ `;Ri(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/dtos";this.success(`Request created: ${u}/${r}.ts`)}};import{writeFileSync as ki,mkdirSync as _i,existsSync as Oi}from"fs";import{join as Ai}from"path";var It=class extends p{name="make:plugin";description="Create a new plugin class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a plugin name.");return}let s=t.endsWith("Plugin")?t:`${t}Plugin`,r=this.sharedDir("plugins");_i(r,{recursive:!0});let i=Ai(r,`${s}.ts`);if(Oi(i)){this.warn(`Plugin ${s} already exists.`);return}let o=s.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,""),n=`import { Plugin } from '@beeblock/svelar/plugins';
477
477
  import type { Container } from '@beeblock/svelar/container';
478
478
 
479
479
  export class ${s} extends Plugin {
@@ -495,7 +495,7 @@ export class ${s} extends Plugin {
495
495
  // Clean up resources
496
496
  }
497
497
  }
498
- `;ki(n,i);let a=this.isDDD()?`src/lib/shared/plugins/${s}.ts`:`src/lib/plugins/${s}.ts`;this.success(`Plugin created: ${a}`)}};import{writeFileSync as _i,mkdirSync as Mi,existsSync as Li}from"fs";import{join as Ii}from"path";var It=class extends p{name="make:task";description="Create a new scheduled task class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a task name.");return}let s=(t.endsWith("Task"),t),r=this.sharedDir("scheduler");Mi(r,{recursive:!0});let n=Ii(r,`${s}.ts`);if(Li(n)){this.warn(`Task ${s} already exists.`);return}let o=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
498
+ `;ki(i,n);let a=this.isDDD()?`src/lib/shared/plugins/${s}.ts`:`src/lib/plugins/${s}.ts`;this.success(`Plugin created: ${a}`)}};import{writeFileSync as Ni,mkdirSync as Mi,existsSync as Li}from"fs";import{join as Ii}from"path";var jt=class extends p{name="make:task";description="Create a new scheduled task class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a task name.");return}let s=(t.endsWith("Task"),t),r=this.sharedDir("scheduler");Mi(r,{recursive:!0});let i=Ii(r,`${s}.ts`);if(Li(i)){this.warn(`Task ${s} already exists.`);return}let o=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
499
499
 
500
500
  export class ${s} extends ScheduledTask {
501
501
  name = '${this.toKebabCase(s)}';
@@ -528,7 +528,7 @@ export class ${s} extends ScheduledTask {
528
528
  console.error('${s} failed:', error.message);
529
529
  }
530
530
  }
531
- `;_i(n,o);let i=this.isDDD()?`src/lib/shared/scheduler/${s}.ts`:`src/lib/scheduler/${s}.ts`;this.success(`Scheduled task created: ${i}`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as ji,mkdirSync as qi,existsSync as Ui}from"fs";import{join as Hi}from"path";var jt=class extends p{name="make:job";description="Create a new queue job class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a job name.");return}let s=(t.endsWith("Job"),t),r=this.sharedDir("jobs");qi(r,{recursive:!0});let n=Hi(r,`${s}.ts`);if(Ui(n)){this.warn(`Job ${s} already exists.`);return}let o=`import { Job } from '@beeblock/svelar/queue';
531
+ `;Ni(i,o);let n=this.isDDD()?`src/lib/shared/scheduler/${s}.ts`:`src/lib/scheduler/${s}.ts`;this.success(`Scheduled task created: ${n}`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as ji,mkdirSync as qi,existsSync as Ui}from"fs";import{join as Hi}from"path";var qt=class extends p{name="make:job";description="Create a new queue job class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a job name.");return}let s=(t.endsWith("Job"),t),r=this.sharedDir("jobs");qi(r,{recursive:!0});let i=Hi(r,`${s}.ts`);if(Ui(i)){this.warn(`Job ${s} already exists.`);return}let o=`import { Job } from '@beeblock/svelar/queue';
532
532
 
533
533
  export class ${s} extends Job {
534
534
  maxAttempts = 3; // Retry up to 3 times
@@ -555,10 +555,10 @@ export class ${s} extends Job {
555
555
  console.log('${s} retrying, attempt', attempt);
556
556
  }
557
557
  }
558
- `;ji(n,o);let i=this.isDDD()?`src/lib/shared/jobs/${s}.ts`:`src/lib/jobs/${s}.ts`;this.success(`Job created: ${i}`)}};import{writeFileSync as Fi,mkdirSync as Bi,existsSync as Ki}from"fs";import{join as Wi}from"path";var qt=class extends p{name="make:command";description="Create a new custom CLI command";arguments=["name"];flags=[{name:"command",description:'The terminal command name (e.g. "app:sync")',type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a command class name. Example: npx svelar make:command SyncUsers");return}let r=s.endsWith("Command")?s:`${s}Command`,n=this.sharedDir("commands");Bi(n,{recursive:!0});let o=Wi(n,`${r}.ts`);if(Ki(o)){this.warn(`Command ${r} already exists.`);return}let i=t.command??this.deriveCommandName(r),a=`import { Command } from '@beeblock/svelar/cli';
558
+ `;ji(i,o);let n=this.isDDD()?`src/lib/shared/jobs/${s}.ts`:`src/lib/jobs/${s}.ts`;this.success(`Job created: ${n}`)}};import{writeFileSync as Fi,mkdirSync as Bi,existsSync as Ki}from"fs";import{join as Wi}from"path";var Ut=class extends p{name="make:command";description="Create a new custom CLI command";arguments=["name"];flags=[{name:"command",description:'The terminal command name (e.g. "app:sync")',type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a command class name. Example: npx svelar make:command SyncUsers");return}let r=s.endsWith("Command")?s:`${s}Command`,i=this.sharedDir("commands");Bi(i,{recursive:!0});let o=Wi(i,`${r}.ts`);if(Ki(o)){this.warn(`Command ${r} already exists.`);return}let n=t.command??this.deriveCommandName(r),a=`import { Command } from '@beeblock/svelar/cli';
559
559
 
560
560
  export class ${r} extends Command {
561
- name = '${i}';
561
+ name = '${n}';
562
562
  description = 'TODO: Describe your command';
563
563
  arguments = ['name']; // Positional args your command accepts
564
564
  flags = [
@@ -569,7 +569,7 @@ export class ${r} extends Command {
569
569
  async handle(args: string[], flags: Record<string, any>): Promise<void> {
570
570
  const name = args[0];
571
571
 
572
- this.info('Running ${i}...');
572
+ this.info('Running ${n}...');
573
573
 
574
574
  // Your command logic here
575
575
  // Use this.bootstrap() if you need database access
@@ -578,7 +578,7 @@ export class ${r} extends Command {
578
578
  this.success('Done!');
579
579
  }
580
580
  }
581
- `;Fi(o,a);let l=this.isDDD()?`src/lib/shared/commands/${r}.ts`:`src/lib/commands/${r}.ts`;this.success(`Command created: ${l}`),this.info(`Command name: ${i}`),this.newLine(),this.info("Your command will be auto-discovered. Run it with:"),this.log(` npx svelar ${i}`)}deriveCommandName(e){return`app:${e.replace(/Command$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}`}};import{writeFileSync as Ji,mkdirSync as Vi,existsSync as zi}from"fs";import{join as Pr}from"path";var Ut=class extends p{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
581
+ `;Fi(o,a);let l=this.isDDD()?`src/lib/shared/commands/${r}.ts`:`src/lib/commands/${r}.ts`;this.success(`Command created: ${l}`),this.info(`Command name: ${n}`),this.newLine(),this.info("Your command will be auto-discovered. Run it with:"),this.log(` npx svelar ${n}`)}deriveCommandName(e){return`app:${e.replace(/Command$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}`}};import{writeFileSync as zi,mkdirSync as Ji,existsSync as Yi}from"fs";import{join as Pr}from"path";var Ht=class extends p{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
582
582
 
583
583
  export default {
584
584
  name: env('APP_NAME', 'Svelar'),
@@ -787,7 +787,7 @@ export default {
787
787
  },
788
788
  },
789
789
  };
790
- `};async handle(e){let t=e[0];if(!t){this.error("Please provide a config file name. Example: npx svelar make:config database"),this.newLine(),this.info("Available presets: app, database, auth, mail, cache, queue, storage, broadcasting, logging");return}let s=Pr(process.cwd(),"config");Vi(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),n=Pr(s,`${r}.ts`);if(zi(n)){this.warn(`Config file config/${r}.ts already exists.`);return}let o=this.templates[r]??this.blankTemplate(r);Ji(n,o),this.success(`Config created: config/${r}.ts`),this.newLine(),this.info("Access it with:"),this.log(` config.get('${r}.key')`)}blankTemplate(e){return`import { env } from 'svelar/config';
790
+ `};async handle(e){let t=e[0];if(!t){this.error("Please provide a config file name. Example: npx svelar make:config database"),this.newLine(),this.info("Available presets: app, database, auth, mail, cache, queue, storage, broadcasting, logging");return}let s=Pr(process.cwd(),"config");Ji(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),i=Pr(s,`${r}.ts`);if(Yi(i)){this.warn(`Config file config/${r}.ts already exists.`);return}let o=this.templates[r]??this.blankTemplate(r);zi(i,o),this.success(`Config created: config/${r}.ts`),this.newLine(),this.info("Access it with:"),this.log(` config.get('${r}.key')`)}blankTemplate(e){return`import { env } from 'svelar/config';
791
791
 
792
792
  export default {
793
793
  // Add your ${e} configuration here
@@ -796,7 +796,7 @@ export default {
796
796
  // env<number>('MY_PORT', 3000)
797
797
  // env<boolean>('MY_FLAG', false)
798
798
  };
799
- `}};import{writeFileSync as Yi,mkdirSync as Gi,existsSync as Qi}from"fs";import{join as Xi}from"path";var Ht=class extends p{name="make:channel";description="Create a new broadcast channel authorization";arguments=["name"];flags=[{name:"presence",alias:"p",description:"Create a presence channel",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a channel name. Example: npx svelar make:channel OrderChannel");return}let r=s.endsWith("Channel")?s:`${s}Channel`,n=this.sharedDir("channels");Gi(n,{recursive:!0});let o=Xi(n,`${r}.ts`);if(Qi(o)){this.warn(`Channel ${r} already exists.`);return}let i=r.replace(/Channel$/,""),a=i.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),l=i.charAt(0).toLowerCase()+i.slice(1)+"Id",u=t.presence,h=`${u?"presence":"private"}-${a}.{${l}}`,m=u?this.presenceTemplate(r,h,l):this.privateTemplate(r,h,l);Yi(o,m);let f=this.isDDD()?"src/lib/shared/channels":"src/lib/channels";this.success(`Channel created: ${f}/${r}.ts`),this.info(`Channel pattern: ${h}`),this.newLine(),this.info("Register it in src/app.ts or a service provider:"),this.log(` import { register${r} } from './${f.replace("src/","")}/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
799
+ `}};import{writeFileSync as Vi,mkdirSync as Gi,existsSync as Qi}from"fs";import{join as Xi}from"path";var Ft=class extends p{name="make:channel";description="Create a new broadcast channel authorization";arguments=["name"];flags=[{name:"presence",alias:"p",description:"Create a presence channel",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a channel name. Example: npx svelar make:channel OrderChannel");return}let r=s.endsWith("Channel")?s:`${s}Channel`,i=this.sharedDir("channels");Gi(i,{recursive:!0});let o=Xi(i,`${r}.ts`);if(Qi(o)){this.warn(`Channel ${r} already exists.`);return}let n=r.replace(/Channel$/,""),a=n.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),l=n.charAt(0).toLowerCase()+n.slice(1)+"Id",u=t.presence,h=`${u?"presence":"private"}-${a}.{${l}}`,m=u?this.presenceTemplate(r,h,l):this.privateTemplate(r,h,l);Vi(o,m);let f=this.isDDD()?"src/lib/shared/channels":"src/lib/channels";this.success(`Channel created: ${f}/${r}.ts`),this.info(`Channel pattern: ${h}`),this.newLine(),this.info("Register it in src/app.ts or a service provider:"),this.log(` import { register${r} } from './${f.replace("src/","")}/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
800
800
 
801
801
  /**
802
802
  * ${e}
@@ -839,7 +839,7 @@ export function register${e}(): void {
839
839
  };
840
840
  });
841
841
  }
842
- `}};import{writeFileSync as Zi,mkdirSync as Rr,existsSync as eo,readFileSync as to}from"fs";import{join as A}from"path";var F=class{static dockerfile(){return`# \u2500\u2500 Svelar Production Dockerfile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
842
+ `}};import{writeFileSync as Zi,mkdirSync as Ue,existsSync as eo,readFileSync as to}from"fs";import{join as R}from"path";var D=class{static dockerfile(){return`# \u2500\u2500 Svelar Production Dockerfile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
843
843
  # Multi-stage build: base \u2192 deps \u2192 builder \u2192 production / development
844
844
  # Generated by: npx svelar make:docker
845
845
 
@@ -923,6 +923,210 @@ services:
923
923
  app:
924
924
  image: \${DOCKER_IMAGE:-${e}}:latest
925
925
  # No build \u2014 uses pre-built image from registry
926
+ `}static postgresInit(){return`-- PostgreSQL init script
927
+ -- Runs once when the data volume is first created.
928
+ -- Add extensions, custom types, or seed data here.
929
+
930
+ -- Common extensions
931
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation (uuid_generate_v4)
932
+ CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- gen_random_uuid, encryption, hashing
933
+ CREATE EXTENSION IF NOT EXISTS "citext"; -- Case-insensitive text (emails, usernames)
934
+ CREATE EXTENSION IF NOT EXISTS "unaccent"; -- Accent-insensitive search (cafe = cafe)
935
+ CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Fast LIKE/ILIKE, fuzzy search, similarity
936
+ CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"; -- Query performance tracking
937
+ `}static postgresConf(){return`# PostgreSQL Configuration
938
+ # Optimized for SvelteKit/Svelar API workload with PgBouncer
939
+ # Generated by: npx svelar make:docker
940
+ #
941
+ # Default tuning: 2GB RAM / 2 vCPUs (typical $12-24/mo droplet)
942
+ # Scale values proportionally for larger instances.
943
+ # Use https://pgtune.leopard.in.ua for precise tuning.
944
+
945
+ # =============================================================================
946
+ # CONNECTIONS
947
+ # =============================================================================
948
+ # With PgBouncer handling pooling, PostgreSQL needs fewer direct connections.
949
+ # PgBouncer's max_db_connections should be less than this.
950
+ max_connections = 100
951
+ superuser_reserved_connections = 3
952
+
953
+ # =============================================================================
954
+ # MEMORY (2GB RAM baseline \u2014 scale proportionally)
955
+ # =============================================================================
956
+ # 25% of RAM for shared buffers
957
+ shared_buffers = 512MB
958
+ # Per-operation sort/hash memory (careful: multiplied by max_connections)
959
+ work_mem = 32MB
960
+ # Memory for VACUUM, CREATE INDEX, ALTER TABLE
961
+ maintenance_work_mem = 256MB
962
+ # WAL writer memory
963
+ wal_buffers = 16MB
964
+ # Estimate of OS + PostgreSQL caches (~75% of RAM)
965
+ effective_cache_size = 1536MB
966
+
967
+ # =============================================================================
968
+ # CHECKPOINT / WAL
969
+ # =============================================================================
970
+ checkpoint_completion_target = 0.9
971
+ max_wal_size = 1GB
972
+ min_wal_size = 256MB
973
+ wal_compression = on
974
+
975
+ # =============================================================================
976
+ # QUERY PLANNER
977
+ # =============================================================================
978
+ # SSD storage \u2014 lower random page cost
979
+ random_page_cost = 1.1
980
+ effective_io_concurrency = 200
981
+ default_statistics_target = 100
982
+
983
+ # =============================================================================
984
+ # PARALLEL QUERY (2 vCPUs baseline)
985
+ # =============================================================================
986
+ max_parallel_workers_per_gather = 1
987
+ max_parallel_workers = 2
988
+ max_parallel_maintenance_workers = 1
989
+ parallel_leader_participation = on
990
+
991
+ # =============================================================================
992
+ # LOGGING
993
+ # =============================================================================
994
+ log_destination = 'stderr'
995
+ logging_collector = on
996
+ log_directory = 'log'
997
+ log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
998
+ log_rotation_age = 1d
999
+ log_rotation_size = 100MB
1000
+
1001
+ # Log slow queries (>1s)
1002
+ log_min_duration_statement = 1000
1003
+ log_checkpoints = on
1004
+ log_connections = on
1005
+ log_disconnections = on
1006
+ log_lock_waits = on
1007
+ log_temp_files = 0
1008
+
1009
+ log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h '
1010
+
1011
+ # =============================================================================
1012
+ # STATISTICS / MONITORING
1013
+ # =============================================================================
1014
+ shared_preload_libraries = 'pg_stat_statements'
1015
+ pg_stat_statements.max = 10000
1016
+ pg_stat_statements.track = all
1017
+ pg_stat_statements.track_utility = on
1018
+ pg_stat_statements.track_planning = on
1019
+
1020
+ track_io_timing = on
1021
+ track_functions = all
1022
+ track_activity_query_size = 2048
1023
+
1024
+ # =============================================================================
1025
+ # AUTOVACUUM
1026
+ # =============================================================================
1027
+ autovacuum = on
1028
+ autovacuum_max_workers = 3
1029
+ autovacuum_naptime = 1min
1030
+ autovacuum_vacuum_threshold = 50
1031
+ autovacuum_vacuum_scale_factor = 0.05
1032
+ autovacuum_analyze_threshold = 50
1033
+ autovacuum_analyze_scale_factor = 0.025
1034
+ autovacuum_vacuum_cost_delay = 2ms
1035
+ autovacuum_vacuum_cost_limit = 1000
1036
+
1037
+ # =============================================================================
1038
+ # LOCALE / ENCODING
1039
+ # =============================================================================
1040
+ lc_messages = 'en_US.utf8'
1041
+ lc_monetary = 'en_US.utf8'
1042
+ lc_numeric = 'en_US.utf8'
1043
+ lc_time = 'en_US.utf8'
1044
+
1045
+ # =============================================================================
1046
+ # SECURITY
1047
+ # =============================================================================
1048
+ password_encryption = scram-sha-256
1049
+ listen_addresses = '*'
1050
+ port = 5432
1051
+ `}static mysqlInit(){return`-- MySQL init script
1052
+ -- Runs once when the data volume is first created.
1053
+ -- Add custom tables, functions, or seed data here.
1054
+
1055
+ -- Ensure UTF-8 support for the default database
1056
+ ALTER DATABASE IF EXISTS \`svelar\`
1057
+ CHARACTER SET = utf8mb4
1058
+ COLLATE = utf8mb4_unicode_ci;
1059
+ `}static pgbouncerIni(){return`; PgBouncer configuration
1060
+ ; Generated by: npx svelar make:docker
1061
+ ; Docs: https://www.pgbouncer.org/config.html
1062
+ ;
1063
+ ; Credentials are read from DATABASE_URL env var in docker-compose.yml.
1064
+ ; The edoburu/pgbouncer image auto-generates the auth file from DATABASE_URL
1065
+ ; at startup \u2014 no static userlist.txt with plain text passwords needed.
1066
+
1067
+ [databases]
1068
+ ; * = use DATABASE_URL from environment (auto-configured by edoburu/pgbouncer image)
1069
+ ; To add more databases, use format: dbname = host=hostname port=port dbname=database
1070
+
1071
+ [pgbouncer]
1072
+ ; Connection settings
1073
+ listen_addr = 0.0.0.0
1074
+ listen_port = 6432
1075
+ unix_socket_dir =
1076
+
1077
+ ; Authentication \u2014 uses auto-generated auth file from DATABASE_URL
1078
+ ; Client \u2192 PgBouncer uses md5 (required: edoburu image writes plain text to userlist)
1079
+ ; PgBouncer \u2192 PostgreSQL uses scram-sha-256 (negotiated automatically by the server)
1080
+ auth_type = md5
1081
+ auth_file = /etc/pgbouncer/userlist.txt
1082
+
1083
+ ; Pool Mode
1084
+ ; transaction = release connection after each transaction (best for web apps)
1085
+ ; session = release after session disconnects
1086
+ ; statement = release after each statement (not recommended with prepared statements)
1087
+ pool_mode = transaction
1088
+
1089
+ ; Pool Size Settings
1090
+ ; default_pool_size: connections per user/database pair
1091
+ default_pool_size = 25
1092
+ min_pool_size = 5
1093
+ reserve_pool_size = 5
1094
+ reserve_pool_timeout = 3
1095
+
1096
+ ; Max connections
1097
+ max_client_conn = 500
1098
+ max_db_connections = 80
1099
+ max_user_connections = 80
1100
+
1101
+ ; Timeouts
1102
+ server_connect_timeout = 15
1103
+ server_idle_timeout = 300
1104
+ server_lifetime = 3600
1105
+ client_idle_timeout = 0
1106
+ client_login_timeout = 60
1107
+ query_timeout = 0
1108
+ query_wait_timeout = 120
1109
+
1110
+ ; Logging
1111
+ log_connections = 1
1112
+ log_disconnections = 1
1113
+ log_pooler_errors = 1
1114
+ stats_period = 60
1115
+ verbose = 0
1116
+
1117
+ ; TCP keepalive
1118
+ tcp_keepalive = 1
1119
+ tcp_keepidle = 30
1120
+ tcp_keepintvl = 10
1121
+ tcp_keepcnt = 3
1122
+
1123
+ ; Server settings
1124
+ server_reset_query = DISCARD ALL
1125
+ server_check_query = SELECT 1
1126
+ server_check_delay = 30
1127
+
1128
+ ; Ignore startup parameters (important for Node.js drivers)
1129
+ ignore_startup_parameters = extra_float_digits,application_name
926
1130
  `}static healthEndpoint(){return`import { json } from '@sveltejs/kit';
927
1131
 
928
1132
  export const GET = () => json({
@@ -930,16 +1134,18 @@ export const GET = () => json({
930
1134
  timestamp: new Date().toISOString(),
931
1135
  uptime: process.uptime(),
932
1136
  });
933
- `}static githubActionsWorkflow(e){return`# \u2500\u2500 Svelar CI/CD \u2014 Build, Push & Deploy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1137
+ `}static githubActionsWorkflow(){return`# \u2500\u2500 Svelar CI/CD \u2014 Build, Push & Deploy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
934
1138
  # Builds on push and PR to main. Deploys only on push.
935
1139
  #
936
1140
  # Required GitHub Secrets:
937
- # DOCKER_USERNAME \u2014 Docker Hub username
938
- # DOCKER_TOKEN \u2014 Docker Hub access token
939
- # DROPLET_HOST \u2014 Droplet IP or hostname
940
- # DROPLET_USER \u2014 SSH user on the droplet (e.g. deploy)
941
- # DROPLET_SSH_KEY \u2014 Private SSH key for the deploy user
942
- # ENV_PROD \u2014 Complete production .env file contents
1141
+ # DOCKER_USERNAME \u2014 Docker Hub username
1142
+ # DOCKER_TOKEN \u2014 Docker Hub access token
1143
+ # DOCKER_IMAGE_NAME \u2014 Docker image name (e.g. myapp)
1144
+ # DROPLET_HOST \u2014 Droplet IP or hostname
1145
+ # DROPLET_USER \u2014 SSH user on the droplet (e.g. deploy)
1146
+ # DROPLET_SSH_KEY \u2014 Private SSH key for the deploy user
1147
+ # DROPLET_PROJECT \u2014 Project directory name on the droplet (e.g. myapp)
1148
+ # ENV_PROD \u2014 Complete production .env file contents
943
1149
  #
944
1150
  # Generated by: npx svelar make:ci
945
1151
 
@@ -952,7 +1158,7 @@ on:
952
1158
  branches: [main]
953
1159
 
954
1160
  env:
955
- DOCKER_IMAGE: \${{ secrets.DOCKER_USERNAME }}/${e}
1161
+ DOCKER_IMAGE: \${{ secrets.DOCKER_USERNAME }}/\${{ secrets.DOCKER_IMAGE_NAME }}
956
1162
 
957
1163
  jobs:
958
1164
  build-and-deploy:
@@ -967,7 +1173,10 @@ jobs:
967
1173
 
968
1174
  - name: Log in to Docker Hub
969
1175
  if: github.event_name == 'push'
970
- run: echo "\${{ secrets.DOCKER_TOKEN }}" | docker login -u "\${{ secrets.DOCKER_USERNAME }}" --password-stdin
1176
+ uses: docker/login-action@v3
1177
+ with:
1178
+ username: \${{ secrets.DOCKER_USERNAME }}
1179
+ password: \${{ secrets.DOCKER_TOKEN }}
971
1180
 
972
1181
  - name: Define tags
973
1182
  run: |
@@ -986,6 +1195,16 @@ jobs:
986
1195
  docker push $DOCKER_IMAGE:$TIMESTAMP_TAG
987
1196
  docker push $DOCKER_IMAGE:latest
988
1197
 
1198
+ - name: Copy compose files to droplet
1199
+ if: github.event_name == 'push'
1200
+ uses: appleboy/scp-action@v0.1.7
1201
+ with:
1202
+ host: \${{ secrets.DROPLET_HOST }}
1203
+ username: \${{ secrets.DROPLET_USER }}
1204
+ key: \${{ secrets.DROPLET_SSH_KEY }}
1205
+ source: "docker-compose.yml,docker-compose.prod.yml,docker/"
1206
+ target: \${{ secrets.DROPLET_PROJECT }}
1207
+
989
1208
  - name: Deploy to droplet
990
1209
  if: github.event_name == 'push'
991
1210
  uses: appleboy/ssh-action@v1
@@ -995,8 +1214,9 @@ jobs:
995
1214
  key: \${{ secrets.DROPLET_SSH_KEY }}
996
1215
  script: |
997
1216
  echo "\${{ secrets.DOCKER_TOKEN }}" | docker login -u "\${{ secrets.DOCKER_USERNAME }}" --password-stdin
998
- cd ${e}/
1217
+ cd \${{ secrets.DROPLET_PROJECT }}/
999
1218
  echo "\${{ secrets.ENV_PROD }}" > .env
1219
+ echo "DOCKER_IMAGE=\${{ secrets.DOCKER_USERNAME }}/\${{ secrets.DOCKER_IMAGE_NAME }}" >> .env
1000
1220
  docker compose -f docker-compose.yml -f docker-compose.prod.yml pull
1001
1221
  docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
1002
1222
  docker image prune -f
@@ -1081,6 +1301,12 @@ if [[ ! -f "$COMPOSE_PROD" ]]; then
1081
1301
  exit 1
1082
1302
  fi
1083
1303
 
1304
+ # Validate paths don't contain spaces (word-splitting would break SSH commands)
1305
+ if [[ "$SSH_KEY_PATH" == *" "* ]]; then
1306
+ err "SSH_KEY_PATH must not contain spaces: $SSH_KEY_PATH"
1307
+ exit 1
1308
+ fi
1309
+
1084
1310
  SSH_ROOT="ssh -o StrictHostKeyChecking=accept-new -i $SSH_KEY_PATH root@$DROPLET_IP"
1085
1311
  SSH_USER="ssh -o StrictHostKeyChecking=accept-new -i $SSH_KEY_PATH $DEPLOY_USER@$DROPLET_IP"
1086
1312
  PUB_KEY_CONTENT=$(cat "$SSH_PUB_KEY")
@@ -1125,8 +1351,8 @@ $SSH_ROOT bash -s <<REMOTE_SCRIPT
1125
1351
  echo "Password set for $DEPLOY_USER."
1126
1352
  fi
1127
1353
 
1128
- # Allow sudo without password for deploy user
1129
- echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$DEPLOY_USER
1354
+ # Allow passwordless sudo for Docker commands only (principle of least privilege)
1355
+ echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:/usr/bin/docker,/usr/bin/docker-compose,/usr/local/bin/docker-compose" > /etc/sudoers.d/$DEPLOY_USER
1130
1356
  chmod 440 /etc/sudoers.d/$DEPLOY_USER
1131
1357
  REMOTE_SCRIPT
1132
1358
 
@@ -1212,6 +1438,13 @@ scp -o StrictHostKeyChecking=accept-new -i "$SSH_KEY_PATH" \\
1212
1438
  scp -o StrictHostKeyChecking=accept-new -i "$SSH_KEY_PATH" \\
1213
1439
  "$COMPOSE_PROD" "$DEPLOY_USER@$DROPLET_IP:$REMOTE_DIR/docker-compose.prod.yml"
1214
1440
 
1441
+ # Copy docker config directory (postgres, pgbouncer configs)
1442
+ if [[ -d "docker" ]]; then
1443
+ scp -o StrictHostKeyChecking=accept-new -i "$SSH_KEY_PATH" -r \\
1444
+ docker "$DEPLOY_USER@$DROPLET_IP:$REMOTE_DIR/"
1445
+ log "Docker config files copied (docker/ directory)."
1446
+ fi
1447
+
1215
1448
  log "Compose files copied (.env is managed by CI/CD via ENV_PROD secret)."
1216
1449
 
1217
1450
  # \u2500\u2500 Step 6: Configure firewall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
@@ -1292,7 +1525,7 @@ COMPOSE_FILE=docker-compose.prod.yml
1292
1525
 
1293
1526
  # Password for the deploy user (optional, for emergency console access)
1294
1527
  DEPLOY_USER_PASSWORD=
1295
- `}};var Ft=class extends p{name="make:docker";description="Scaffold Docker deployment files (Dockerfile, docker-compose, PM2, health endpoint)";arguments=[];flags=[{name:"db",alias:"d",description:"Database driver: postgres, mysql, sqlite (default: postgres)",type:"string"},{name:"image",alias:"i",description:"Docker image name (default: package.json name)",type:"string"},{name:"registry",description:"Docker registry prefix (default: Docker Hub)",type:"string"},{name:"port",description:"Production port (default: 3000)",type:"string"},{name:"dev-port",description:"Development port (default: 5173)",type:"string"},{name:"soketi",alias:"s",description:"Include Soketi WebSocket server",type:"boolean"},{name:"redis",alias:"r",description:"Include Redis service",type:"boolean"},{name:"gotenberg",alias:"g",description:"Include Gotenberg PDF service (default: true)",type:"boolean"},{name:"rustfs",description:"Include RustFS S3-compatible object storage (default: true)",type:"boolean"},{name:"meilisearch",alias:"m",description:"Include Meilisearch full-text search engine",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.db??"postgres",n=t.soketi??!0,o=t.redis??!0,i=t.gotenberg??!0,a=t.rustfs??!0,l=t.meilisearch??!1,u=t.force??!1,d=this.resolveAppName(s),h=t.image??d,m=t.registry,f=m?`${m}/${h}`:h,E=["postgres","mysql","sqlite"];if(!E.includes(r)){this.error(`Unknown database driver: ${r}. Use one of: ${E.join(", ")}`);return}let T=A(s,"src","routes","api","health");Rr(T,{recursive:!0});let be=[{path:A(s,"Dockerfile"),content:F.dockerfile(),label:"Dockerfile"},{path:A(s,"docker-compose.yml"),content:this.composeTemplate(r,n,o,i,a,l),label:"docker-compose.yml"},{path:A(s,"docker-compose.dev.yml"),content:F.composeDevOverride(),label:"docker-compose.dev.yml"},{path:A(s,"docker-compose.prod.yml"),content:F.composeProdOverride(f),label:"docker-compose.prod.yml"},{path:A(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:A(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"},{path:A(T,"+server.ts"),content:F.healthEndpoint(),label:"src/routes/api/health/+server.ts"}],O=0,z=0;for(let $ of be){if(eo($.path)&&!u){this.warn(`${$.label} already exists (use --force to overwrite)`),z++;continue}Zi($.path,$.content),this.success(`Created ${$.label}`),O++}if(r!=="sqlite"){let $=A(s,"docker");Rr($,{recursive:!0})}this.newLine(),O>0?this.info(`${O} file(s) created${z>0?`, ${z} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Quick start:"),this.log(" # Development (with hot-reload)"),this.log(" npx svelar dev:up"),this.newLine(),this.log(" # Production (local build)"),this.log(" docker compose up -d --build"),this.newLine(),this.log(" # Run migrations inside the container"),this.log(" docker compose exec app npx svelar migrate"),this.newLine(),this.log(" # View logs"),this.log(" npx svelar dev:logs"),this.newLine(),this.log(" # Stop services"),this.log(" npx svelar dev:down"),this.newLine(),this.info("Make sure to update .env with production values before deploying.")}resolveAppName(e){try{let t=JSON.parse(to(A(e,"package.json"),"utf-8"));if(t.name&&typeof t.name=="string")return t.name.replace(/^@[^/]+\//,"")}catch{}return"svelar-app"}composeTemplate(e,t,s,r,n=!0,o=!1){let i=[];i.push("# \u2500\u2500 Svelar Docker Compose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),i.push("# Generated by: npx svelar make:docker"),i.push("#"),i.push("# Usage:"),i.push("# docker compose up -d --build # Start all services"),i.push("# docker compose exec app npx svelar migrate # Run migrations"),i.push("# docker compose logs -f app # View app logs"),i.push("# docker compose down # Stop all services"),i.push(""),i.push("services:"),i.push(" app:"),i.push(" build: ."),i.push(" restart: unless-stopped"),i.push(" ports:"),i.push(' - "${APP_PORT:-3000}:3000"'),i.push(" env_file: .env"),i.push(" environment:"),i.push(" - NODE_ENV=production"),e==="postgres"?(i.push(" - DB_HOST=postgres"),i.push(" - DB_PORT=5432")):e==="mysql"&&(i.push(" - DB_HOST=mysql"),i.push(" - DB_PORT=3306")),s&&(i.push(" - REDIS_HOST=redis"),i.push(" - REDIS_PORT=6379"),i.push(" - REDIS_PASSWORD=${REDIS_PASSWORD:-svelarsecret}"),i.push(" - QUEUE_DRIVER=redis")),t&&(i.push(" - PUSHER_HOST=soketi"),i.push(" - PUSHER_PORT=6001")),r&&i.push(" - GOTENBERG_URL=http://gotenberg:3000"),n&&(i.push(" - S3_ENDPOINT=http://rustfs:9000"),i.push(" - S3_ACCESS_KEY=${RUSTFS_ROOT_USER:-svelar}"),i.push(" - S3_SECRET_KEY=${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),i.push(" - S3_BUCKET=${S3_BUCKET:-svelar}"),i.push(" - S3_REGION=us-east-1"),i.push(" - STORAGE_DISK=s3")),o&&(i.push(" - MEILISEARCH_HOST=http://meilisearch:7700"),i.push(" - MEILISEARCH_KEY=${MEILI_MASTER_KEY:-svelar-meili-master-key}"));let a=[];if(e==="postgres"&&a.push("postgres"),e==="mysql"&&a.push("mysql"),s&&a.push("redis"),t&&a.push("soketi"),r&&a.push("gotenberg"),n&&a.push("rustfs"),o&&a.push("meilisearch"),a.length>0){i.push(" depends_on:");for(let l of a)i.push(` ${l}:`),i.push(" condition: service_healthy")}return i.push(" volumes:"),i.push(" - app_storage:/app/storage"),e==="postgres"&&(i.push(""),i.push(" postgres:"),i.push(" image: postgres:16-alpine"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" environment:"),i.push(" POSTGRES_DB: ${DB_NAME:-svelar}"),i.push(" POSTGRES_USER: ${DB_USER:-svelar}"),i.push(" POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}"),i.push(" volumes:"),i.push(" - pgdata:/var/lib/postgresql/data"),i.push(" healthcheck:"),i.push(' test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-svelar}"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),e==="mysql"&&(i.push(""),i.push(" mysql:"),i.push(" image: mysql:8.0"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" environment:"),i.push(" MYSQL_DATABASE: ${DB_NAME:-svelar}"),i.push(" MYSQL_USER: ${DB_USER:-svelar}"),i.push(" MYSQL_PASSWORD: ${DB_PASSWORD:-secret}"),i.push(" MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}"),i.push(" volumes:"),i.push(" - mysqldata:/var/lib/mysql"),i.push(" healthcheck:"),i.push(' test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),s&&(i.push(""),i.push(" redis:"),i.push(" image: redis:7-alpine"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" command: redis-server --requirepass ${REDIS_PASSWORD:-svelarsecret}"),i.push(" volumes:"),i.push(" - redisdata:/data"),i.push(" healthcheck:"),i.push(' test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-svelarsecret}", "ping"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),t&&(i.push(""),i.push(" soketi:"),i.push(" image: quay.io/soketi/soketi:1.6-16-debian"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" # Expose 6001 to host only if clients connect directly (uncomment below)"),i.push(" # ports:"),i.push(' # - "${SOKETI_PORT:-6001}:6001"'),i.push(" environment:"),i.push(' SOKETI_DEBUG: "${SOKETI_DEBUG:-0}"'),i.push(" SOKETI_DEFAULT_APP_ID: ${PUSHER_APP_ID}"),i.push(" SOKETI_DEFAULT_APP_KEY: ${PUSHER_KEY}"),i.push(" SOKETI_DEFAULT_APP_SECRET: ${PUSHER_SECRET}"),i.push(' SOKETI_DEFAULT_APP_MAX_CONNS: "${SOKETI_MAX_CONNS:-1000}"'),i.push(' SOKETI_DEFAULT_APP_ENABLE_CLIENT_MESSAGES: "true"'),i.push(' SOKETI_DEFAULT_APP_MAX_BACKEND_EVENTS_PER_SEC: "-1"'),i.push(" healthcheck:"),i.push(' test: ["CMD", "wget", "-qO-", "http://localhost:6001"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 3")),r&&(i.push(""),i.push(" gotenberg:"),i.push(" image: gotenberg/gotenberg:8"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" environment:"),i.push(' CHROMIUM_DISABLE_JAVASCRIPT: "false"'),i.push(' CHROMIUM_ALLOW_LIST: "file:///tmp/.*"'),i.push(' API_TIMEOUT: "${GOTENBERG_TIMEOUT:-60s}"'),i.push(' LOG_LEVEL: "${GOTENBERG_LOG_LEVEL:-info}"'),i.push(" healthcheck:"),i.push(' test: ["CMD", "curl", "-f", "http://localhost:3000/health"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),n&&(i.push(""),i.push(" rustfs:"),i.push(" image: rustfs/rustfs:latest"),i.push(" restart: unless-stopped"),i.push(" ports:"),i.push(' - "${RUSTFS_CONSOLE_PORT:-9001}:9001" # Admin console (protect with firewall)'),i.push(" environment:"),i.push(" RUSTFS_ROOT_USER: ${RUSTFS_ROOT_USER:-svelar}"),i.push(" RUSTFS_ROOT_PASSWORD: ${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),i.push(' command: server /data --console-address ":9001"'),i.push(" volumes:"),i.push(" - rustfs_data:/data"),i.push(" healthcheck:"),i.push(' test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),o&&(i.push(""),i.push(" meilisearch:"),i.push(" image: getmeili/meilisearch:v1.13"),i.push(" restart: unless-stopped"),i.push(" # No ports exposed \u2014 only reachable by app via Docker network"),i.push(" # Uncomment below to access the dashboard from the host"),i.push(" # ports:"),i.push(' # - "${MEILI_PORT:-7700}:7700"'),i.push(" environment:"),i.push(" MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-svelar-meili-master-key}"),i.push(" MEILI_ENV: production"),i.push(" MEILI_DB_PATH: /meili_data"),i.push(' MEILI_NO_ANALYTICS: "true"'),i.push(" volumes:"),i.push(" - meili_data:/meili_data"),i.push(" healthcheck:"),i.push(' test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"]'),i.push(" interval: 10s"),i.push(" timeout: 5s"),i.push(" retries: 5")),i.push(""),i.push("volumes:"),i.push(" app_storage:"),e==="postgres"&&i.push(" pgdata:"),e==="mysql"&&i.push(" mysqldata:"),s&&i.push(" redisdata:"),n&&i.push(" rustfs_data:"),o&&i.push(" meili_data:"),i.push(""),i.join(`
1528
+ `}};var Bt=class extends p{name="make:docker";description="Scaffold Docker deployment files (Dockerfile, docker-compose, PM2, health endpoint)";arguments=[];flags=[{name:"db",alias:"d",description:"Database driver: postgres, mysql, sqlite (default: postgres)",type:"string"},{name:"image",alias:"i",description:"Docker image name (default: package.json name)",type:"string"},{name:"registry",description:"Docker registry prefix (default: Docker Hub)",type:"string"},{name:"port",description:"Production port (default: 3000)",type:"string"},{name:"dev-port",description:"Development port (default: 5173)",type:"string"},{name:"soketi",alias:"s",description:"Include Soketi WebSocket server",type:"boolean"},{name:"redis",alias:"r",description:"Include Redis service",type:"boolean"},{name:"gotenberg",alias:"g",description:"Include Gotenberg PDF service (default: true)",type:"boolean"},{name:"rustfs",description:"Include RustFS S3-compatible object storage (default: true)",type:"boolean"},{name:"meilisearch",alias:"m",description:"Include Meilisearch full-text search engine",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.db??"postgres",i=t.soketi??!0,o=t.redis??!0,n=t.gotenberg??!0,a=t.rustfs??!0,l=t.meilisearch??!1,u=t.force??!1,d=this.resolveAppName(s),h=t.image??d,m=t.registry,f=m?`${m}/${h}`:h,E=["postgres","mysql","sqlite"];if(!E.includes(r)){this.error(`Unknown database driver: ${r}. Use one of: ${E.join(", ")}`);return}let T=R(s,"src","routes","api","health");Ue(T,{recursive:!0}),r==="postgres"?(Ue(R(s,"docker","postgres"),{recursive:!0}),Ue(R(s,"docker","pgbouncer"),{recursive:!0})):r==="mysql"&&Ue(R(s,"docker","mysql"),{recursive:!0});let M=[{path:R(s,"Dockerfile"),content:D.dockerfile(),label:"Dockerfile"},{path:R(s,"docker-compose.yml"),content:this.composeTemplate(r,i,o,n,a,l),label:"docker-compose.yml"},{path:R(s,"docker-compose.dev.yml"),content:D.composeDevOverride(),label:"docker-compose.dev.yml"},{path:R(s,"docker-compose.prod.yml"),content:D.composeProdOverride(f),label:"docker-compose.prod.yml"},{path:R(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:R(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"},{path:R(T,"+server.ts"),content:D.healthEndpoint(),label:"src/routes/api/health/+server.ts"}];r==="postgres"?(M.push({path:R(s,"docker","postgres","postgresql.conf"),content:D.postgresConf(),label:"docker/postgres/postgresql.conf"}),M.push({path:R(s,"docker","postgres","init.sql"),content:D.postgresInit(),label:"docker/postgres/init.sql"}),M.push({path:R(s,"docker","pgbouncer","pgbouncer.ini"),content:D.pgbouncerIni(),label:"docker/pgbouncer/pgbouncer.ini"})):r==="mysql"&&M.push({path:R(s,"docker","mysql","init.sql"),content:D.mysqlInit(),label:"docker/mysql/init.sql"});let O=0,V=0;for(let L of M){if(eo(L.path)&&!u){this.warn(`${L.label} already exists (use --force to overwrite)`),V++;continue}Zi(L.path,L.content),this.success(`Created ${L.label}`),O++}this.newLine(),O>0?this.info(`${O} file(s) created${V>0?`, ${V} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Quick start:"),this.log(" # Development (with hot-reload)"),this.log(" npx svelar dev:up"),this.newLine(),this.log(" # Production (local build)"),this.log(" docker compose up -d --build"),this.newLine(),this.log(" # Run migrations inside the container"),this.log(" docker compose exec app npx svelar migrate"),this.newLine(),this.log(" # View logs"),this.log(" npx svelar dev:logs"),this.newLine(),this.log(" # Stop services"),this.log(" npx svelar dev:down"),this.newLine(),this.info("Make sure to update .env with production values before deploying.")}resolveAppName(e){try{let t=JSON.parse(to(R(e,"package.json"),"utf-8"));if(t.name&&typeof t.name=="string")return t.name.replace(/^@[^/]+\//,"")}catch{}return"svelar-app"}composeTemplate(e,t,s,r,i=!0,o=!1){let n=[];n.push("# \u2500\u2500 Svelar Docker Compose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),n.push("# Generated by: npx svelar make:docker"),n.push("#"),n.push("# Usage:"),n.push("# docker compose up -d --build # Start all services"),n.push("# docker compose exec app npx svelar migrate # Run migrations"),n.push("# docker compose logs -f app # View app logs"),n.push("# docker compose down # Stop all services"),n.push(""),n.push("services:"),n.push(" app:"),n.push(" build: ."),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${APP_PORT:-3000}:3000"'),n.push(" env_file: .env"),n.push(" environment:"),n.push(" - NODE_ENV=production"),e==="postgres"?(n.push(" - DB_HOST=pgbouncer"),n.push(" - DB_PORT=6432")):e==="mysql"&&(n.push(" - DB_HOST=mysql"),n.push(" - DB_PORT=3306")),s&&(n.push(" - REDIS_HOST=redis"),n.push(" - REDIS_PORT=6379"),n.push(" - REDIS_PASSWORD=${REDIS_PASSWORD:-svelarsecret}"),n.push(" - QUEUE_DRIVER=redis")),t&&(n.push(" - PUSHER_HOST=soketi"),n.push(" - PUSHER_PORT=6001")),r&&n.push(" - GOTENBERG_URL=http://gotenberg:3000"),i&&(n.push(" - S3_ENDPOINT=http://rustfs:9000"),n.push(" - S3_ACCESS_KEY=${RUSTFS_ROOT_USER:-svelar}"),n.push(" - S3_SECRET_KEY=${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),n.push(" - S3_BUCKET=${S3_BUCKET:-svelar}"),n.push(" - S3_REGION=us-east-1"),n.push(" - STORAGE_DISK=s3")),o&&(n.push(" - MEILISEARCH_HOST=http://meilisearch:7700"),n.push(" - MEILISEARCH_KEY=${MEILI_MASTER_KEY:-svelar-meili-master-key}"));let a=[];if(e==="postgres"&&a.push("pgbouncer"),e==="mysql"&&a.push("mysql"),s&&a.push("redis"),t&&a.push("soketi"),r&&a.push("gotenberg"),i&&a.push("rustfs"),o&&a.push("meilisearch"),a.length>0){n.push(" depends_on:");for(let l of a)n.push(` ${l}:`),n.push(" condition: service_healthy")}return n.push(" volumes:"),n.push(" - app_storage:/app/storage"),n.push(" healthcheck:"),n.push(' test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]'),n.push(" interval: 30s"),n.push(" timeout: 5s"),n.push(" start_period: 15s"),n.push(" retries: 3"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: ${APP_MEMORY_LIMIT:-1G}"),n.push(" pids: 200"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "10m"'),n.push(' max-file: "3"'),e==="postgres"&&(n.push(""),n.push(" postgres:"),n.push(" image: postgres:17-alpine"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable via PgBouncer on the Docker network"),n.push(" command: postgres -c config_file=/etc/postgresql/postgresql.conf"),n.push(" environment:"),n.push(" POSTGRES_DB: ${DB_NAME:-svelar}"),n.push(" POSTGRES_USER: ${DB_USER:-svelar}"),n.push(" POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}"),n.push(" volumes:"),n.push(" - pgdata:/var/lib/postgresql/data"),n.push(" - ./docker/postgres/postgresql.conf:/etc/postgresql/postgresql.conf:ro"),n.push(" - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:ro"),n.push(" healthcheck:"),n.push(' test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-svelar} -d ${DB_NAME:-svelar}"]'),n.push(" interval: 30s"),n.push(" timeout: 10s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: ${POSTGRES_MEMORY_LIMIT:-1G}"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "10m"'),n.push(' max-file: "3"'),n.push(""),n.push(" pgbouncer:"),n.push(" image: edoburu/pgbouncer:v1.25.1-p0"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" # Expose 6432 to host only for direct debugging (uncomment below)"),n.push(" # ports:"),n.push(' # - "6432:6432"'),n.push(" environment:"),n.push(" DATABASE_URL: postgres://${DB_USER:-svelar}:${DB_PASSWORD:-secret}@postgres:5432/${DB_NAME:-svelar}"),n.push(" volumes:"),n.push(" - ./docker/pgbouncer/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro"),n.push(" depends_on:"),n.push(" postgres:"),n.push(" condition: service_healthy"),n.push(" healthcheck:"),n.push(' test: ["CMD", "pg_isready", "-h", "localhost", "-p", "6432"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: 128M"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),e==="mysql"&&(n.push(""),n.push(" mysql:"),n.push(" image: mysql:8.0"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" environment:"),n.push(" MYSQL_DATABASE: ${DB_NAME:-svelar}"),n.push(" MYSQL_USER: ${DB_USER:-svelar}"),n.push(" MYSQL_PASSWORD: ${DB_PASSWORD:-secret}"),n.push(" MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}"),n.push(" volumes:"),n.push(" - mysqldata:/var/lib/mysql"),n.push(" - ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro"),n.push(" healthcheck:"),n.push(' test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: ${MYSQL_MEMORY_LIMIT:-1G}"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "10m"'),n.push(' max-file: "3"')),s&&(n.push(""),n.push(" redis:"),n.push(" image: redis:7-alpine"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" command: redis-server --requirepass ${REDIS_PASSWORD:-svelarsecret}"),n.push(" volumes:"),n.push(" - redisdata:/data"),n.push(" healthcheck:"),n.push(' test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-svelarsecret}", "ping"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: ${REDIS_MEMORY_LIMIT:-256M}"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),t&&(n.push(""),n.push(" soketi:"),n.push(" image: quay.io/soketi/soketi:1.6-16-debian"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" # Expose 6001 to host only if clients connect directly (uncomment below)"),n.push(" # ports:"),n.push(' # - "${SOKETI_PORT:-6001}:6001"'),n.push(" environment:"),n.push(' SOKETI_DEBUG: "${SOKETI_DEBUG:-0}"'),n.push(" SOKETI_DEFAULT_APP_ID: ${PUSHER_APP_ID}"),n.push(" SOKETI_DEFAULT_APP_KEY: ${PUSHER_KEY}"),n.push(" SOKETI_DEFAULT_APP_SECRET: ${PUSHER_SECRET}"),n.push(' SOKETI_DEFAULT_APP_MAX_CONNS: "${SOKETI_MAX_CONNS:-1000}"'),n.push(' SOKETI_DEFAULT_APP_ENABLE_CLIENT_MESSAGES: "true"'),n.push(' SOKETI_DEFAULT_APP_MAX_BACKEND_EVENTS_PER_SEC: "-1"'),n.push(" healthcheck:"),n.push(' test: ["CMD", "wget", "-qO-", "http://localhost:6001"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 3"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: 256M"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),r&&(n.push(""),n.push(" gotenberg:"),n.push(" image: gotenberg/gotenberg:8"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" environment:"),n.push(' CHROMIUM_DISABLE_JAVASCRIPT: "false"'),n.push(' CHROMIUM_ALLOW_LIST: "file:///tmp/.*"'),n.push(' API_TIMEOUT: "${GOTENBERG_TIMEOUT:-60s}"'),n.push(' LOG_LEVEL: "${GOTENBERG_LOG_LEVEL:-info}"'),n.push(" healthcheck:"),n.push(' test: ["CMD", "curl", "-f", "http://localhost:3000/health"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: 512M"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),i&&(n.push(""),n.push(" rustfs:"),n.push(" image: rustfs/rustfs:latest"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${RUSTFS_CONSOLE_PORT:-9001}:9001" # Admin console (protect with firewall)'),n.push(" environment:"),n.push(" RUSTFS_ROOT_USER: ${RUSTFS_ROOT_USER:-svelar}"),n.push(" RUSTFS_ROOT_PASSWORD: ${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),n.push(' command: server /data --console-address ":9001"'),n.push(" volumes:"),n.push(" - rustfs_data:/data"),n.push(" healthcheck:"),n.push(' test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: 512M"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),o&&(n.push(""),n.push(" meilisearch:"),n.push(" image: getmeili/meilisearch:v1.13"),n.push(" restart: unless-stopped"),n.push(" # No ports exposed \u2014 only reachable by app via Docker network"),n.push(" # Uncomment below to access the dashboard from the host"),n.push(" # ports:"),n.push(' # - "${MEILI_PORT:-7700}:7700"'),n.push(" environment:"),n.push(" MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-svelar-meili-master-key}"),n.push(" MEILI_ENV: production"),n.push(" MEILI_DB_PATH: /meili_data"),n.push(' MEILI_NO_ANALYTICS: "true"'),n.push(" volumes:"),n.push(" - meili_data:/meili_data"),n.push(" healthcheck:"),n.push(' test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5"),n.push(" deploy:"),n.push(" resources:"),n.push(" limits:"),n.push(" memory: 512M"),n.push(" logging:"),n.push(" driver: json-file"),n.push(" options:"),n.push(' max-size: "5m"'),n.push(' max-file: "3"')),n.push(""),n.push("volumes:"),n.push(" app_storage:"),e==="postgres"&&n.push(" pgdata:"),e==="mysql"&&n.push(" mysqldata:"),s&&n.push(" redisdata:"),i&&n.push(" rustfs_data:"),o&&n.push(" meili_data:"),n.push(""),n.join(`
1296
1529
  `)}dockerignoreTemplate(){return`# Dependencies
1297
1530
  node_modules
1298
1531
 
@@ -1415,7 +1648,7 @@ module.exports = {
1415
1648
  },
1416
1649
  ],
1417
1650
  };
1418
- `}};import{writeFileSync as so,mkdirSync as ro,existsSync as $r}from"fs";import{join as L}from"path";var Bt=class extends p{name="make:broadcasting";description="Scaffold broadcasting routes (Pusher auth, SSE stream, client init)";arguments=[];flags=[{name:"sse",description:"Only scaffold SSE routes (no Pusher auth)",type:"boolean"},{name:"pusher",description:"Only scaffold Pusher/Soketi routes",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,n=t.sse??!1,o=t.pusher??!1,i=!n&&!o,a=[];(i||o)&&a.push({path:L(s,"src/routes/api/broadcasting/auth/+server.ts"),content:this.pusherAuthRoute(),label:"src/routes/api/broadcasting/auth/+server.ts",dirs:[L(s,"src/routes/api/broadcasting/auth")]}),(i||n)&&a.push({path:L(s,"src/routes/api/broadcasting/[channel]/+server.ts"),content:this.sseRoute(),label:"src/routes/api/broadcasting/[channel]/+server.ts",dirs:[L(s,"src/routes/api/broadcasting/[channel]")]}),a.push({path:L(s,"src/lib/broadcasting.ts"),content:i||o?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[L(s,"src/lib")]});let l=L(s,"config/broadcasting.ts");$r(l)||a.push({path:l,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[L(s,"config")]});let u=0,d=0;for(let h of a){if($r(h.path)&&!r){this.warn(`${h.label} already exists (use --force to overwrite)`),d++;continue}for(let m of h.dirs)ro(m,{recursive:!0});so(h.path,h.content),this.success(`Created ${h.label}`),u++}this.newLine(),u>0?this.info(`${u} file(s) created${d>0?`, ${d} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Next steps:"),i||o?(this.log(" 1. Install pusher-js: npm install pusher-js"),this.log(" 2. Add Pusher env vars to .env:"),this.log(" BROADCAST_DRIVER=pusher"),this.log(" PUSHER_KEY=svelar-key"),this.log(" PUSHER_SECRET=svelar-secret"),this.log(" PUSHER_APP_ID=svelar-app"),this.log(' PUSHER_HOST=localhost # or "soketi" in Docker'),this.log(" PUSHER_PORT=6001"),this.log(" 3. Import broadcasting in your root layout:"),this.log(" import '$lib/broadcasting';")):(this.log(" 1. Import broadcasting in your root layout:"),this.log(" import '$lib/broadcasting';")),this.log(" 4. Register channel authorizations in src/app.ts"),this.log(" 5. Run 'npx svelar make:docker' for Soketi in Docker Compose")}pusherAuthRoute(){return`/**
1651
+ `}};import{writeFileSync as so,mkdirSync as ro,existsSync as $r}from"fs";import{join as j}from"path";var Kt=class extends p{name="make:broadcasting";description="Scaffold broadcasting routes (Pusher auth, SSE stream, client init)";arguments=[];flags=[{name:"sse",description:"Only scaffold SSE routes (no Pusher auth)",type:"boolean"},{name:"pusher",description:"Only scaffold Pusher/Soketi routes",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,i=t.sse??!1,o=t.pusher??!1,n=!i&&!o,a=[];(n||o)&&a.push({path:j(s,"src/routes/api/broadcasting/auth/+server.ts"),content:this.pusherAuthRoute(),label:"src/routes/api/broadcasting/auth/+server.ts",dirs:[j(s,"src/routes/api/broadcasting/auth")]}),(n||i)&&a.push({path:j(s,"src/routes/api/broadcasting/[channel]/+server.ts"),content:this.sseRoute(),label:"src/routes/api/broadcasting/[channel]/+server.ts",dirs:[j(s,"src/routes/api/broadcasting/[channel]")]}),a.push({path:j(s,"src/lib/broadcasting.ts"),content:n||o?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[j(s,"src/lib")]});let l=j(s,"config/broadcasting.ts");$r(l)||a.push({path:l,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[j(s,"config")]});let u=0,d=0;for(let h of a){if($r(h.path)&&!r){this.warn(`${h.label} already exists (use --force to overwrite)`),d++;continue}for(let m of h.dirs)ro(m,{recursive:!0});so(h.path,h.content),this.success(`Created ${h.label}`),u++}this.newLine(),u>0?this.info(`${u} file(s) created${d>0?`, ${d} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Next steps:"),n||o?(this.log(" 1. Install pusher-js: npm install pusher-js"),this.log(" 2. Add Pusher env vars to .env:"),this.log(" BROADCAST_DRIVER=pusher"),this.log(" PUSHER_KEY=svelar-key"),this.log(" PUSHER_SECRET=svelar-secret"),this.log(" PUSHER_APP_ID=svelar-app"),this.log(' PUSHER_HOST=localhost # or "soketi" in Docker'),this.log(" PUSHER_PORT=6001"),this.log(" 3. Import broadcasting in your root layout:"),this.log(" import '$lib/broadcasting';")):(this.log(" 1. Import broadcasting in your root layout:"),this.log(" import '$lib/broadcasting';")),this.log(" 4. Register channel authorizations in src/app.ts"),this.log(" 5. Run 'npx svelar make:docker' for Soketi in Docker Compose")}pusherAuthRoute(){return`/**
1419
1652
  * Pusher/Soketi Channel Authorization Endpoint
1420
1653
  *
1421
1654
  * This route authenticates channel subscriptions from pusher-js.
@@ -1569,7 +1802,7 @@ export default {
1569
1802
  },
1570
1803
  },
1571
1804
  };
1572
- `}};import{writeFileSync as no,mkdirSync as io,existsSync as oo}from"fs";import{join as R}from"path";var Kt=class extends p{name="make:dashboard";description="Scaffold admin dashboard routes (health, queue, scheduler, logs)";arguments=[];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,n=[{path:R(s,"src/routes/api/admin/health/+server.ts"),content:this.healthServerTemplate(),label:"api/admin/health/+server.ts"},{path:R(s,"src/routes/api/admin/queue/+server.ts"),content:this.queueServerTemplate(),label:"api/admin/queue/+server.ts"},{path:R(s,"src/routes/api/admin/queue/[id]/retry/+server.ts"),content:this.queueRetryServerTemplate(),label:"api/admin/queue/[id]/retry/+server.ts"},{path:R(s,"src/routes/api/admin/queue/[id]/+server.ts"),content:this.queueDeleteServerTemplate(),label:"api/admin/queue/[id]/+server.ts"},{path:R(s,"src/routes/api/admin/scheduler/+server.ts"),content:this.schedulerServerTemplate(),label:"api/admin/scheduler/+server.ts"},{path:R(s,"src/routes/api/admin/scheduler/[name]/run/+server.ts"),content:this.schedulerRunServerTemplate(),label:"api/admin/scheduler/[name]/run/+server.ts"},{path:R(s,"src/routes/api/admin/scheduler/[name]/toggle/+server.ts"),content:this.schedulerToggleServerTemplate(),label:"api/admin/scheduler/[name]/toggle/+server.ts"},{path:R(s,"src/routes/api/admin/logs/+server.ts"),content:this.logsServerTemplate(),label:"api/admin/logs/+server.ts"},{path:R(s,"src/routes/api/admin/logs/tail/+server.ts"),content:this.logsTailServerTemplate(),label:"api/admin/logs/tail/+server.ts"},{path:R(s,"src/routes/api/admin/stats/+server.ts"),content:this.statsServerTemplate(),label:"api/admin/stats/+server.ts"},{path:R(s,"src/routes/admin/dashboard/+page.server.ts"),content:this.dashboardPageServerTemplate(),label:"admin/dashboard/+page.server.ts"},{path:R(s,"src/routes/admin/dashboard/+page.svelte"),content:this.dashboardPageSvelteTemplate(),label:"admin/dashboard/+page.svelte"}],o=0,i=0;for(let a of n){let l=a.path.substring(0,a.path.lastIndexOf("/"));if(io(l,{recursive:!0}),oo(a.path)&&!r){this.warn(`${a.label} already exists (use --force to overwrite)`),i++;continue}no(a.path,a.content),this.success(`Created ${a.label}`),o++}this.newLine(),o>0?this.info(`${o} file(s) created${i>0?`, ${i} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Setup instructions:"),this.log(" 1. Import dashboard modules in your app:"),this.log(' import { ScheduleMonitor } from "svelar/scheduler/ScheduleMonitor";'),this.log(' import { JobMonitor } from "svelar/queue/JobMonitor";'),this.log(' import { LogViewer } from "svelar/logging/LogViewer";'),this.newLine(),this.log(" 2. Configure auth middleware on admin routes:"),this.log(' - Replace "// TODO: Add admin middleware check" with your auth logic'),this.log(' - Example: if (!event.locals.user?.isAdmin) return error(403, "Forbidden");'),this.newLine(),this.log(" 3. Access the dashboard:"),this.log(" - Navigate to: /admin/dashboard"),this.newLine(),this.log(" 4. API endpoints available at:"),this.log(" - GET /api/admin/health"),this.log(" - GET /api/admin/queue"),this.log(" - GET /api/admin/scheduler"),this.log(" - GET /api/admin/logs"),this.log(" - GET /api/admin/stats"),this.newLine()}healthServerTemplate(){return`import { json } from '@sveltejs/kit';
1805
+ `}};import{writeFileSync as no,mkdirSync as io,existsSync as oo}from"fs";import{join as $}from"path";var Wt=class extends p{name="make:dashboard";description="Scaffold admin dashboard routes (health, queue, scheduler, logs)";arguments=[];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,i=[{path:$(s,"src/routes/api/admin/health/+server.ts"),content:this.healthServerTemplate(),label:"api/admin/health/+server.ts"},{path:$(s,"src/routes/api/admin/queue/+server.ts"),content:this.queueServerTemplate(),label:"api/admin/queue/+server.ts"},{path:$(s,"src/routes/api/admin/queue/[id]/retry/+server.ts"),content:this.queueRetryServerTemplate(),label:"api/admin/queue/[id]/retry/+server.ts"},{path:$(s,"src/routes/api/admin/queue/[id]/+server.ts"),content:this.queueDeleteServerTemplate(),label:"api/admin/queue/[id]/+server.ts"},{path:$(s,"src/routes/api/admin/scheduler/+server.ts"),content:this.schedulerServerTemplate(),label:"api/admin/scheduler/+server.ts"},{path:$(s,"src/routes/api/admin/scheduler/[name]/run/+server.ts"),content:this.schedulerRunServerTemplate(),label:"api/admin/scheduler/[name]/run/+server.ts"},{path:$(s,"src/routes/api/admin/scheduler/[name]/toggle/+server.ts"),content:this.schedulerToggleServerTemplate(),label:"api/admin/scheduler/[name]/toggle/+server.ts"},{path:$(s,"src/routes/api/admin/logs/+server.ts"),content:this.logsServerTemplate(),label:"api/admin/logs/+server.ts"},{path:$(s,"src/routes/api/admin/logs/tail/+server.ts"),content:this.logsTailServerTemplate(),label:"api/admin/logs/tail/+server.ts"},{path:$(s,"src/routes/api/admin/stats/+server.ts"),content:this.statsServerTemplate(),label:"api/admin/stats/+server.ts"},{path:$(s,"src/routes/admin/dashboard/+page.server.ts"),content:this.dashboardPageServerTemplate(),label:"admin/dashboard/+page.server.ts"},{path:$(s,"src/routes/admin/dashboard/+page.svelte"),content:this.dashboardPageSvelteTemplate(),label:"admin/dashboard/+page.svelte"}],o=0,n=0;for(let a of i){let l=a.path.substring(0,a.path.lastIndexOf("/"));if(io(l,{recursive:!0}),oo(a.path)&&!r){this.warn(`${a.label} already exists (use --force to overwrite)`),n++;continue}no(a.path,a.content),this.success(`Created ${a.label}`),o++}this.newLine(),o>0?this.info(`${o} file(s) created${n>0?`, ${n} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Setup instructions:"),this.log(" 1. Import dashboard modules in your app:"),this.log(' import { ScheduleMonitor } from "svelar/scheduler/ScheduleMonitor";'),this.log(' import { JobMonitor } from "svelar/queue/JobMonitor";'),this.log(' import { LogViewer } from "svelar/logging/LogViewer";'),this.newLine(),this.log(" 2. Configure auth middleware on admin routes:"),this.log(' - Replace "// TODO: Add admin middleware check" with your auth logic'),this.log(' - Example: if (!event.locals.user?.isAdmin) return error(403, "Forbidden");'),this.newLine(),this.log(" 3. Access the dashboard:"),this.log(" - Navigate to: /admin/dashboard"),this.newLine(),this.log(" 4. API endpoints available at:"),this.log(" - GET /api/admin/health"),this.log(" - GET /api/admin/queue"),this.log(" - GET /api/admin/scheduler"),this.log(" - GET /api/admin/logs"),this.log(" - GET /api/admin/stats"),this.newLine()}healthServerTemplate(){return`import { json } from '@sveltejs/kit';
1573
1806
  import type { RequestHandler } from '@sveltejs/kit';
1574
1807
 
1575
1808
  /**
@@ -2186,7 +2419,7 @@ export const load: PageServerLoad = async ({ fetch }) => {
2186
2419
  margin-top: 0;
2187
2420
  }
2188
2421
  </style>
2189
- `}};import{writeFileSync as Dr,mkdirSync as ao,existsSync as kr}from"fs";import{join as Or}from"path";var Wt=class extends p{name="make:resource";description="Create a new API resource (response transformer)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"},{name:"model",alias:"m",description:"Model name to transform",type:"string"},{name:"collection",alias:"c",description:"Also generate a collection resource",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a resource name.");return}let r=s.endsWith("Resource")?s:`${s}Resource`,n=t.module||this.deriveModuleName(r);!t.module&&this.isDDD()&&this.warn(`No --module specified, using "${n}". Use --module=<name> to target a specific module.`);let o=this.moduleDir(n,"resources");ao(o,{recursive:!0});let i=Or(o,`${r}.ts`);if(kr(i)){this.warn(`Resource ${r} already exists.`);return}let a=t.model||this.inferModelName(r),l=this.isDDD()?`./${a}.js`:`../models/${a}.js`,u=this.generateResource(r,a,l);Dr(i,u);let d=this.isDDD()?`src/lib/modules/${n}`:"src/lib/resources";if(this.success(`Resource created: ${d}/${r}.ts`),t.collection){let h=r.replace("Resource","CollectionResource"),m=Or(o,`${h}.ts`);if(!kr(m)){let f=this.isDDD()?`./${a}.js`:`../models/${a}.js`,E=this.generateCollectionResource(h,r,a,f);Dr(m,E);let T=this.isDDD()?`src/lib/modules/${n}`:"src/lib/resources";this.success(`Collection resource created: ${T}/${h}.ts`)}}}generateResource(e,t,s=`./${t}.js`){let r=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
2422
+ `}};import{writeFileSync as Dr,mkdirSync as ao,existsSync as kr}from"fs";import{join as _r}from"path";var zt=class extends p{name="make:resource";description="Create a new API resource (response transformer)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"},{name:"model",alias:"m",description:"Model name to transform",type:"string"},{name:"collection",alias:"c",description:"Also generate a collection resource",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a resource name.");return}let r=s.endsWith("Resource")?s:`${s}Resource`,i=t.module||this.deriveModuleName(r);!t.module&&this.isDDD()&&this.warn(`No --module specified, using "${i}". Use --module=<name> to target a specific module.`);let o=this.moduleDir(i,"resources");ao(o,{recursive:!0});let n=_r(o,`${r}.ts`);if(kr(n)){this.warn(`Resource ${r} already exists.`);return}let a=t.model||this.inferModelName(r),l=this.isDDD()?`./${a}.js`:`../models/${a}.js`,u=this.generateResource(r,a,l);Dr(n,u);let d=this.isDDD()?`src/lib/modules/${i}`:"src/lib/resources";if(this.success(`Resource created: ${d}/${r}.ts`),t.collection){let h=r.replace("Resource","CollectionResource"),m=_r(o,`${h}.ts`);if(!kr(m)){let f=this.isDDD()?`./${a}.js`:`../models/${a}.js`,E=this.generateCollectionResource(h,r,a,f);Dr(m,E);let T=this.isDDD()?`src/lib/modules/${i}`:"src/lib/resources";this.success(`Collection resource created: ${T}/${h}.ts`)}}}generateResource(e,t,s=`./${t}.js`){let r=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
2190
2423
  import type { ${t} } from '${s}';
2191
2424
 
2192
2425
  // \u2500\u2500 API Contract \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
@@ -2264,7 +2497,7 @@ export class ${e} {
2264
2497
  .toObject();
2265
2498
  }
2266
2499
  }
2267
- `}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as co,mkdirSync as lo,existsSync as uo}from"fs";import{join as ho}from"path";var Jt=class extends p{name="make:schema";description="Create a contract schema (Zod schemas + shared types)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a schema name (e.g. User, Post, Invoice).");return}let r=s.charAt(0).toUpperCase()+s.slice(1),n=this.toKebab(s)+".schema",o=t.module||s.toLowerCase(),i=this.moduleDir(o,"schemas");lo(i,{recursive:!0});let a=ho(i,`${n}.ts`);if(uo(a)){let h=this.isDDD()?`src/lib/modules/${o}`:"src/lib/schemas";this.warn(`Schema already exists: ${h}/${n}.ts`);return}let l=this.generateSchema(r);co(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/schemas";this.success(`Schema created: ${u}/${n}.ts`),this.info(""),this.info(" Use this schema across your entire stack:"),this.info(""),this.info(` Resource: extends Resource<${r}, ${r}Data>`),this.info(` FormRequest: uses create${r}Schema / update${r}Schema`);let d=this.isDDD()?`$lib/modules/${o}/${n}`:`$lib/schemas/${n}`;this.info(` Frontend: import type { ${r}Data } from '${d}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
2500
+ `}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as co,mkdirSync as lo,existsSync as uo}from"fs";import{join as ho}from"path";var Jt=class extends p{name="make:schema";description="Create a contract schema (Zod schemas + shared types)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a schema name (e.g. User, Post, Invoice).");return}let r=s.charAt(0).toUpperCase()+s.slice(1),i=this.toKebab(s)+".schema",o=t.module||s.toLowerCase(),n=this.moduleDir(o,"schemas");lo(n,{recursive:!0});let a=ho(n,`${i}.ts`);if(uo(a)){let h=this.isDDD()?`src/lib/modules/${o}`:"src/lib/schemas";this.warn(`Schema already exists: ${h}/${i}.ts`);return}let l=this.generateSchema(r);co(a,l);let u=this.isDDD()?`src/lib/modules/${o}`:"src/lib/schemas";this.success(`Schema created: ${u}/${i}.ts`),this.info(""),this.info(" Use this schema across your entire stack:"),this.info(""),this.info(` Resource: extends Resource<${r}, ${r}Data>`),this.info(` FormRequest: uses create${r}Schema / update${r}Schema`);let d=this.isDDD()?`$lib/modules/${o}/${i}`:`$lib/schemas/${i}`;this.info(` Frontend: import type { ${r}Data } from '${d}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
2268
2501
 
2269
2502
  // \u2500\u2500 ${e} Contract Schema \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2270
2503
  //
@@ -2299,7 +2532,7 @@ export const update${e}Schema = create${e}Schema.partial();
2299
2532
  export type ${e}Data = z.infer<typeof ${t}Schema>;
2300
2533
  export type Create${e}Input = z.infer<typeof create${e}Schema>;
2301
2534
  export type Update${e}Input = z.infer<typeof update${e}Schema>;
2302
- `}toKebab(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}};import{writeFileSync as po,mkdirSync as mo,existsSync as go}from"fs";import{join as fo}from"path";var Vt=class extends p{name="make:observer";description="Create a new model observer class";arguments=["name"];flags=[{name:"model",alias:"m",description:"The model class to observe",type:"string"},{name:"module",description:"Module name (e.g. users, posts)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an observer name (e.g. UserObserver).");return}let r=t.model||s.replace(/Observer$/,""),n=t.module||this.toSnakeCase(this.pluralize(r)),o=this.moduleDir(n,"observers");mo(o,{recursive:!0});let i=fo(o,`${s}.ts`);if(go(i)){this.warn(`Observer ${s} already exists at ${i}`);return}let a=this.isDDD()?`./${r}.js`:`../models/${r}.js`,l=`import { ModelObserver } from '@beeblock/svelar/orm';
2535
+ `}toKebab(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}};import{writeFileSync as po,mkdirSync as mo,existsSync as go}from"fs";import{join as fo}from"path";var Yt=class extends p{name="make:observer";description="Create a new model observer class";arguments=["name"];flags=[{name:"model",alias:"m",description:"The model class to observe",type:"string"},{name:"module",description:"Module name (e.g. users, posts)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an observer name (e.g. UserObserver).");return}let r=t.model||s.replace(/Observer$/,""),i=t.module||this.toSnakeCase(this.pluralize(r)),o=this.moduleDir(i,"observers");mo(o,{recursive:!0});let n=fo(o,`${s}.ts`);if(go(n)){this.warn(`Observer ${s} already exists at ${n}`);return}let a=this.isDDD()?`./${r}.js`:`../models/${r}.js`,l=`import { ModelObserver } from '@beeblock/svelar/orm';
2303
2536
  import type { ${r} } from '${a}';
2304
2537
 
2305
2538
  export class ${s} extends ModelObserver {
@@ -2337,7 +2570,7 @@ export class ${s} extends ModelObserver {
2337
2570
  // async deleted(${r.toLowerCase()}: ${r}) {
2338
2571
  // }
2339
2572
  }
2340
- `;po(i,l);let u=this.isDDD()?`src/lib/modules/${n}`:"src/lib/observers";this.success(`Observer created: ${u}/${s}.ts`),this.info(`Register it in your app: ${r}.observe(new ${s}());`)}toSnakeCase(e){return e.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}pluralize(e){return e.endsWith("y")?e.slice(0,-1)+"ies":e.endsWith("s")||e.endsWith("x")||e.endsWith("z")||e.endsWith("ch")||e.endsWith("sh")?e+"es":e+"s"}};import{writeFileSync as yo,mkdirSync as bo,existsSync as wo}from"fs";import{join as vo}from"path";var zt=class extends p{name="make:event";description="Create a new event class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an event name (e.g. UserRegistered).");return}let r=t.module||s.replace(/([A-Z])/g," $1").trim().split(" ")[0].toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let n=this.moduleDir(r,"events");bo(n,{recursive:!0});let o=vo(n,`${s}.ts`);if(wo(o)){this.warn(`Event ${s} already exists at ${o}`);return}let i=`/**
2573
+ `;po(n,l);let u=this.isDDD()?`src/lib/modules/${i}`:"src/lib/observers";this.success(`Observer created: ${u}/${s}.ts`),this.info(`Register it in your app: ${r}.observe(new ${s}());`)}toSnakeCase(e){return e.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}pluralize(e){return e.endsWith("y")?e.slice(0,-1)+"ies":e.endsWith("s")||e.endsWith("x")||e.endsWith("z")||e.endsWith("ch")||e.endsWith("sh")?e+"es":e+"s"}};import{writeFileSync as yo,mkdirSync as bo,existsSync as vo}from"fs";import{join as wo}from"path";var Vt=class extends p{name="make:event";description="Create a new event class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an event name (e.g. UserRegistered).");return}let r=t.module||s.replace(/([A-Z])/g," $1").trim().split(" ")[0].toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=this.moduleDir(r,"events");bo(i,{recursive:!0});let o=wo(i,`${s}.ts`);if(vo(o)){this.warn(`Event ${s} already exists at ${o}`);return}let n=`/**
2341
2574
  * ${s} Event
2342
2575
  *
2343
2576
  * Dispatched when ... (describe when this event fires).
@@ -2355,7 +2588,7 @@ export class ${s} {
2355
2588
  // public readonly metadata?: Record<string, any>,
2356
2589
  ) {}
2357
2590
  }
2358
- `;yo(o,i);let a=this.isDDD()?`src/lib/modules/${r}`:"src/lib/events";this.success(`Event created: ${a}/${s}.ts`)}};import{writeFileSync as Eo,mkdirSync as To,existsSync as So}from"fs";import{join as Co}from"path";var Yt=class extends p{name="make:listener";description="Create a new event listener class";arguments=["name"];flags=[{name:"event",alias:"e",description:"The event class this listener handles",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a listener name (e.g. SendWelcomeEmail).");return}let r=t.module||s.replace(/([A-Z])/g," $1").trim().split(" ")[0].toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let n=this.moduleDir(r,"listeners");To(n,{recursive:!0});let o=Co(n,`${s}.ts`);if(So(o)){this.warn(`Listener ${s} already exists at ${o}`);return}let i=t.event||"any",a=t.event?this.isDDD()?`./${t.event}.js`:`../events/${t.event}.js`:"",l=t.event?`import type { ${t.event} } from '${a}';
2591
+ `;yo(o,n);let a=this.isDDD()?`src/lib/modules/${r}`:"src/lib/events";this.success(`Event created: ${a}/${s}.ts`)}};import{writeFileSync as Eo,mkdirSync as To,existsSync as So}from"fs";import{join as Co}from"path";var Gt=class extends p{name="make:listener";description="Create a new event listener class";arguments=["name"];flags=[{name:"event",alias:"e",description:"The event class this listener handles",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a listener name (e.g. SendWelcomeEmail).");return}let r=t.module||s.replace(/([A-Z])/g," $1").trim().split(" ")[0].toLowerCase();!t.module&&this.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=this.moduleDir(r,"listeners");To(i,{recursive:!0});let o=Co(i,`${s}.ts`);if(So(o)){this.warn(`Listener ${s} already exists at ${o}`);return}let n=t.event||"any",a=t.event?this.isDDD()?`./${t.event}.js`:`../events/${t.event}.js`:"",l=t.event?`import type { ${t.event} } from '${a}';
2359
2592
 
2360
2593
  `:"",u=t.event||"any",d=`import { Listener } from '@beeblock/svelar/events';
2361
2594
  ${l}export class ${s} extends Listener<${u}> {
@@ -2369,11 +2602,11 @@ ${l}export class ${s} extends Listener<${u}> {
2369
2602
  // return true;
2370
2603
  // }
2371
2604
  }
2372
- `;Eo(o,d);let h=this.isDDD()?`src/lib/modules/${r}`:"src/lib/listeners";this.success(`Listener created: ${h}/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as xo,mkdirSync as Po,existsSync as Ro}from"fs";import{join as Ar}from"path";var Gt=class extends p{name="make:route";description="Create route files with controller bindings";arguments=["path"];flags=[{name:"controller",alias:"c",description:"Controller class name",type:"string"},{name:"resource",alias:"r",description:"Generate full CRUD resource routes",type:"boolean"},{name:"api",description:"Prefix path with /api",type:"boolean"},{name:"methods",alias:"m",description:"HTTP methods (comma-separated: GET,POST,PUT,DELETE)",type:"string"},{name:"module",description:"Module name for controller import path",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a route path (e.g. posts, users/[id], admin/settings).");return}let r=s.replace(/^\//,"");t.api&&!r.startsWith("api/")&&(r="api/"+r);let n=t.controller||this.inferControllerName(r),o=t.module||this.inferModuleName(r);t.resource?this.generateResourceRoutes(r,n,o):this.generateRoute(r,n,o,t.methods)}generateResourceRoutes(e,t,s){this.generateRouteFile(e,t,s,[{method:"GET",handler:"index"},{method:"POST",handler:"store"}]);let r=this.inferParamName(e);this.generateRouteFile(`${e}/[${r}]`,t,s,[{method:"GET",handler:"show"},{method:"PUT",handler:"update"},{method:"DELETE",handler:"destroy"}])}generateRoute(e,t,s,r){let o=(r?r.split(",").map(i=>i.trim().toUpperCase()):["GET"]).map(i=>({method:i,handler:this.defaultHandler(i)}));this.generateRouteFile(e,t,s,o)}generateRouteFile(e,t,s,r){let n=Ar(process.cwd(),"src","routes",...e.split("/"));Po(n,{recursive:!0});let o=Ar(n,"+server.ts");if(Ro(o)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let i=this.isDDD()?`$lib/modules/${s}/${t}.js`:`$lib/controllers/${t}.js`,a=r.map(u=>`export const ${u.method} = ctrl.handle('${u.handler}');`).join(`
2373
- `),l=`import { ${t} } from '${i}';
2605
+ `;Eo(o,d);let h=this.isDDD()?`src/lib/modules/${r}`:"src/lib/listeners";this.success(`Listener created: ${h}/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as xo,mkdirSync as Ro,existsSync as Po}from"fs";import{join as Or}from"path";var Qt=class extends p{name="make:route";description="Create route files with controller bindings";arguments=["path"];flags=[{name:"controller",alias:"c",description:"Controller class name",type:"string"},{name:"resource",alias:"r",description:"Generate full CRUD resource routes",type:"boolean"},{name:"api",description:"Prefix path with /api",type:"boolean"},{name:"methods",alias:"m",description:"HTTP methods (comma-separated: GET,POST,PUT,DELETE)",type:"string"},{name:"module",description:"Module name for controller import path",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a route path (e.g. posts, users/[id], admin/settings).");return}let r=s.replace(/^\//,"");t.api&&!r.startsWith("api/")&&(r="api/"+r);let i=t.controller||this.inferControllerName(r),o=t.module||this.inferModuleName(r);t.resource?this.generateResourceRoutes(r,i,o):this.generateRoute(r,i,o,t.methods)}generateResourceRoutes(e,t,s){this.generateRouteFile(e,t,s,[{method:"GET",handler:"index"},{method:"POST",handler:"store"}]);let r=this.inferParamName(e);this.generateRouteFile(`${e}/[${r}]`,t,s,[{method:"GET",handler:"show"},{method:"PUT",handler:"update"},{method:"DELETE",handler:"destroy"}])}generateRoute(e,t,s,r){let o=(r?r.split(",").map(n=>n.trim().toUpperCase()):["GET"]).map(n=>({method:n,handler:this.defaultHandler(n)}));this.generateRouteFile(e,t,s,o)}generateRouteFile(e,t,s,r){let i=Or(process.cwd(),"src","routes",...e.split("/"));Ro(i,{recursive:!0});let o=Or(i,"+server.ts");if(Po(o)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let n=this.isDDD()?`$lib/modules/${s}/${t}.js`:`$lib/controllers/${t}.js`,a=r.map(u=>`export const ${u.method} = ctrl.handle('${u.handler}');`).join(`
2606
+ `),l=`import { ${t} } from '${n}';
2374
2607
 
2375
2608
  const ctrl = new ${t}();
2376
2609
  ${a}
2377
- `;xo(o,l),this.success(`Route created: src/routes/${e}/+server.ts`);for(let u of r)this.info(` ${u.method} /${e} \u2192 ${t}.${u.handler}()`)}inferControllerName(e){let t=e.replace(/^api\//,"").split("/").filter(o=>!o.startsWith("[")),s=t[t.length-1]||t[0]||"Index",r=this.singularize(s);return`${r.charAt(0).toUpperCase()+r.slice(1)}Controller`}inferModuleName(e){return e.replace(/^api\//,"").split("/").filter(s=>!s.startsWith("["))[0]||"app"}inferParamName(e){return"id"}defaultHandler(e){return{GET:"index",POST:"store",PUT:"update",PATCH:"update",DELETE:"destroy"}[e]||e.toLowerCase()}singularize(e){return e.endsWith("ies")?e.slice(0,-3)+"y":e.endsWith("ses")||e.endsWith("xes")||e.endsWith("zes")||e.endsWith("ches")||e.endsWith("shes")?e.slice(0,-2):e.endsWith("s")&&!e.endsWith("ss")?e.slice(0,-1):e}};import{join as Nr,relative as Qt,sep as Xt}from"path";import{existsSync as $o,readdirSync as Do,readFileSync as _r,statSync as ko}from"fs";var Zt=class extends p{name="routes:list";description="List all registered routes";arguments=[];flags=[{name:"json",description:"Output as JSON",type:"boolean"},{name:"api",description:"Show only API routes",type:"boolean"},{name:"method",alias:"m",description:"Filter by HTTP method (GET, POST, etc.)",type:"string"}];async handle(e,t){let s=Nr(process.cwd(),"src","routes");if(!$o(s)){this.error("No src/routes/ directory found.");return}let n=this.scanRoutes(s,s);if(t.api&&(n=n.filter(u=>u.path.startsWith("/api"))),t.method){let u=t.method.toUpperCase();n=n.filter(d=>d.method===u)}if(n.sort((u,d)=>u.path.localeCompare(d.path)||u.method.localeCompare(d.method)),n.length===0){this.warn("No routes found.");return}if(t.json){this.log(JSON.stringify(n,null,2));return}this.log(""),this.log(` \x1B[1mApplication Routes\x1B[0m (${n.length} routes)
2378
- `);let o=Math.max(6,...n.map(u=>u.method.length)),i=Math.max(4,...n.map(u=>u.path.length)),a=Math.max(7,...n.map(u=>u.handler.length)),l=` ${"METHOD".padEnd(o)} ${"PATH".padEnd(i)} ${"HANDLER".padEnd(a)} FILE`;this.log(`\x1B[2m${l}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(o)} ${"\u2500".repeat(i)} ${"\u2500".repeat(a)} ${"\u2500".repeat(20)}\x1B[0m`);for(let u of n){let h=`${this.getMethodColor(u.method)}${u.method.padEnd(o)}\x1B[0m`,m=u.path.padEnd(i),f=`\x1B[2m${u.handler.padEnd(a)}\x1B[0m`,E=`\x1B[2m${u.file}\x1B[0m`;this.log(` ${h} ${m} ${f} ${E}`)}this.log("")}scanRoutes(e,t){let s=[],r=Do(e);for(let n of r){let o=Nr(e,n);if(ko(o).isDirectory()){s.push(...this.scanRoutes(o,t));continue}n==="+server.ts"||n==="+server.js"?s.push(...this.parseServerFile(o,t)):(n==="+page.server.ts"||n==="+page.server.js")&&s.push(...this.parsePageServerFile(o,t))}return s}parseServerFile(e,t){let s=[],r=_r(e,"utf-8"),n=this.filePathToUrl(e,t),o=Qt(process.cwd(),e).split(Xt).join("/"),i=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,a;for(;(a=i.exec(r))!==null;){let l=a[1],u=this.extractHandler(r,l);s.push({method:l,path:n,handler:u,file:o})}return s}parsePageServerFile(e,t){let s=[],r=_r(e,"utf-8"),n=this.filePathToUrl(e,t),o=Qt(process.cwd(),e).split(Xt).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:n,handler:"load()",file:o});let i=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(i){let a=i[1].split(",").map(l=>l.trim().split(":")[0].split("(")[0].trim()).filter(Boolean);for(let l of a)s.push({method:"POST",path:l==="default"?n:`${n}?/${l}`,handler:`actions.${l}()`,file:o})}return s}filePathToUrl(e,t){let s=Qt(t,e).split(Xt).join("/");return s=s.replace(/\/?\+(?:server|page\.server)\.[tj]s$/,""),s=s.replace(/\[\.\.\.(\w+)\]/g,"*$1").replace(/\[\[(\w+)\]\]/g,":$1?").replace(/\[(\w+)\]/g,":$1"),s=s.replace(/\([^)]+\)\//g,""),"/"+s||"/"}extractHandler(e,t){let s=new RegExp(`export\\s+const\\s+${t}\\s*=\\s*(\\w+)\\.handle\\(['"]([^'"]+)['"]\\)`),r=e.match(s);if(r)return`${r[1]}.${r[2]}()`;let n=new RegExp(`const\\s*\\{[^}]*${t}[^}]*\\}\\s*=\\s*resource\\(\\s*(\\w+)`),o=e.match(n);return o?`${o[1]}.${{GET:"index/show",POST:"store",PUT:"update",PATCH:"update",DELETE:"destroy"}[t]??t.toLowerCase()}()`:new RegExp(`export\\s+(?:const|async\\s+function)\\s+${t}\\s*(?:=\\s*async)?`).test(e)?"inline handler":"handler"}getMethodColor(e){return{GET:"\x1B[32m",POST:"\x1B[33m",PUT:"\x1B[34m",PATCH:"\x1B[34m",DELETE:"\x1B[31m",HEAD:"\x1B[2m",OPTIONS:"\x1B[2m"}[e]||""}};import{readdirSync as Oo}from"fs";import{join as Ir}from"path";import{pathToFileURL as Ao}from"url";var rs=class extends p{name="migrate";description="Run pending database migrations";flags=[{name:"rollback",description:"Rollback the last batch of migrations",type:"boolean"},{name:"reset",description:"Reset all migrations",type:"boolean"},{name:"refresh",description:"Reset and re-run all migrations",type:"boolean"},{name:"fresh",description:"Drop all tables and re-run all migrations",type:"boolean"},{name:"status",description:"Show migration status",type:"boolean"},{name:"seed",description:"Run seeders after migrating",type:"boolean"},{name:"force",description:"Force destructive operations in production",type:"boolean"}];destructiveFlags=["reset","refresh","fresh"];async handle(e,t){await this.bootstrap();let s=this.destructiveFlags.find(l=>t[l]);s&&this.isProduction()&&!t.force&&(this.error(`The --${s} flag is destructive and cannot be run in production.`),this.error(`Use --force to run this command in production: npx svelar migrate --${s} --force`),process.exit(1));let{Migrator:r}=await Promise.resolve().then(()=>(ss(),Lr)),n=new r,o=Ir(process.cwd(),"src","lib","database","migrations"),i=await this.loadMigrations(o);if(t.status){let l=await n.status(i);this.table(["Migration","Status","Batch"],l.map(u=>[u.name,u.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",u.batch?.toString()??"-"]));return}if(t.rollback){this.info("Rolling back last batch...");let l=await n.rollback(i);if(l.length===0)this.info("Nothing to rollback.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let l=await n.reset(i);if(l.length===0)this.info("Nothing to reset.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let l=await n.refresh(i);for(let u of l.reset)this.success(`Rolled back: ${u}`);for(let u of l.migrated)this.success(`Migrated: ${u}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let l=await n.fresh(i);if(l.dropped.length>0)for(let u of l.dropped)this.success(`Dropped table: ${u}`);this.newLine(),this.info("Re-running all migrations...");for(let u of l.migrated)this.success(`Migrated: ${u}`);return}this.info("Running migrations...");let a=await n.run(i);if(a.length===0)this.info("Nothing to migrate.");else for(let l of a)this.success(`Migrated: ${l}`)}isProduction(){return(process.env.NODE_ENV||process.env.APP_ENV||"development")==="production"}warnDestructive(e){this.isProduction()&&this.warn(`Running --${e} in PRODUCTION with --force.`)}async loadMigrations(e){let t;try{t=Oo(e).filter(r=>r.endsWith(".ts")||r.endsWith(".js")).sort()}catch{return this.warn(`Migrations directory not found: ${e}`),[]}let s=[];for(let r of t){let n=Ir(e,r);try{let o=await import(Ao(n).href),i=o.default??Object.values(o).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.up=="function");i?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:n,migration:new i}):this.warn(`No migration class found in: ${r}`)}catch(o){let i;try{i=o instanceof Error?o.message:String(o)}catch{i=JSON.stringify(o)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${i}`)}}return s}};import{join as ns}from"path";import{pathToFileURL as No}from"url";import{existsSync as jr}from"fs";var is=class extends p{name="seed:run";description="Run database seeders";flags=[{name:"class",description:"Specific seeder class to run",type:"string"}];async handle(e,t){await this.bootstrap();let s=ns(process.cwd(),"src","lib","database","seeders"),r=t.class?ns(s,`${t.class}.ts`):ns(s,"DatabaseSeeder.ts"),n=r;jr(n)||(n=n.replace(/\.ts$/,".js")),jr(n)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let o=await import(No(n).href),i=o.default??o.DatabaseSeeder??Object.values(o).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.run=="function");(!i||typeof i!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new i().run(),this.success("Database seeded successfully.")}catch(o){let i=o instanceof Error?o.message:String(o);this.error(`Seeding failed: ${i}`),o?.stack&&console.error(o.stack),process.exit(1)}}};import{existsSync as Io,readdirSync as jo}from"fs";import{join as cs}from"path";import{pathToFileURL as qo}from"url";var ls=class extends p{name="schedule:run";description="Run the task scheduler";flags=[{name:"once",description:"Run due tasks once and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Scheduler:s}=await Promise.resolve().then(()=>(Fr(),Hr)),r=new s;r.persistToDatabase();let n=cs(process.cwd(),"src","lib","shared","scheduler"),o=cs(process.cwd(),"src","lib","scheduler"),i=Io(n)?n:o,a=await this.loadTasks(i);if(a.length===0){this.warn("No scheduled tasks found in src/lib/shared/scheduler/ or src/lib/scheduler/");return}for(let d of a)r.register(d),this.info(`Registered task: ${d.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let d=await r.run();if(d.length===0)this.info("No tasks were due.");else for(let h of d)h.success?this.success(`${h.task}: completed in ${h.duration}ms`):this.error(`${h.task}: failed \u2014 ${h.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let l=async()=>{let d=await r.run();for(let h of d){let m=new Date().toISOString().replace("T"," ").slice(0,19);h.success?this.success(`[${m}] ${h.task}: completed in ${h.duration}ms`):this.error(`[${m}] ${h.task}: failed \u2014 ${h.error}`)}};await l();let u=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(u/1e3)}s.`),await new Promise(d=>setTimeout(d,u)),await l(),setInterval(l,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=jo(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let n=cs(e,r);try{let o=await import(qo(n).href),i=o.default??Object.values(o).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.handle=="function");if(i){let a=new i;a.schedule(),s.push(a)}}catch(o){this.error(`Failed to load task ${r}: ${o.message??o}`)}}return s}};var ys=class extends p{name="queue:work";description="Process queued jobs";flags=[{name:"queue",description:'Queue name to process (default: "default")',type:"string",default:"default"},{name:"max-jobs",description:"Stop after processing N jobs",type:"string"},{name:"max-time",description:"Stop after N seconds",type:"string"},{name:"sleep",description:"Sleep N milliseconds between polls (default: 1000)",type:"string",default:"1000"},{name:"once",description:"Process a single job and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(fs(),Br)),r=t.queue??"default",n=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,o=t["max-time"]?parseInt(t["max-time"]):void 0,i=t.sleep?parseInt(t.sleep):1e3;if(this.info(`Processing queue "${r}"...`),n&&this.info(`Will stop after ${n} jobs.`),o&&this.info(`Will stop after ${o} seconds.`),this.newLine(),t.once){let u=await s.work({queue:r,maxJobs:1,sleep:0});u===0?this.info("No jobs to process."):this.success(`Processed ${u} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let a=Date.now(),l=0;for(;;){if(o&&(Date.now()-a)/1e3>=o){this.info(`Max time (${o}s) reached. Stopping.`);break}if(n&&l>=n){this.info(`Max jobs (${n}) reached. Stopping.`);break}let u=await s.work({queue:r,maxJobs:1,sleep:0});if(u>0){l+=u;let d=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${d}] Processed ${u} job(s) (total: ${l})`)}else await new Promise(d=>setTimeout(d,i))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${l}`)}};var pr=class extends p{name="tinker";description="Start an interactive REPL with Svelar preloaded";flags=[];async handle(){await this.bootstrap(),this.info("Starting Svelar Tinker..."),this.log(`Type .exit to quit. All Svelar modules are available.
2379
- `);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(Hn(),Un));for(let[r,n]of Object.entries(s))t.context[r]=n;t.context.DB=s.Connection,t.context.Schema=s.Schema,this.log("Available: Model, QueryBuilder, Connection, Schema, Hash, Cache, Event, Log, ..."),this.log("")}catch(s){this.warn(`Could not preload all modules: ${s.message}`)}try{let{readdirSync:s}=await import("fs"),{join:r}=await import("path"),{pathToFileURL:n}=await import("url"),{existsSync:o}=await import("fs"),i=r(process.cwd(),"src","lib","models"),a=r(process.cwd(),"src","lib","modules"),l=[],u=i;if(o(i))u=i,l=s(i).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith("index"));else if(o(a)){u=a;for(let d of s(a,{withFileTypes:!0})){if(!d.isDirectory())continue;let h=r(a,d.name);for(let m of s(h))(m.endsWith(".ts")||m.endsWith(".js"))&&(m.startsWith("index")||m.includes("Controller")||m.includes("Service")||m.includes("Repository")||m.includes("Request")||m.includes("Resource")||m.includes("schema")||m.includes("gates")||l.push(r(d.name,m)))}}for(let d of l)try{let h=await import(n(r(u,d)).href);for(let[m,f]of Object.entries(h))typeof f=="function"&&(t.context[m]=f)}catch{}l.length>0&&this.log(`Loaded models: ${l.map(d=>d.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var fr=class extends p{name="plugin:list";description="List all discovered and enabled plugins";arguments=[];flags=[];async handle(e,t){try{let{PluginRegistry:s}=await Promise.resolve().then(()=>(bt(),gr)),r=s;await r.discover();let n=r.list();if(n.length===0){this.info("No plugins discovered.");return}let o=["Name","Version","Description","Status","Config","Migrations"],i=n.map(a=>[a.name,a.version,a.description||"-",a.enabled?"\u2713 Enabled":" Disabled",a.hasConfig?"\u2713":"-",a.hasMigrations?"\u2713":"-"]);this.newLine(),this.table(o,i),this.newLine(),this.info(`Total: ${n.length} plugin(s)`)}catch(s){this.error(`Failed to list plugins: ${s?.message??String(s)}`)}}};var vr=class extends p{name="plugin:publish";description="Publish a plugin's config and migration files";arguments=["name"];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"},{name:"only",alias:"o",description:"Publish only config|migrations|assets",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a plugin name.");return}try{let{PluginRegistry:r}=await Promise.resolve().then(()=>(bt(),gr)),{PluginPublisher:n}=await Promise.resolve().then(()=>(wr(),Fn)),o=r,i=n;await o.discover();let a=o.get(s);if(!a){this.error(`Plugin "${s}" not found.`);return}let l=await this.loadPluginClass(a.packageName);if(!l){this.error(`Failed to load plugin class for "${s}".`);return}let u=new l,d={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let h=await i.publish(u,d);this.newLine(),h.configs.length>0&&(this.success(`${h.configs.length} config file(s) published:`),h.configs.forEach(m=>this.log(` - ${m}`))),h.migrations.length>0&&(this.success(`${h.migrations.length} migration file(s) published:`),h.migrations.forEach(m=>this.log(` - ${m}`))),h.assets.length>0&&(this.success(`${h.assets.length} asset file(s) published:`),h.assets.forEach(m=>this.log(` - ${m}`))),h.configs.length===0&&h.migrations.length===0&&h.assets.length===0&&this.warn("No publishable files found for this plugin."),this.newLine()}catch(r){this.error(`Failed to publish plugin: ${r?.message??String(r)}`)}}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}};var Tr=class extends p{name="plugin:install";description="Install a plugin from npm";arguments=["package"];flags=[{name:"no-publish",alias:"n",description:"Skip auto-publishing plugin assets",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a package name.");return}try{let{PluginInstaller:r}=await Promise.resolve().then(()=>(Kn(),Bn)),n=r;this.info(`Installing plugin package: ${s}`),this.newLine();let o=await n.install(s,{publish:!t["no-publish"]});this.newLine(),o.success?(this.success(`Plugin installed: ${o.pluginName} (v${o.version})`),o.published&&(o.published.configs.length>0&&this.info(`${o.published.configs.length} config file(s) published`),o.published.migrations.length>0&&this.info(`${o.published.migrations.length} migration file(s) published`),o.published.assets.length>0&&this.info(`${o.published.assets.length} asset file(s) published`)),this.newLine(),this.log("You can now use the plugin in your application by registering it in your app bootstrap code.")):this.error(`Failed to install plugin: ${o.error}`),this.newLine()}catch(r){this.error(`Installation error: ${r?.message??String(r)}`)}}};export{Tt as Cli,p as Command,_t as MakeActionCommand,Bt as MakeBroadcastingCommand,Ht as MakeChannelCommand,qt as MakeCommandCommand,Ut as MakeConfigCommand,$t as MakeControllerCommand,Kt as MakeDashboardCommand,Ft as MakeDockerCommand,zt as MakeEventCommand,jt as MakeJobCommand,Yt as MakeListenerCommand,Dt as MakeMiddlewareCommand,Rt as MakeMigrationCommand,Pt as MakeModelCommand,Vt as MakeObserverCommand,Lt as MakePluginCommand,kt as MakeProviderCommand,Nt as MakeRepositoryCommand,Mt as MakeRequestCommand,Wt as MakeResourceCommand,Gt as MakeRouteCommand,Jt as MakeSchemaCommand,Ot as MakeSeederCommand,At as MakeServiceCommand,It as MakeTaskCommand,rs as MigrateCommand,Tr as PluginInstallCommand,fr as PluginListCommand,vr as PluginPublishCommand,ys as QueueWorkCommand,Zt as RoutesListCommand,ls as ScheduleRunCommand,is as SeedCommand,pr as TinkerCommand};
2610
+ `;xo(o,l),this.success(`Route created: src/routes/${e}/+server.ts`);for(let u of r)this.info(` ${u.method} /${e} \u2192 ${t}.${u.handler}()`)}inferControllerName(e){let t=e.replace(/^api\//,"").split("/").filter(o=>!o.startsWith("[")),s=t[t.length-1]||t[0]||"Index",r=this.singularize(s);return`${r.charAt(0).toUpperCase()+r.slice(1)}Controller`}inferModuleName(e){return e.replace(/^api\//,"").split("/").filter(s=>!s.startsWith("["))[0]||"app"}inferParamName(e){return"id"}defaultHandler(e){return{GET:"index",POST:"store",PUT:"update",PATCH:"update",DELETE:"destroy"}[e]||e.toLowerCase()}singularize(e){return e.endsWith("ies")?e.slice(0,-3)+"y":e.endsWith("ses")||e.endsWith("xes")||e.endsWith("zes")||e.endsWith("ches")||e.endsWith("shes")?e.slice(0,-2):e.endsWith("s")&&!e.endsWith("ss")?e.slice(0,-1):e}};import{join as Ar,relative as Xt,sep as Zt}from"path";import{existsSync as $o,readdirSync as Do,readFileSync as Nr,statSync as ko}from"fs";var es=class extends p{name="routes:list";description="List all registered routes";arguments=[];flags=[{name:"json",description:"Output as JSON",type:"boolean"},{name:"api",description:"Show only API routes",type:"boolean"},{name:"method",alias:"m",description:"Filter by HTTP method (GET, POST, etc.)",type:"string"}];async handle(e,t){let s=Ar(process.cwd(),"src","routes");if(!$o(s)){this.error("No src/routes/ directory found.");return}let i=this.scanRoutes(s,s);if(t.api&&(i=i.filter(u=>u.path.startsWith("/api"))),t.method){let u=t.method.toUpperCase();i=i.filter(d=>d.method===u)}if(i.sort((u,d)=>u.path.localeCompare(d.path)||u.method.localeCompare(d.method)),i.length===0){this.warn("No routes found.");return}if(t.json){this.log(JSON.stringify(i,null,2));return}this.log(""),this.log(` \x1B[1mApplication Routes\x1B[0m (${i.length} routes)
2611
+ `);let o=Math.max(6,...i.map(u=>u.method.length)),n=Math.max(4,...i.map(u=>u.path.length)),a=Math.max(7,...i.map(u=>u.handler.length)),l=` ${"METHOD".padEnd(o)} ${"PATH".padEnd(n)} ${"HANDLER".padEnd(a)} FILE`;this.log(`\x1B[2m${l}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(o)} ${"\u2500".repeat(n)} ${"\u2500".repeat(a)} ${"\u2500".repeat(20)}\x1B[0m`);for(let u of i){let h=`${this.getMethodColor(u.method)}${u.method.padEnd(o)}\x1B[0m`,m=u.path.padEnd(n),f=`\x1B[2m${u.handler.padEnd(a)}\x1B[0m`,E=`\x1B[2m${u.file}\x1B[0m`;this.log(` ${h} ${m} ${f} ${E}`)}this.log("")}scanRoutes(e,t){let s=[],r=Do(e);for(let i of r){let o=Ar(e,i);if(ko(o).isDirectory()){s.push(...this.scanRoutes(o,t));continue}i==="+server.ts"||i==="+server.js"?s.push(...this.parseServerFile(o,t)):(i==="+page.server.ts"||i==="+page.server.js")&&s.push(...this.parsePageServerFile(o,t))}return s}parseServerFile(e,t){let s=[],r=Nr(e,"utf-8"),i=this.filePathToUrl(e,t),o=Xt(process.cwd(),e).split(Zt).join("/"),n=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,a;for(;(a=n.exec(r))!==null;){let l=a[1],u=this.extractHandler(r,l);s.push({method:l,path:i,handler:u,file:o})}return s}parsePageServerFile(e,t){let s=[],r=Nr(e,"utf-8"),i=this.filePathToUrl(e,t),o=Xt(process.cwd(),e).split(Zt).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:i,handler:"load()",file:o});let n=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(n){let a=n[1].split(",").map(l=>l.trim().split(":")[0].split("(")[0].trim()).filter(Boolean);for(let l of a)s.push({method:"POST",path:l==="default"?i:`${i}?/${l}`,handler:`actions.${l}()`,file:o})}return s}filePathToUrl(e,t){let s=Xt(t,e).split(Zt).join("/");return s=s.replace(/\/?\+(?:server|page\.server)\.[tj]s$/,""),s=s.replace(/\[\.\.\.(\w+)\]/g,"*$1").replace(/\[\[(\w+)\]\]/g,":$1?").replace(/\[(\w+)\]/g,":$1"),s=s.replace(/\([^)]+\)\//g,""),"/"+s||"/"}extractHandler(e,t){let s=new RegExp(`export\\s+const\\s+${t}\\s*=\\s*(\\w+)\\.handle\\(['"]([^'"]+)['"]\\)`),r=e.match(s);if(r)return`${r[1]}.${r[2]}()`;let i=new RegExp(`const\\s*\\{[^}]*${t}[^}]*\\}\\s*=\\s*resource\\(\\s*(\\w+)`),o=e.match(i);return o?`${o[1]}.${{GET:"index/show",POST:"store",PUT:"update",PATCH:"update",DELETE:"destroy"}[t]??t.toLowerCase()}()`:new RegExp(`export\\s+(?:const|async\\s+function)\\s+${t}\\s*(?:=\\s*async)?`).test(e)?"inline handler":"handler"}getMethodColor(e){return{GET:"\x1B[32m",POST:"\x1B[33m",PUT:"\x1B[34m",PATCH:"\x1B[34m",DELETE:"\x1B[31m",HEAD:"\x1B[2m",OPTIONS:"\x1B[2m"}[e]||""}};import{readdirSync as _o}from"fs";import{join as Ir}from"path";import{pathToFileURL as Oo}from"url";var ns=class extends p{name="migrate";description="Run pending database migrations";flags=[{name:"rollback",description:"Rollback the last batch of migrations",type:"boolean"},{name:"reset",description:"Reset all migrations",type:"boolean"},{name:"refresh",description:"Reset and re-run all migrations",type:"boolean"},{name:"fresh",description:"Drop all tables and re-run all migrations",type:"boolean"},{name:"status",description:"Show migration status",type:"boolean"},{name:"seed",description:"Run seeders after migrating",type:"boolean"},{name:"force",description:"Force destructive operations in production",type:"boolean"}];destructiveFlags=["reset","refresh","fresh"];async handle(e,t){await this.bootstrap();let s=this.destructiveFlags.find(l=>t[l]);s&&this.isProduction()&&!t.force&&(this.error(`The --${s} flag is destructive and cannot be run in production.`),this.error(`Use --force to run this command in production: npx svelar migrate --${s} --force`),process.exit(1));let{Migrator:r}=await Promise.resolve().then(()=>(rs(),Lr)),i=new r,o=Ir(process.cwd(),"src","lib","database","migrations"),n=await this.loadMigrations(o);if(t.status){let l=await i.status(n);this.table(["Migration","Status","Batch"],l.map(u=>[u.name,u.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",u.batch?.toString()??"-"]));return}if(t.rollback){this.info("Rolling back last batch...");let l=await i.rollback(n);if(l.length===0)this.info("Nothing to rollback.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let l=await i.reset(n);if(l.length===0)this.info("Nothing to reset.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let l=await i.refresh(n);for(let u of l.reset)this.success(`Rolled back: ${u}`);for(let u of l.migrated)this.success(`Migrated: ${u}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let l=await i.fresh(n);if(l.dropped.length>0)for(let u of l.dropped)this.success(`Dropped table: ${u}`);this.newLine(),this.info("Re-running all migrations...");for(let u of l.migrated)this.success(`Migrated: ${u}`);return}this.info("Running migrations...");let a=await i.run(n);if(a.length===0)this.info("Nothing to migrate.");else for(let l of a)this.success(`Migrated: ${l}`)}isProduction(){return(process.env.NODE_ENV||process.env.APP_ENV||"development")==="production"}warnDestructive(e){this.isProduction()&&this.warn(`Running --${e} in PRODUCTION with --force.`)}async loadMigrations(e){let t;try{t=_o(e).filter(r=>r.endsWith(".ts")||r.endsWith(".js")).sort()}catch{return this.warn(`Migrations directory not found: ${e}`),[]}let s=[];for(let r of t){let i=Ir(e,r);try{let o=await import(Oo(i).href),n=o.default??Object.values(o).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.up=="function");n?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:i,migration:new n}):this.warn(`No migration class found in: ${r}`)}catch(o){let n;try{n=o instanceof Error?o.message:String(o)}catch{n=JSON.stringify(o)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${n}`)}}return s}};import{join as is}from"path";import{pathToFileURL as Ao}from"url";import{existsSync as jr}from"fs";var os=class extends p{name="seed:run";description="Run database seeders";flags=[{name:"class",description:"Specific seeder class to run",type:"string"}];async handle(e,t){await this.bootstrap();let s=is(process.cwd(),"src","lib","database","seeders"),r=t.class?is(s,`${t.class}.ts`):is(s,"DatabaseSeeder.ts"),i=r;jr(i)||(i=i.replace(/\.ts$/,".js")),jr(i)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let o=await import(Ao(i).href),n=o.default??o.DatabaseSeeder??Object.values(o).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.run=="function");(!n||typeof n!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new n().run(),this.success("Database seeded successfully.")}catch(o){let n=o instanceof Error?o.message:String(o);this.error(`Seeding failed: ${n}`),o?.stack&&console.error(o.stack),process.exit(1)}}};import{existsSync as Io,readdirSync as jo}from"fs";import{join as ls}from"path";import{pathToFileURL as qo}from"url";var us=class extends p{name="schedule:run";description="Run the task scheduler";flags=[{name:"once",description:"Run due tasks once and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Scheduler:s}=await Promise.resolve().then(()=>(Fr(),Hr)),r=new s;r.persistToDatabase();let i=ls(process.cwd(),"src","lib","shared","scheduler"),o=ls(process.cwd(),"src","lib","scheduler"),n=Io(i)?i:o,a=await this.loadTasks(n);if(a.length===0){this.warn("No scheduled tasks found in src/lib/shared/scheduler/ or src/lib/scheduler/");return}for(let d of a)r.register(d),this.info(`Registered task: ${d.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let d=await r.run();if(d.length===0)this.info("No tasks were due.");else for(let h of d)h.success?this.success(`${h.task}: completed in ${h.duration}ms`):this.error(`${h.task}: failed \u2014 ${h.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let l=async()=>{let d=await r.run();for(let h of d){let m=new Date().toISOString().replace("T"," ").slice(0,19);h.success?this.success(`[${m}] ${h.task}: completed in ${h.duration}ms`):this.error(`[${m}] ${h.task}: failed \u2014 ${h.error}`)}};await l();let u=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(u/1e3)}s.`),await new Promise(d=>setTimeout(d,u)),await l(),setInterval(l,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=jo(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let i=ls(e,r);try{let o=await import(qo(i).href),n=o.default??Object.values(o).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.handle=="function");if(n){let a=new n;a.schedule(),s.push(a)}}catch(o){this.error(`Failed to load task ${r}: ${o.message??o}`)}}return s}};var bs=class extends p{name="queue:work";description="Process queued jobs";flags=[{name:"queue",description:'Queue name to process (default: "default")',type:"string",default:"default"},{name:"max-jobs",description:"Stop after processing N jobs",type:"string"},{name:"max-time",description:"Stop after N seconds",type:"string"},{name:"sleep",description:"Sleep N milliseconds between polls (default: 1000)",type:"string",default:"1000"},{name:"once",description:"Process a single job and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(ys(),Br)),r=t.queue??"default",i=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,o=t["max-time"]?parseInt(t["max-time"]):void 0,n=t.sleep?parseInt(t.sleep):1e3;if(this.info(`Processing queue "${r}"...`),i&&this.info(`Will stop after ${i} jobs.`),o&&this.info(`Will stop after ${o} seconds.`),this.newLine(),t.once){let u=await s.work({queue:r,maxJobs:1,sleep:0});u===0?this.info("No jobs to process."):this.success(`Processed ${u} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let a=Date.now(),l=0;for(;;){if(o&&(Date.now()-a)/1e3>=o){this.info(`Max time (${o}s) reached. Stopping.`);break}if(i&&l>=i){this.info(`Max jobs (${i}) reached. Stopping.`);break}let u=await s.work({queue:r,maxJobs:1,sleep:0});if(u>0){l+=u;let d=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${d}] Processed ${u} job(s) (total: ${l})`)}else await new Promise(d=>setTimeout(d,n))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${l}`)}};var mr=class extends p{name="tinker";description="Start an interactive REPL with Svelar preloaded";flags=[];async handle(){await this.bootstrap(),this.info("Starting Svelar Tinker..."),this.log(`Type .exit to quit. All Svelar modules are available.
2612
+ `);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(Hn(),Un));for(let[r,i]of Object.entries(s))t.context[r]=i;t.context.DB=s.Connection,t.context.Schema=s.Schema,this.log("Available: Model, QueryBuilder, Connection, Schema, Hash, Cache, Event, Log, ..."),this.log("")}catch(s){this.warn(`Could not preload all modules: ${s.message}`)}try{let{readdirSync:s}=await import("fs"),{join:r}=await import("path"),{pathToFileURL:i}=await import("url"),{existsSync:o}=await import("fs"),n=r(process.cwd(),"src","lib","models"),a=r(process.cwd(),"src","lib","modules"),l=[],u=n;if(o(n))u=n,l=s(n).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith("index"));else if(o(a)){u=a;for(let d of s(a,{withFileTypes:!0})){if(!d.isDirectory())continue;let h=r(a,d.name);for(let m of s(h))(m.endsWith(".ts")||m.endsWith(".js"))&&(m.startsWith("index")||m.includes("Controller")||m.includes("Service")||m.includes("Repository")||m.includes("Request")||m.includes("Resource")||m.includes("schema")||m.includes("gates")||l.push(r(d.name,m)))}}for(let d of l)try{let h=await import(i(r(u,d)).href);for(let[m,f]of Object.entries(h))typeof f=="function"&&(t.context[m]=f)}catch{}l.length>0&&this.log(`Loaded models: ${l.map(d=>d.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var yr=class extends p{name="plugin:list";description="List all discovered and enabled plugins";arguments=[];flags=[];async handle(e,t){try{let{PluginRegistry:s}=await Promise.resolve().then(()=>(vt(),fr)),r=s;await r.discover();let i=r.list();if(i.length===0){this.info("No plugins discovered.");return}let o=["Name","Version","Description","Status","Config","Migrations"],n=i.map(a=>[a.name,a.version,a.description||"-",a.enabled?"\u2713 Enabled":" Disabled",a.hasConfig?"\u2713":"-",a.hasMigrations?"\u2713":"-"]);this.newLine(),this.table(o,n),this.newLine(),this.info(`Total: ${i.length} plugin(s)`)}catch(s){this.error(`Failed to list plugins: ${s?.message??String(s)}`)}}};var Er=class extends p{name="plugin:publish";description="Publish a plugin's config and migration files";arguments=["name"];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"},{name:"only",alias:"o",description:"Publish only config|migrations|assets",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a plugin name.");return}try{let{PluginRegistry:r}=await Promise.resolve().then(()=>(vt(),fr)),{PluginPublisher:i}=await Promise.resolve().then(()=>(wr(),Fn)),o=r,n=i;await o.discover();let a=o.get(s);if(!a){this.error(`Plugin "${s}" not found.`);return}let l=await this.loadPluginClass(a.packageName);if(!l){this.error(`Failed to load plugin class for "${s}".`);return}let u=new l,d={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let h=await n.publish(u,d);this.newLine(),h.configs.length>0&&(this.success(`${h.configs.length} config file(s) published:`),h.configs.forEach(m=>this.log(` - ${m}`))),h.migrations.length>0&&(this.success(`${h.migrations.length} migration file(s) published:`),h.migrations.forEach(m=>this.log(` - ${m}`))),h.assets.length>0&&(this.success(`${h.assets.length} asset file(s) published:`),h.assets.forEach(m=>this.log(` - ${m}`))),h.configs.length===0&&h.migrations.length===0&&h.assets.length===0&&this.warn("No publishable files found for this plugin."),this.newLine()}catch(r){this.error(`Failed to publish plugin: ${r?.message??String(r)}`)}}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}};var Sr=class extends p{name="plugin:install";description="Install a plugin from npm";arguments=["package"];flags=[{name:"no-publish",alias:"n",description:"Skip auto-publishing plugin assets",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a package name.");return}try{let{PluginInstaller:r}=await Promise.resolve().then(()=>(Kn(),Bn)),i=r;this.info(`Installing plugin package: ${s}`),this.newLine();let o=await i.install(s,{publish:!t["no-publish"]});this.newLine(),o.success?(this.success(`Plugin installed: ${o.pluginName} (v${o.version})`),o.published&&(o.published.configs.length>0&&this.info(`${o.published.configs.length} config file(s) published`),o.published.migrations.length>0&&this.info(`${o.published.migrations.length} migration file(s) published`),o.published.assets.length>0&&this.info(`${o.published.assets.length} asset file(s) published`)),this.newLine(),this.log("You can now use the plugin in your application by registering it in your app bootstrap code.")):this.error(`Failed to install plugin: ${o.error}`),this.newLine()}catch(r){this.error(`Installation error: ${r?.message??String(r)}`)}}};export{St as Cli,p as Command,Mt as MakeActionCommand,Kt as MakeBroadcastingCommand,Ft as MakeChannelCommand,Ut as MakeCommandCommand,Ht as MakeConfigCommand,Dt as MakeControllerCommand,Wt as MakeDashboardCommand,Bt as MakeDockerCommand,Vt as MakeEventCommand,qt as MakeJobCommand,Gt as MakeListenerCommand,kt as MakeMiddlewareCommand,$t as MakeMigrationCommand,Pt as MakeModelCommand,Yt as MakeObserverCommand,It as MakePluginCommand,_t as MakeProviderCommand,Nt as MakeRepositoryCommand,Lt as MakeRequestCommand,zt as MakeResourceCommand,Qt as MakeRouteCommand,Jt as MakeSchemaCommand,Ot as MakeSeederCommand,At as MakeServiceCommand,jt as MakeTaskCommand,ns as MigrateCommand,Sr as PluginInstallCommand,yr as PluginListCommand,Er as PluginPublishCommand,bs as QueueWorkCommand,es as RoutesListCommand,us as ScheduleRunCommand,os as SeedCommand,mr as TinkerCommand};