@beeblock/svelar 0.4.2 → 0.4.4

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/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- var wn=Object.defineProperty;var He=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var v=(l,e)=>()=>(l&&(e=l(l=0)),e);var E=(l,e)=>{for(var t in e)wn(l,t,{get:e[t],enumerable:!0})};function w(l,e){let t=Symbol.for(l),s=globalThis;return s[t]||(s[t]=e()),s[t]}var T=v(()=>{"use strict"});var C={};E(C,{Connection:()=>g});var cs,g,x=v(()=>{"use strict";T();cs=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 i=await this.rawClient(s),a=t.map(u=>typeof u=="boolean"?u?1:0:u instanceof Date?u.toISOString():u),o=i.prepare(e),c=e.trimStart().toUpperCase();return c.startsWith("SELECT")||c.startsWith("PRAGMA")||c.startsWith("WITH")?o.all(...a):o.run(...a)}case"postgres":return(await this.rawClient(s))(e,...t);case"mysql":{let i=await this.rawClient(s),[a]=await i.execute(e,t);return a}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 i=await e();return await n.commit(),n.release(),i}catch(i){throw await n.rollback(),n.release(),i}}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 i={prepare(o){let c=n.prepare(o);return{all(...u){return c.all(...u)},run(...u){return c.run(...u)},get(...u){return c.get(...u)}}},exec(o){n.exec(o)},pragma(o){return n.prepare(`PRAGMA ${o}`).all()},close(){n.close()}},a;try{let{drizzle:o}=await import("drizzle-orm/better-sqlite3");a=o(i)}catch{a=i}return{drizzle:a,config:e,rawClient:i}}}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=w("svelar.connection",()=>new cs)});var I,gs,J,L,ri,fs=v(()=>{"use strict";x();T();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 gs(this.column)}build(){return this.column}},gs=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},J=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 i=`FOREIGN KEY (${n.name}) REFERENCES ${n.references.table}(${n.references.column})`;n.references.onDelete&&(i+=` ON DELETE ${n.references.onDelete}`),n.references.onUpdate&&(i+=` ON UPDATE ${n.references.onUpdate}`),r.push(i)}s.push(`CREATE TABLE ${e} (
2
+ var wn=Object.defineProperty;var ze=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var y=(o,e)=>()=>(o&&(e=o(o=0)),e);var E=(o,e)=>{for(var t in e)wn(o,t,{get:e[t],enumerable:!0})};function w(o,e){let t=Symbol.for(o),s=globalThis;return s[t]||(s[t]=e()),s[t]}var S=y(()=>{"use strict"});var P={};E(P,{Connection:()=>f});var us,f,C=y(()=>{"use strict";S();us=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 n=await this.rawClient(s),a=t.map(d=>typeof d=="boolean"?d?1:0:d instanceof Date?d.toISOString():d),l=n.prepare(e),c=e.trimStart().toUpperCase();return c.startsWith("SELECT")||c.startsWith("PRAGMA")||c.startsWith("WITH")?l.all(...a):l.run(...a)}case"postgres":return(await this.rawClient(s))(e,...t);case"mysql":{let n=await this.rawClient(s),[a]=await n.execute(e,t);return a}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 n=await e();return await i.commit(),i.release(),n}catch(n){throw await i.rollback(),i.release(),n}}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 n={prepare(l){let c=i.prepare(l);return{all(...d){return c.all(...d)},run(...d){return c.run(...d)},get(...d){return c.get(...d)}}},exec(l){i.exec(l)},pragma(l){return i.prepare(`PRAGMA ${l}`).all()},close(){i.close()}},a;try{let{drizzle:l}=await import("drizzle-orm/better-sqlite3");a=l(n)}catch{a=n}return{drizzle:a,config:e,rawClient:n}}}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{}}},f=w("svelar.connection",()=>new us)});var _,ys,W,j,ni,bs=y(()=>{"use strict";C();S();_=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 ys(this.column)}build(){return this.column}},ys=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},W=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 _(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 _(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 _(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 _(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 n=`FOREIGN KEY (${i.name}) REFERENCES ${i.references.table}(${i.references.column})`;i.references.onDelete&&(n+=` ON DELETE ${i.references.onDelete}`),i.references.onUpdate&&(n+=` ON UPDATE ${i.references.onUpdate}`),r.push(n)}s.push(`CREATE TABLE ${e} (
3
3
  ${r.join(`,
4
4
  `)}
5
- )`);for(let n of this.indices){let i=n.name??`idx_${e}_${n.columns.join("_")}`,a=n.unique?"UNIQUE ":"";s.push(`CREATE ${a}INDEX ${i} 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}},L=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new J;t(s);let r=g.getDriver(this.connectionName),n=s.toSQL(e,r);for(let i of n)await g.raw(i,[],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 J;t(s);let r=g.getDriver(this.connectionName),n=s.columns;for(let i of n){let a=s.columnToSQL(i,r);await g.raw(`ALTER TABLE ${e} ADD COLUMN ${a}`,[],this.connectionName)}}async dropColumn(e,t){await g.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},ri=w("svelar.schema",()=>new L)});var ii={};E(ii,{Migration:()=>Ce,Migrator:()=>Pe});var Ce,Pe,ys=v(()=>{"use strict";x();fs();Ce=class{schema=new L},Pe=class{migrationsTable="svelar_migrations";connectionName;constructor(e){this.connectionName=e}async ensureMigrationsTable(){let e=new L(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(i=>!t.includes(i.name));if(s.length===0)return[];let r=await this.getNextBatch(),n=[];for(let i of s)await i.migration.up(),await g.raw(`INSERT INTO ${this.migrationsTable} (migration, batch) VALUES (?, ?)`,[i.name,r],this.connectionName),n.push(i.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 i=n.migration,a=e.find(o=>o.name===i);a&&(await a.migration.down(),await g.raw(`DELETE FROM ${this.migrationsTable} WHERE migration = ?`,[i],this.connectionName),r.push(i))}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 bt={};E(bt,{SchedulerLock:()=>Te});import{hostname as Ba}from"os";async function Se(){let{Connection:l}=await Promise.resolve().then(()=>(x(),C));return l}async function Ha(){return(await Se()).getDriver()}var oi,B,Te,Re=v(()=>{"use strict";oi=!1,B=`${Ba()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;Te=class{static getOwnerId(){return B}static async ensureTable(){if(oi)return;let e=await Se();switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
5
+ )`);for(let i of this.indices){let n=i.name??`idx_${e}_${i.columns.join("_")}`,a=i.unique?"UNIQUE ":"";s.push(`CREATE ${a}INDEX ${n} 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}},j=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new W;t(s);let r=f.getDriver(this.connectionName),i=s.toSQL(e,r);for(let n of i)await f.raw(n,[],this.connectionName)}async dropTable(e){await f.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async dropTableIfExists(e){await f.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async renameTable(e,t){f.getDriver(this.connectionName)==="mysql"?await f.raw(`RENAME TABLE ${e} TO ${t}`,[],this.connectionName):await f.raw(`ALTER TABLE ${e} RENAME TO ${t}`,[],this.connectionName)}async hasTable(e){let t=f.getDriver(this.connectionName),s;switch(t){case"sqlite":s=await f.raw("SELECT name FROM sqlite_master WHERE type='table' AND name=?",[e],this.connectionName);break;case"postgres":s=await f.raw("SELECT tablename FROM pg_tables WHERE tablename = $1",[e],this.connectionName);break;case"mysql":s=await f.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 W;t(s);let r=f.getDriver(this.connectionName),i=s.columns;for(let n of i){let a=s.columnToSQL(n,r);await f.raw(`ALTER TABLE ${e} ADD COLUMN ${a}`,[],this.connectionName)}}async dropColumn(e,t){await f.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},ni=w("svelar.schema",()=>new j)});var ai={};E(ai,{Migration:()=>we,Migrator:()=>Ce});var we,Ce,vs=y(()=>{"use strict";C();bs();we=class{schema=new j},Ce=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(n=>!t.includes(n.name));if(s.length===0)return[];let r=await this.getNextBatch(),i=[];for(let n of s)await n.migration.up(),await f.raw(`INSERT INTO ${this.migrationsTable} (migration, batch) VALUES (?, ?)`,[n.name,r],this.connectionName),i.push(n.name);return i}async rollback(e){await this.ensureMigrationsTable();let t=await this.getLastBatch();if(t===0)return[];let s=await f.raw(`SELECT migration FROM ${this.migrationsTable} WHERE batch = ? ORDER BY id DESC`,[t],this.connectionName),r=[];for(let i of s){let n=i.migration,a=e.find(l=>l.name===n);a&&(await a.migration.down(),await f.raw(`DELETE FROM ${this.migrationsTable} WHERE migration = ?`,[n],this.connectionName),r.push(n))}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=f.getDriver(this.connectionName),t=[];switch(e){case"sqlite":{t=(await f.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",[],this.connectionName)).map(r=>r.name),await f.raw("PRAGMA foreign_keys = OFF",[],this.connectionName);for(let r of t)await f.raw(`DROP TABLE IF EXISTS "${r}"`,[],this.connectionName);await f.raw("PRAGMA foreign_keys = ON",[],this.connectionName);break}case"mysql":{t=(await f.raw("SHOW TABLES",[],this.connectionName)).map(r=>Object.values(r)[0]),await f.raw("SET FOREIGN_KEY_CHECKS = 0",[],this.connectionName);for(let r of t)await f.raw(`DROP TABLE IF EXISTS \`${r}\``,[],this.connectionName);await f.raw("SET FOREIGN_KEY_CHECKS = 1",[],this.connectionName);break}case"postgres":{t=(await f.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'",[],this.connectionName)).map(r=>r.tablename);for(let r of t)await f.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 f.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 f.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 f.raw(`SELECT MAX(batch) as max_batch FROM ${this.migrationsTable}`,[],this.connectionName))[0]?.max_batch??0}catch{return 0}}}});var vt={};E(vt,{SchedulerLock:()=>Pe});import{hostname as qa}from"os";async function xe(){let{Connection:o}=await Promise.resolve().then(()=>(C(),P));return o}async function Ua(){return(await xe()).getDriver()}var ci,F,Pe,Re=y(()=>{"use strict";ci=!1,F=`${qa()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;Pe=class{static getOwnerId(){return F}static async ensureTable(){if(ci)return;let e=await xe();switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
6
6
  task_key TEXT PRIMARY KEY,
7
7
  owner TEXT NOT NULL,
8
8
  expires_at TEXT NOT NULL
@@ -14,7 +14,7 @@ var wn=Object.defineProperty;var He=(l=>typeof require<"u"?require:typeof Proxy<
14
14
  task_key VARCHAR(255) PRIMARY KEY,
15
15
  owner VARCHAR(255) NOT NULL,
16
16
  expires_at DATETIME NOT NULL
17
- ) ENGINE=InnoDB`);break}oi=!0}static async acquire(e,t=5){await this.ensureTable();let s=await Se(),r=await Ha(),n=new Date().toISOString(),i=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,i]);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,i]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,B,i]);break}});let a=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return a.length>0&&a[0].owner===B}catch{return!1}}static async release(e){try{await(await Se()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,B])}catch{}}static async releaseAll(){try{await(await Se()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[B])}catch{}}}});var ci={};E(ci,{ScheduledTask:()=>wt,Scheduler:()=>ws,SchedulerLock:()=>Te,cronMatches:()=>bs,parseCron:()=>li,task:()=>za});function Ee(l,e,t){if(l==="*")return null;let s=new Set;for(let r of l.split(",")){let[n,i]=r.split("/"),a=i?parseInt(i,10):1;if(n==="*")for(let o=e;o<=t;o+=a)s.add(o);else if(n.includes("-")){let[o,c]=n.split("-"),u=parseInt(o,10),d=parseInt(c,10);for(let p=u;p<=d;p+=a)s.add(p)}else s.add(parseInt(n,10))}return[...s].sort((r,n)=>r-n)}function li(l){let e=l.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${l}". Expected 5 fields.`);return{minute:Ee(e[0],0,59),hour:Ee(e[1],0,23),dayOfMonth:Ee(e[2],1,31),month:Ee(e[3],1,12),dayOfWeek:Ee(e[4],0,6)}}function bs(l,e){let t=li(l),s=e.getMinutes(),r=e.getHours(),n=e.getDate(),i=e.getMonth()+1,a=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(i)||t.dayOfWeek&&!t.dayOfWeek.includes(a))}function za(l,e,t){class s extends wt{name=l;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var wt,ws,di=v(()=>{"use strict";Re();wt=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(()=>(Re(),bt));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(()=>(Re(),bt));await s.release(this.name)}catch{}}}},ws=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(bs(n,t)){let i=await r.executeTask();s.push(i),this.addToHistory(i)}}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(()=>(Re(),bt));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=>bs(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(()=>(x(),C));switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
17
+ ) ENGINE=InnoDB`);break}ci=!0}static async acquire(e,t=5){await this.ensureTable();let s=await xe(),r=await Ua(),i=new Date().toISOString(),n=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,F,n]);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,F,n]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,F,n]);break}});let a=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return a.length>0&&a[0].owner===F}catch{return!1}}static async release(e){try{await(await xe()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,F])}catch{}}static async releaseAll(){try{await(await xe()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[F])}catch{}}}});var ui={};E(ui,{ScheduledTask:()=>wt,Scheduler:()=>xs,SchedulerLock:()=>Pe,cronMatches:()=>Cs,parseCron:()=>di,task:()=>Fa});function Se(o,e,t){if(o==="*")return null;let s=new Set;for(let r of o.split(",")){let[i,n]=r.split("/"),a=n?parseInt(n,10):1;if(i==="*")for(let l=e;l<=t;l+=a)s.add(l);else if(i.includes("-")){let[l,c]=i.split("-"),d=parseInt(l,10),p=parseInt(c,10);for(let h=d;h<=p;h+=a)s.add(h)}else s.add(parseInt(i,10))}return[...s].sort((r,i)=>r-i)}function di(o){let e=o.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${o}". Expected 5 fields.`);return{minute:Se(e[0],0,59),hour:Se(e[1],0,23),dayOfMonth:Se(e[2],1,31),month:Se(e[3],1,12),dayOfWeek:Se(e[4],0,6)}}function Cs(o,e){let t=di(o),s=e.getMinutes(),r=e.getHours(),i=e.getDate(),n=e.getMonth()+1,a=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(n)||t.dayOfWeek&&!t.dayOfWeek.includes(a))}function Fa(o,e,t){class s extends wt{name=o;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var wt,xs,mi=y(()=>{"use strict";Re();wt=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(()=>(Re(),vt));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(()=>(Re(),vt));await s.release(this.name)}catch{}}}},xs=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(Cs(i,t)){let n=await r.executeTask();s.push(n),this.addToHistory(n)}}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(()=>(Re(),vt));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=>Cs(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(()=>(C(),P));switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
18
18
  id INTEGER PRIMARY KEY AUTOINCREMENT,
19
19
  task TEXT NOT NULL,
20
20
  success INTEGER NOT NULL,
@@ -35,11 +35,11 @@ var wn=Object.defineProperty;var He=(l=>typeof require<"u"?require:typeof Proxy<
35
35
  duration INT NOT NULL,
36
36
  error TEXT,
37
37
  ran_at DATETIME NOT NULL
38
- ) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(x(),C));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 ke={};E(ke,{Job:()=>Q,Queue:()=>Rs});var Q,Ct,xs,V,Pt,Cs,Ps,Ss,Ts,Rs,G=v(()=>{"use strict";T();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)}},Ct=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(){}},xs=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()}},V=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(x(),C));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
+ ) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(C(),P));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 Te={};E(Te,{Job:()=>V,Queue:()=>ks});var V,xt,Ps,J,Pt,Rs,Ss,Ts,Es,ks,Q=y(()=>{"use strict";S();V=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)}},xt=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(){}},Ps=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()}},J=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(C(),P));return e}async push(e){await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, payload, attempts, max_attempts, available_at, created_at)
39
39
  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}
40
40
  WHERE queue = ? AND available_at <= ? AND reserved_at IS NULL
41
- 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 i=JSON.parse(n.payload),a=this.registry.resolve(i.jobClass,i.payload);return{id:n.id,jobClass:i.jobClass,payload:i.payload,queue:n.queue,attempts:n.attempts+1,maxAttempts:n.max_attempts,availableAt:n.available_at*1e3,createdAt:n.created_at*1e3,job:a}}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])}},Pt=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(),i=this.getRedisConnection(),a=this.config.prefix??"svelar",o=new n.Worker(e,async c=>{let u=c.data,d=t.resolve(u.jobClass,u.payload);d.attempts=c.attemptsMade+1,await d.handle()},{connection:i,prefix:a,concurrency:r?.concurrency??1});return o.on("failed",async(c,u)=>{let d=c?.data;if(d)try{let p=t.resolve(d.jobClass,d.payload);c.attemptsMade>=(c.opts?.attempts??3)&&(p.failed(u),await s.store({id:c.id,jobClass:d.jobClass,payload:d.payload,queue:e,attempts:c.attemptsMade,maxAttempts:c.opts?.attempts??3,availableAt:Date.now(),createdAt:c.timestamp??Date.now(),job:p},u))}catch{console.error("[Queue] Failed to resolve job for failure handler:",u.message)}}),o}},Cs=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(x(),C));return e}async store(e,t){try{await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, job_class, payload, exception, failed_at)
42
- 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 n=JSON.parse(t);r.restore(n)}catch{}return r}has(e){return this.jobs.has(e)}},Ss=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new Ps;failedStore=new Cs;_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 i={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(i)}async dispatchSync(e){let t=new Ct,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 Ts(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 Pt){let o=await s.createWorker(r,this.jobRegistry,this.failedStore,{concurrency:e?.concurrency??1});return this.processing=!0,this._activeWorker=o,await new Promise(c=>{let u=()=>{this.processing?setTimeout(u,500):o.close().then(c).catch(c)};u()}),0}let n=e?.maxJobs??1/0,i=(e?.sleep??1)*1e3,a=0;for(this.processing=!0;this.processing&&a<n;){let o=await s.pop(r);if(!o){if(n===1/0){await new Promise(c=>setTimeout(c,i));continue}break}o.attempts++,o.job.attempts=o.attempts;try{await o.job.handle(),a++,s instanceof V&&await s.delete(o.id)}catch(c){if(o.attempts<o.maxAttempts){o.job.retrying(o.attempts);let u=o.job.retryDelay??60;s instanceof V?await s.release(o.id,u):(o.availableAt=Date.now()+u*1e3,await s.push(o))}else o.job.failed(c),await this.failedStore.store(o,c),s instanceof V&&await s.delete(o.id)}}return a}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 Ct;break;case"memory":s=new xs;break;case"database":s=new V(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Pt(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},Ts=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(i=>setTimeout(i,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()}))})}},Rs=w("svelar.queue",()=>new Ss)});var N,Es=v(()=>{"use strict";x();N=class l{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 l(this.tableName,this.modelClass,this.connectionName);if(e(s),s.whereClauses.length>0){let{whereSQL:r,whereBindings:n}=s.buildWhere(),i=r.replace(/^WHERE /,"");this.whereClauses.push({type:"raw",raw:`(${i})`,values:n,boolean:t})}return this}orWhereNested(e){return this.whereNested(e,"OR")}whereExists(e){let t=new l("__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 l("__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 l("__placeholder__",void 0,this.connectionName);s(r);let{sql:n,bindings:i}=r.toSQL();return this.whereClauses.push({type:"sub",column:e,operator:t,subSQL:n,subBindings:i,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 l("__placeholder__",void 0,this.connectionName);t(r);let{sql:n,bindings:i}=r.toSQL();return this.cteClauses.push({name:e,sql:n,bindings:i,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 l("__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 l("__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 i=await n.get();if(i.length===0||await t(i,s)===!1||i.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),i=Object.values(e),a=i.map(()=>"?").join(", "),o=s??n.filter(u=>!t.includes(u)),c;if(r==="postgres"){let u=o.map(d=>`${d} = EXCLUDED.${d}`).join(", ");c=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}else if(r==="mysql"){let u=o.map(d=>`${d} = VALUES(${d})`).join(", ");c=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${a}) ON DUPLICATE KEY UPDATE ${u}`}else{let u=o.map(d=>`${d} = excluded.${d}`).join(", ");c=`INSERT INTO ${this.tableName} (${n.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}return g.raw(c,i,this.connectionName)}async insertMany(e){if(e.length===0)return;let t=Object.keys(e[0]),s=[],r=[];for(let i of e){let a=t.map(o=>i[o]);s.push(...a),r.push(`(${a.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[i,a]of Object.entries(e))this.where(i,a);let s=await this.first();if(s)return s;let r={...e,...t},n=await new l(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new l(this.tableName,this.modelClass,this.connectionName).findOrFail(n)}async updateOrCreate(e,t){let s=new l(this.tableName,this.modelClass,this.connectionName);for(let[a,o]of Object.entries(e))s.where(a,o);let r=await s.first();if(r)return await new l(this.tableName,this.modelClass,this.connectionName).where(this.modelClass?.primaryKey??"id",r[this.modelClass?.primaryKey??"id"]).update(t),new l(this.tableName,this.modelClass,this.connectionName).findOrFail(r[this.modelClass?.primaryKey??"id"]);let n={...e,...t},i=await new l(this.tableName,this.modelClass,this.connectionName).insertGetId(n);return new l(this.tableName,this.modelClass,this.connectionName).findOrFail(i)}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 l("__placeholder__",void 0,this.connectionName);e(s);let{sql:r,bindings:n}=s.toSQL(),i=`(${r}) as ${t}`;return this.selectColumns[0]==="*"?this.selectColumns=[i]:this.selectColumns.push(i),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),i=n.map(()=>"?").join(", "),a=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${i})`;return s==="postgres"?(a+=` RETURNING ${t}`,(await g.raw(a,n,this.connectionName))[0]?.[t]):(await g.raw(a,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(o=>`${o} = ?`).join(", "),{whereSQL:n,whereBindings:i}=this.buildWhere(),a=`UPDATE ${this.tableName} SET ${r}${n}`;return await g.raw(a,[...s,...i],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 a=this.cteClauses.some(c=>c.recursive)?"WITH RECURSIVE":"WITH",o=this.cteClauses.map(c=>(t.push(...c.bindings),`${c.name} AS (${c.sql})`));e.push(`${a} ${o.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 i of this.joinClauses)i.type==="CROSS"?e.push(`CROSS JOIN ${i.table}`):e.push(`${i.type} JOIN ${i.table} ON ${i.first} ${i.operator} ${i.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 i=[];for(let a of this.havingClauses)a.type==="raw"?(i.push(a.raw),a.values&&t.push(...a.values)):(i.push(`${a.column} ${a.operator} ?`),t.push(a.value));e.push(`HAVING ${i.join(" AND ")}`)}if(this.orderClauses.length>0){let i=this.orderClauses.map(a=>a.__raw?a.column:`${a.column} ${a.direction.toUpperCase()}`);e.push(`ORDER BY ${i.join(", ")}`)}if(this.limitValue!==null&&e.push(`LIMIT ${this.limitValue}`),this.offsetValue!==null&&e.push(`OFFSET ${this.offsetValue}`),this.unionClauses.length>0)for(let i of this.unionClauses)e.push(i.all?"UNION ALL":"UNION"),e.push(i.sql),t.push(...i.bindings);return{sql:e.join(" "),bindings:t}}clone(){let e=new l(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 o=(r.operator==="IS","null");e.push(`${n} ${r.column} ${r.operator} ${o}`)}else e.push(`${n} ${r.column} ${r.operator} ?`),t.push(r.value);break;case"in":let i=r.values.map(()=>"?").join(", ");e.push(`${n} ${r.column} IN (${i})`),t.push(...r.values);break;case"notIn":let a=r.values.map(()=>"?").join(", ");e.push(`${n} ${r.column} NOT IN (${a})`),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 Y,X,Z,ee,te,ks=v(()=>{"use strict";x();Y=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},X=class extends Y{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(a=>a.getAttribute(this.localKey)),n=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),i=new Map;for(let a of n)i.set(a.getAttribute(this.foreignKey),a);for(let a of t){let o=a.getAttribute(this.localKey);a.setRelation(s,i.get(o)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},Z=class extends Y{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(a=>a.getAttribute(this.localKey)),n=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),i=new Map;for(let a of n){let o=a.getAttribute(this.foreignKey);i.has(o)||i.set(o,[]),i.get(o).push(a)}for(let a of t){let o=a.getAttribute(this.localKey);a.setRelation(s,i.get(o)??[])}}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}},ee=class extends Y{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(a=>a.getAttribute(this.foreignKey)).filter(a=>a!=null);if(r.length===0){for(let a of t)a.setRelation(s,null);return}let n=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),i=new Map;for(let a of n)i.set(a.getAttribute(this.ownerKey),a);for(let a of t){let o=a.getAttribute(this.foreignKey);a.setRelation(s,i.get(o)??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}},te=class extends Y{constructor(t,s,r,n,i,a="id",o="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=n;this.relatedPivotKey=i;this.parentKey=a;this.relatedKey=o}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,i=(await g.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(a=>a[this.relatedPivotKey]);return i.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,i).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(", "),i=await g.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${n})`,r),a=[...new Set(i.map(d=>d[this.relatedPivotKey]))],o=a.length>0?await this.relatedModel.query().whereIn(this.relatedKey,a).get():[],c=new Map;for(let d of o)c.set(d.getAttribute(this.relatedKey),d);let u=new Map;for(let d of i){let p=d[this.foreignPivotKey],f=d[this.relatedPivotKey],y=c.get(f);y&&(u.has(p)||u.set(p,[]),u.get(p).push(y))}for(let d of t){let p=d.getAttribute(this.parentKey);d.setRelation(s,u.get(p)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),n={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},i=Object.keys(n),a=Object.values(n),o=a.map(()=>"?").join(", ");await g.raw(`INSERT INTO ${this.pivotTable} (${i.join(", ")}) VALUES (${o})`,a)}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 mi=v(()=>{"use strict"});var $e,$s=v(()=>{"use strict";$e=class{app;constructor(e){this.app=e}boot(){}}});var pi=v(()=>{"use strict";$s();kt()});var Ae,se,kt=v(()=>{"use strict";T();mi();pi();Ae=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)}},se=w("svelar.event",()=>new Ae)});var $t,hi=v(()=>{"use strict";Es();ks();kt();$t=class l{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 a=new Date().toISOString();t.setAttribute(s.createdAt,a),t.setAttribute(s.updatedAt,a)}let r=t.getInsertableAttributes(),i=await new N(s.table,this,s.connection).insertGetId(r,s.primaryKey);return s.incrementing&&i&&t.setAttribute(s.primaryKey,i),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 X(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new Z(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new ee(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,n,i){return new te(this,e,t,s,r,n??this.constructor.primaryKey,i??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 l?n.toJSON():n):r instanceof l?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=l.hooks.get(t.name);s?.[e]&&await s[e](this),typeof this[e]=="function"&&await this[e]();let r=l.observers.get(t.name)??[];for(let i of r){let a=i[e];typeof a=="function"&&await a.call(i,this)}let n=t.name.toLowerCase();await se.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=l.observers.get(t.name)??[];for(let n of s){let i=n[e];typeof i=="function"&&await i.call(n,this)}let r=t.name.toLowerCase();await se.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 At,gi=v(()=>{"use strict";At=class{async call(e){await new e().run()}}});var H,fi,As=v(()=>{"use strict";T();H=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}},fi=w("svelar.container",()=>new H)});var Dt,yi=v(()=>{"use strict";As();Dt=class{container;providers=[];booted=!1;constructor(e){this.container=e??new H,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 R,q,Nt,re,_t,ie,ne,Mt,ae,oe=v(()=>{"use strict";R=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 i of s){let a=this.namedMiddleware.get(i);a&&r.push(a)}let n=t;for(let i=r.length-1;i>=0;i--){let a=r[i],o=n;typeof a.handle=="function"?n=()=>a.handle(e,o):n=()=>a(e,o)}return n()}count(){return this.middleware.length}},Nt=class extends R{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}},re=class extends R{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()}},_t=class extends R{async handle(e,t){let s=Date.now(),r=e.event.request.method,n=e.event.url.pathname,i=await t(),a=Date.now()-s,o=i instanceof Response?i.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${n} \u2192 ${o} (${a}ms)`),i}},ie=class extends R{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 i=s.url.pathname;if(this.onlyPaths&&!this.onlyPaths.some(c=>i.startsWith(c)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(c=>i.startsWith(c)))return t();let a=this.getCookieToken(s),o=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!a||!o||!this.timingSafeEqual(a,o)?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),i=0;for(let a=0;a<r.length;a++)i|=r[a]^n[a];return i===0}},ne=class extends R{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 i=s.request.headers.get("origin");if(!i)return t();let a=s.url.origin;return i===a||this.allowedOrigins.has(i)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},Mt=class extends R{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 S=s.url.pathname;if(!this.onlyPaths.some($=>S.startsWith($)))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 i=parseInt(n,10),a=Math.floor(Date.now()/1e3);if(isNaN(i)||Math.abs(a-i)>this.tolerance)return new Response(JSON.stringify({message:"Request signature expired"}),{status:401,headers:{"Content-Type":"application/json"}});let c=await s.request.clone().text(),{createHmac:u}=await import("crypto"),d=s.request.method.toUpperCase(),p=s.url.pathname+s.url.search,f=`${n}.${d}.${p}.${c}`,y=u("sha256",this.secret).update(f).digest("hex");return r.length!==y.length||!this.timingSafeCompare(r,y)?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),i=0;for(let a=0;a<r.length;a++)i|=r[a]^n[a];return i===0}static sign(e,t,s,r,n){let{createHmac:i}=He("crypto"),a=n??Math.floor(Date.now()/1e3),o=`${a}.${t.toUpperCase()}.${s}.${r}`;return{signature:i("sha256",e).update(o).digest("hex"),timestamp:a}}},ae=class extends R{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(),i=this.attempts.get(r);if(i){if(n<i.blockedUntil){let o=Math.ceil((i.blockedUntil-n)/1e3);return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:o}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(o)}})}if(i.count>=this.maxAttempts){i.blockedUntil=n+this.decayMinutes*6e4,i.count=0;let o=this.decayMinutes*60;return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:o}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(o)}})}}let a=await t();if(a instanceof Response&&a.status>=400&&a.status<500){let o=this.attempts.get(r)??{count:0,blockedUntil:0};if(o.count++,this.attempts.set(r,o),this.attempts.size>1e4)for(let[c,u]of this.attempts)n>u.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(c)}return a}}});import{z as le}from"zod";function vi(l,e=!1){let t=new l;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 Ot,U,De,Ne,_e,bi=v(()=>{"use strict";oe();Ot=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof R?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:a}of s)r.use(a);let n={event:t,params:t.params,locals:t.locals},i=await r.execute(n,async()=>this.callMethod(e,t));if(i instanceof Response)return i}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 a=await e.request.formData();r=Object.fromEntries(a)}else r=Object.fromEntries(e.url.searchParams);let i=s.safeParse(r);if(!i.success)throw new U(i.error);return i.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 De?this.json({message:e.message||"Not found"},404):e instanceof Ne?this.json({message:e.message||"Unauthorized"},401):e instanceof _e?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)}}},De=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},Ne=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},_e=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as Ja,createHmac as wi,timingSafeEqual as Va}from"crypto";import{promises as F}from"fs";import{join as Me}from"path";var ce,Oe,z,jt,It,Lt,de,Ds=v(()=>{"use strict";oe();ce=class l{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=l.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 Ja(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)}},jt=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(()=>(x(),C));switch(e.getDriver(this.connectionName)){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
41
+ 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 n=JSON.parse(i.payload),a=this.registry.resolve(n.jobClass,n.payload);return{id:i.id,jobClass:n.jobClass,payload:n.payload,queue:i.queue,attempts:i.attempts+1,maxAttempts:i.max_attempts,availableAt:i.available_at*1e3,createdAt:i.created_at*1e3,job:a}}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])}},Pt=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(),n=this.getRedisConnection(),a=this.config.prefix??"svelar",l=new i.Worker(e,async c=>{let d=c.data,p=t.resolve(d.jobClass,d.payload);p.attempts=c.attemptsMade+1,await p.handle()},{connection:n,prefix:a,concurrency:r?.concurrency??1});return l.on("failed",async(c,d)=>{let p=c?.data;if(p)try{let h=t.resolve(p.jobClass,p.payload);c.attemptsMade>=(c.opts?.attempts??3)&&(h.failed(d),await s.store({id:c.id,jobClass:p.jobClass,payload:p.payload,queue:e,attempts:c.attemptsMade,maxAttempts:c.opts?.attempts??3,availableAt:Date.now(),createdAt:c.timestamp??Date.now(),job:h},d))}catch{console.error("[Queue] Failed to resolve job for failure handler:",d.message)}}),l}},Rs=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(C(),P));return e}async store(e,t){try{await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, job_class, payload, exception, failed_at)
42
+ 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}},Ss=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)}},Ts=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new Ss;failedStore=new Rs;_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 n={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(n)}async dispatchSync(e){let t=new xt,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 Es(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 Pt){let l=await s.createWorker(r,this.jobRegistry,this.failedStore,{concurrency:e?.concurrency??1});return this.processing=!0,this._activeWorker=l,await new Promise(c=>{let d=()=>{this.processing?setTimeout(d,500):l.close().then(c).catch(c)};d()}),0}let i=e?.maxJobs??1/0,n=(e?.sleep??1)*1e3,a=0;for(this.processing=!0;this.processing&&a<i;){let l=await s.pop(r);if(!l){if(i===1/0){await new Promise(c=>setTimeout(c,n));continue}break}l.attempts++,l.job.attempts=l.attempts;try{await l.job.handle(),a++,s instanceof J&&await s.delete(l.id)}catch(c){if(l.attempts<l.maxAttempts){l.job.retrying(l.attempts);let d=l.job.retryDelay??60;s instanceof J?await s.release(l.id,d):(l.availableAt=Date.now()+d*1e3,await s.push(l))}else l.job.failed(c),await this.failedStore.store(l,c),s instanceof J&&await s.delete(l.id)}}return a}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 xt;break;case"memory":s=new Ps;break;case"database":s=new J(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Pt(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},Es=class extends V{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(n=>setTimeout(n,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()}))})}},ks=w("svelar.queue",()=>new Ts)});var L,$s=y(()=>{"use strict";C();L=class o{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 o(this.tableName,this.modelClass,this.connectionName);if(e(s),s.whereClauses.length>0){let{whereSQL:r,whereBindings:i}=s.buildWhere(),n=r.replace(/^WHERE /,"");this.whereClauses.push({type:"raw",raw:`(${n})`,values:i,boolean:t})}return this}orWhereNested(e){return this.whereNested(e,"OR")}whereExists(e){let t=new o("__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 o("__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 o("__placeholder__",void 0,this.connectionName);s(r);let{sql:i,bindings:n}=r.toSQL();return this.whereClauses.push({type:"sub",column:e,operator:t,subSQL:i,subBindings:n,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 o("__placeholder__",void 0,this.connectionName);t(r);let{sql:i,bindings:n}=r.toSQL();return this.cteClauses.push({name:e,sql:i,bindings:n,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 o("__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 o("__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 f.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 f.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 f.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 f.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 f.raw(t,s,this.connectionName))[0]?.aggregate??null}async min(e){let{sql:t,bindings:s}=this.buildAggregate(`MIN(${e})`);return(await f.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 f.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName)).map(s=>s[e])}async value(e){return this.selectColumns=[e],this.limitValue=1,(await f.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 n=await i.get();if(n.length===0||await t(n,s)===!1||n.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=f.getDriver(this.connectionName),i=Object.keys(e),n=Object.values(e),a=n.map(()=>"?").join(", "),l=s??i.filter(d=>!t.includes(d)),c;if(r==="postgres"){let d=l.map(p=>`${p} = EXCLUDED.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${d}`}else if(r==="mysql"){let d=l.map(p=>`${p} = VALUES(${p})`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON DUPLICATE KEY UPDATE ${d}`}else{let d=l.map(p=>`${p} = excluded.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${d}`}return f.raw(c,n,this.connectionName)}async insertMany(e){if(e.length===0)return;let t=Object.keys(e[0]),s=[],r=[];for(let n of e){let a=t.map(l=>n[l]);s.push(...a),r.push(`(${a.map(()=>"?").join(", ")})`)}let i=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES ${r.join(", ")}`;return f.raw(i,s,this.connectionName)}async firstOrCreate(e,t={}){for(let[n,a]of Object.entries(e))this.where(n,a);let s=await this.first();if(s)return s;let r={...e,...t},i=await new o(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new o(this.tableName,this.modelClass,this.connectionName).findOrFail(i)}async updateOrCreate(e,t){let s=new o(this.tableName,this.modelClass,this.connectionName);for(let[a,l]of Object.entries(e))s.where(a,l);let r=await s.first();if(r)return await new o(this.tableName,this.modelClass,this.connectionName).where(this.modelClass?.primaryKey??"id",r[this.modelClass?.primaryKey??"id"]).update(t),new o(this.tableName,this.modelClass,this.connectionName).findOrFail(r[this.modelClass?.primaryKey??"id"]);let i={...e,...t},n=await new o(this.tableName,this.modelClass,this.connectionName).insertGetId(i);return new o(this.tableName,this.modelClass,this.connectionName).findOrFail(n)}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 o("__placeholder__",void 0,this.connectionName);e(s);let{sql:r,bindings:i}=s.toSQL(),n=`(${r}) as ${t}`;return this.selectColumns[0]==="*"?this.selectColumns=[n]:this.selectColumns.push(n),this._selectBindings||(this._selectBindings=[]),this._selectBindings.push(...i),this}_selectBindings;async truncate(){f.getDriver(this.connectionName)==="sqlite"?(await f.raw(`DELETE FROM ${this.tableName}`,[],this.connectionName),await f.raw("DELETE FROM sqlite_sequence WHERE name = ?",[this.tableName],this.connectionName)):await f.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 f.raw(i,s,this.connectionName)}async insertGetId(e,t="id"){let s=f.getDriver(this.connectionName),r=Object.keys(e),i=Object.values(e),n=i.map(()=>"?").join(", "),a=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${n})`;return s==="postgres"?(a+=` RETURNING ${t}`,(await f.raw(a,i,this.connectionName))[0]?.[t]):(await f.raw(a,i,this.connectionName),s==="sqlite"?(await f.raw("SELECT last_insert_rowid() as id",[],this.connectionName))[0]?.id:s==="mysql"?(await f.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(l=>`${l} = ?`).join(", "),{whereSQL:i,whereBindings:n}=this.buildWhere(),a=`UPDATE ${this.tableName} SET ${r}${i}`;return await f.raw(a,[...s,...n],this.connectionName),1}async delete(){let{whereSQL:e,whereBindings:t}=this.buildWhere(),s=`DELETE FROM ${this.tableName}${e}`;return await f.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 f.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 a=this.cteClauses.some(c=>c.recursive)?"WITH RECURSIVE":"WITH",l=this.cteClauses.map(c=>(t.push(...c.bindings),`${c.name} AS (${c.sql})`));e.push(`${a} ${l.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 n of this.joinClauses)n.type==="CROSS"?e.push(`CROSS JOIN ${n.table}`):e.push(`${n.type} JOIN ${n.table} ON ${n.first} ${n.operator} ${n.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 n=[];for(let a of this.havingClauses)a.type==="raw"?(n.push(a.raw),a.values&&t.push(...a.values)):(n.push(`${a.column} ${a.operator} ?`),t.push(a.value));e.push(`HAVING ${n.join(" AND ")}`)}if(this.orderClauses.length>0){let n=this.orderClauses.map(a=>a.__raw?a.column:`${a.column} ${a.direction.toUpperCase()}`);e.push(`ORDER BY ${n.join(", ")}`)}if(this.limitValue!==null&&e.push(`LIMIT ${this.limitValue}`),this.offsetValue!==null&&e.push(`OFFSET ${this.offsetValue}`),this.unionClauses.length>0)for(let n of this.unionClauses)e.push(n.all?"UNION ALL":"UNION"),e.push(n.sql),t.push(...n.bindings);return{sql:e.join(" "),bindings:t}}clone(){let e=new o(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 l=(r.operator==="IS","null");e.push(`${i} ${r.column} ${r.operator} ${l}`)}else e.push(`${i} ${r.column} ${r.operator} ?`),t.push(r.value);break;case"in":let n=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} IN (${n})`),t.push(...r.values);break;case"notIn":let a=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} NOT IN (${a})`),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 G,Y,Z,X,ee,As=y(()=>{"use strict";C();G=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},Y=class extends G{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(a=>a.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),n=new Map;for(let a of i)n.set(a.getAttribute(this.foreignKey),a);for(let a of t){let l=a.getAttribute(this.localKey);a.setRelation(s,n.get(l)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},Z=class extends G{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(a=>a.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),n=new Map;for(let a of i){let l=a.getAttribute(this.foreignKey);n.has(l)||n.set(l,[]),n.get(l).push(a)}for(let a of t){let l=a.getAttribute(this.localKey);a.setRelation(s,n.get(l)??[])}}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}},X=class extends G{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(a=>a.getAttribute(this.foreignKey)).filter(a=>a!=null);if(r.length===0){for(let a of t)a.setRelation(s,null);return}let i=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),n=new Map;for(let a of i)n.set(a.getAttribute(this.ownerKey),a);for(let a of t){let l=a.getAttribute(this.foreignKey);a.setRelation(s,n.get(l)??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}},ee=class extends G{constructor(t,s,r,i,n,a="id",l="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=i;this.relatedPivotKey=n;this.parentKey=a;this.relatedKey=l}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,n=(await f.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(a=>a[this.relatedPivotKey]);return n.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,n).get()}async eagerLoad(t,s){let r=t.map(p=>p.getAttribute(this.parentKey));if(r.length===0){for(let p of t)p.setRelation(s,[]);return}let i=r.map(()=>"?").join(", "),n=await f.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${i})`,r),a=[...new Set(n.map(p=>p[this.relatedPivotKey]))],l=a.length>0?await this.relatedModel.query().whereIn(this.relatedKey,a).get():[],c=new Map;for(let p of l)c.set(p.getAttribute(this.relatedKey),p);let d=new Map;for(let p of n){let h=p[this.foreignPivotKey],u=p[this.relatedPivotKey],v=c.get(u);v&&(d.has(h)||d.set(h,[]),d.get(h).push(v))}for(let p of t){let h=p.getAttribute(this.parentKey);p.setRelation(s,d.get(h)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),i={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},n=Object.keys(i),a=Object.values(i),l=a.map(()=>"?").join(", ");await f.raw(`INSERT INTO ${this.pivotTable} (${n.join(", ")}) VALUES (${l})`,a)}async detach(t){let s=this.parentModel.getAttribute(this.parentKey);t?await f.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ?`,[s,t]):await f.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 f.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 hi=y(()=>{"use strict"});var Ee,Ds=y(()=>{"use strict";Ee=class{app;constructor(e){this.app=e}boot(){}}});var gi=y(()=>{"use strict";Ds();kt()});var ke,te,kt=y(()=>{"use strict";S();hi();gi();ke=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)}},te=w("svelar.event",()=>new ke)});var $t,fi=y(()=>{"use strict";$s();As();kt();$t=class o{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 L(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 a=new Date().toISOString();t.setAttribute(s.createdAt,a),t.setAttribute(s.updatedAt,a)}let r=t.getInsertableAttributes(),n=await new L(s.table,this,s.connection).insertGetId(r,s.primaryKey);return s.incrementing&&n&&t.setAttribute(s.primaryKey,n),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 L(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 L(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 L(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 Y(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new Z(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new X(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,i,n){return new ee(this,e,t,s,r,i??this.constructor.primaryKey,n??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 o?i.toJSON():i):r instanceof o?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=o.hooks.get(t.name);s?.[e]&&await s[e](this),typeof this[e]=="function"&&await this[e]();let r=o.observers.get(t.name)??[];for(let n of r){let a=n[e];typeof a=="function"&&await a.call(n,this)}let i=t.name.toLowerCase();await te.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=o.observers.get(t.name)??[];for(let i of s){let n=i[e];typeof n=="function"&&await n.call(i,this)}let r=t.name.toLowerCase();await te.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 At,yi=y(()=>{"use strict";At=class{async call(e){await new e().run()}}});var B,bi,Ls=y(()=>{"use strict";S();B=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}},bi=w("svelar.container",()=>new B)});var Dt,vi=y(()=>{"use strict";Ls();Dt=class{container;providers=[];booted=!1;constructor(e){this.container=e??new B,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 T,O,Lt,se,Mt,re,ie,Nt,ne,ae=y(()=>{"use strict";T=class{},O=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 n of s){let a=this.namedMiddleware.get(n);a&&r.push(a)}let i=t;for(let n=r.length-1;n>=0;n--){let a=r[n],l=i;typeof a.handle=="function"?i=()=>a.handle(e,l):i=()=>a(e,l)}return i()}count(){return this.middleware.length}},Lt=class extends T{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}},se=class extends T{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()}},Mt=class extends T{async handle(e,t){let s=Date.now(),r=e.event.request.method,i=e.event.url.pathname,n=await t(),a=Date.now()-s,l=n instanceof Response?n.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${i} \u2192 ${l} (${a}ms)`),n}},re=class extends T{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 n=s.url.pathname;if(this.onlyPaths&&!this.onlyPaths.some(c=>n.startsWith(c)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(c=>n.startsWith(c)))return t();let a=this.getCookieToken(s),l=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!a||!l||!this.timingSafeEqual(a,l)?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),n=0;for(let a=0;a<r.length;a++)n|=r[a]^i[a];return n===0}},ie=class extends T{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 n=s.request.headers.get("origin");if(!n)return t();let a=s.url.origin;return n===a||this.allowedOrigins.has(n)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},Nt=class extends T{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 x=s.url.pathname;if(!this.onlyPaths.some(k=>x.startsWith(k)))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 n=parseInt(i,10),a=Math.floor(Date.now()/1e3);if(isNaN(n)||Math.abs(a-n)>this.tolerance)return new Response(JSON.stringify({message:"Request signature expired"}),{status:401,headers:{"Content-Type":"application/json"}});let c=await s.request.clone().text(),{createHmac:d}=await import("crypto"),p=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,u=`${i}.${p}.${h}.${c}`,v=d("sha256",this.secret).update(u).digest("hex");return r.length!==v.length||!this.timingSafeCompare(r,v)?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),n=0;for(let a=0;a<r.length;a++)n|=r[a]^i[a];return n===0}static sign(e,t,s,r,i){let{createHmac:n}=ze("crypto"),a=i??Math.floor(Date.now()/1e3),l=`${a}.${t.toUpperCase()}.${s}.${r}`;return{signature:n("sha256",e).update(l).digest("hex"),timestamp:a}}},ne=class extends T{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(),n=this.attempts.get(r);if(n){if(i<n.blockedUntil){let l=Math.ceil((n.blockedUntil-i)/1e3);return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:l}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(l)}})}if(n.count>=this.maxAttempts){n.blockedUntil=i+this.decayMinutes*6e4,n.count=0;let l=this.decayMinutes*60;return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:l}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(l)}})}}let a=await t();if(a instanceof Response&&a.status>=400&&a.status<500){let l=this.attempts.get(r)??{count:0,blockedUntil:0};if(l.count++,this.attempts.set(r,l),this.attempts.size>1e4)for(let[c,d]of this.attempts)i>d.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(c)}return a}}});import{z as oe}from"zod";function wi(o,e=!1){let t=new o;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 It,q,$e,Ae,De,Ci=y(()=>{"use strict";ae();It=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof T?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 O;for(let{middleware:a}of s)r.use(a);let i={event:t,params:t.params,locals:t.locals},n=await r.execute(i,async()=>this.callMethod(e,t));if(n instanceof Response)return n}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 oe.ZodObject?t:oe.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 a=await e.request.formData();r=Object.fromEntries(a)}else r=Object.fromEntries(e.url.searchParams);let n=s.safeParse(r);if(!n.success)throw new q(n.error);return n.data}validateQuery(e,t){let s=t instanceof oe.ZodObject?t:oe.object(t),r=Object.fromEntries(e.url.searchParams),i=s.safeParse(r);if(!i.success)throw new q(i.error);return i.data}validateParams(e,t){let r=(t instanceof oe.ZodObject?t:oe.object(t)).safeParse(e.params);if(!r.success)throw new q(r.error);return r.data}handleError(e,t){return e instanceof q?this.json({message:"Validation failed",errors:e.errors},422):e instanceof $e?this.json({message:e.message||"Not found"},404):e instanceof Ae?this.json({message:e.message||"Unauthorized"},401):e instanceof De?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)}};q=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"}},Ae=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},De=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as za,createHmac as xi,timingSafeEqual as Ka}from"crypto";import{promises as U}from"fs";import{join as Le}from"path";var le,Me,H,_t,jt,Ot,ce,Ms=y(()=>{"use strict";ae();le=class o{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=o.generateId();this.id=t,this.dirty=!0;let s=Me.get(e);return s instanceof H&&s.markOldSessionId(e),Me.delete(e),t}static generateId(){return za(32).toString("hex")}},Me=new Map,H=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}),Me.set(e,this)}async destroy(e){this.sessions.delete(e),Me.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),Me.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},_t=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(()=>(C(),P));switch(e.getDriver(this.connectionName)){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
43
43
  id TEXT PRIMARY KEY,
44
44
  payload TEXT NOT NULL,
45
45
  expires_at TEXT NOT NULL
@@ -51,17 +51,17 @@ var wn=Object.defineProperty;var He=(l=>typeof require<"u"?require:typeof Proxy<
51
51
  id VARCHAR(255) PRIMARY KEY,
52
52
  payload TEXT NOT NULL,
53
53
  expires_at DATETIME NOT NULL
54
- ) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(x(),C)),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(()=>(x(),C)),n=JSON.stringify(t),i=new Date(Date.now()+s*1e3).toISOString(),a=r.getDriver(this.connectionName);a==="sqlite"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
55
- ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,n,i],this.connectionName):a==="postgres"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES ($1, $2, $3)
56
- ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,n,i],this.connectionName):await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
57
- ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,n,i],this.connectionName)}async destroy(e){let{Connection:t}=await Promise.resolve().then(()=>(x(),C));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(x(),C));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},It=class{dir;constructor(e){this.dir=e??Me(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return Me(this.dir,`${t}.json`)}async ensureDir(){await F.mkdir(this.dir,{recursive:!0})}async read(e){try{let t=await F.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 F.writeFile(this.filePath(e),JSON.stringify(r),"utf-8")}async destroy(e){try{await F.unlink(this.filePath(e))}catch{}}async gc(e){try{let t=await F.readdir(this.dir),s=new Date;for(let r of t)if(r.endsWith(".json"))try{let n=await F.readFile(Me(this.dir,r),"utf-8"),i=JSON.parse(n);new Date(i.expiresAt)<s&&await F.unlink(Me(this.dir,r))}catch{await F.unlink(Me(this.dir,r)).catch(()=>{})}}catch{}}},Lt=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 R{config;constructor(e){super(),this.config={cookieName:"svelar_session",lifetime:7200,secret:process.env.APP_KEY??(()=>{throw new Error("APP_KEY is not set. Set it in your .env file before using sessions.")})(),path:"/",domain:"",secure:process.env.NODE_ENV==="production",httpOnly:!0,sameSite:"lax",...e}}async handle(e,t){let s=e.event.request.headers.get("cookie")??"",r=this.getSessionIdFromCookie(s),n=null;if(r){let o=this.verifySignedId(r);o?(n=await this.config.store.read(o),r=o):r=null}r||(r=ce.generateId());let i=new ce(r,n??{});e.event.locals.session=i,e.locals.session=i;let a=await t();if(i.isDirty()&&await this.config.store.write(i.id,i.toPersist(),this.config.lifetime),a instanceof Response){let o=this.signId(i.id),c=this.buildCookieString(o);a.headers.append("Set-Cookie",c)}return a}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=wi("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=wi("sha256",this.config.secret).update(s).digest("base64url");if(r.length!==n.length)return null;let i=Buffer.from(r),a=Buffer.from(n);if(i.length!==a.length)return null;try{if(Va(i,a))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 je={};E(je,{Hash:()=>Ms});import{randomBytes as Ns,scrypt as xi,timingSafeEqual as Qa}from"crypto";async function Ga(l,e=16384){let t=Ns(16),s=64,r=await new Promise((n,i)=>{xi(l,t,s,{N:e,r:8,p:1},(a,o)=>{a?i(a):n(o)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function Ya(l,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"),i=n.length,a=await new Promise((o,c)=>{xi(l,r,i,{N:s,r:8,p:1},(u,d)=>{u?c(u):o(d)})});return Qa(a,n)}var _s,Ms,ue=v(()=>{"use strict";T();_s=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 Ga(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 Ya(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 Ns(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return Ns(e).toString("base64url")}},Ms=w("svelar.hash",()=>new _s)});var Ci={};E(Ci,{EmailTemplates:()=>Xa});import{randomUUID as O}from"crypto";var Os,Xa,Pi=v(()=>{"use strict";T();Os=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:O(),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(()=>(x(),C));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),i=s.text?this.interpolate(s.text,t):void 0;return{subject:r,html:n,text:i}}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:O(),name:"welcome",subject:"Welcome to {{appName}}, {{user.name}}!",html:`
54
+ ) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(C(),P)),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(()=>(C(),P)),i=JSON.stringify(t),n=new Date(Date.now()+s*1e3).toISOString(),a=r.getDriver(this.connectionName);a==="sqlite"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
55
+ ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,i,n],this.connectionName):a==="postgres"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES ($1, $2, $3)
56
+ ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,i,n],this.connectionName):await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
57
+ ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,i,n],this.connectionName)}async destroy(e){let{Connection:t}=await Promise.resolve().then(()=>(C(),P));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(C(),P));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},jt=class{dir;constructor(e){this.dir=e??Le(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return Le(this.dir,`${t}.json`)}async ensureDir(){await U.mkdir(this.dir,{recursive:!0})}async read(e){try{let t=await U.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 U.writeFile(this.filePath(e),JSON.stringify(r),"utf-8")}async destroy(e){try{await U.unlink(this.filePath(e))}catch{}}async gc(e){try{let t=await U.readdir(this.dir),s=new Date;for(let r of t)if(r.endsWith(".json"))try{let i=await U.readFile(Le(this.dir,r),"utf-8"),n=JSON.parse(i);new Date(n.expiresAt)<s&&await U.unlink(Le(this.dir,r))}catch{await U.unlink(Le(this.dir,r)).catch(()=>{})}}catch{}}},Ot=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){}},ce=class extends T{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 l=this.verifySignedId(r);l?(i=await this.config.store.read(l),r=l):r=null}r||(r=le.generateId());let n=new le(r,i??{});e.event.locals.session=n,e.locals.session=n;let a=await t();if(n.isDirty()&&await this.config.store.write(n.id,n.toPersist(),this.config.lifetime),a instanceof Response){let l=this.signId(n.id),c=this.buildCookieString(l);a.headers.append("Set-Cookie",c)}return a}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=xi("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=xi("sha256",this.config.secret).update(s).digest("base64url");if(r.length!==i.length)return null;let n=Buffer.from(r),a=Buffer.from(i);if(n.length!==a.length)return null;try{if(Ka(n,a))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={};E(Ne,{Hash:()=>_s});import{randomBytes as Ns,scrypt as Pi,timingSafeEqual as Wa}from"crypto";async function Ja(o,e=16384){let t=Ns(16),s=64,r=await new Promise((i,n)=>{Pi(o,t,s,{N:e,r:8,p:1},(a,l)=>{a?n(a):i(l)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function Va(o,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"),n=i.length,a=await new Promise((l,c)=>{Pi(o,r,n,{N:s,r:8,p:1},(d,p)=>{d?c(d):l(p)})});return Wa(a,i)}var Is,_s,de=y(()=>{"use strict";S();Is=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 Ja(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 Va(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 Ns(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return Ns(e).toString("base64url")}},_s=w("svelar.hash",()=>new Is)});var Ri={};E(Ri,{EmailTemplates:()=>Qa});import{randomUUID as N}from"crypto";var js,Qa,Si=y(()=>{"use strict";S();js=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:N(),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(()=>(C(),P));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),n=s.text?this.interpolate(s.text,t):void 0;return{subject:r,html:i,text:n}}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:N(),name:"welcome",subject:"Welcome to {{appName}}, {{user.name}}!",html:`
58
58
  <h1>Welcome, {{user.name}}!</h1>
59
59
  <p>Thank you for joining {{appName}}.</p>
60
60
  <p>Your account has been created with the email: <strong>{{user.email}}</strong></p>
61
61
  <p><a href="{{confirmUrl}}">Confirm your email address</a></p>
62
62
  `,text:`Welcome, {{user.name}}!
63
63
 
64
- 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:O(),name:"password-reset",subject:"Reset your {{appName}} password",html:`
64
+ 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:N(),name:"password-reset",subject:"Reset your {{appName}} password",html:`
65
65
  <h1>Password Reset</h1>
66
66
  <p>Hi {{user.name}},</p>
67
67
  <p>Click the link below to reset your password. This link expires in 1 hour.</p>
@@ -69,18 +69,18 @@ Confirm your email: {{confirmUrl}}`,variables:["appName","user.name","user.email
69
69
  <p>If you didn't request this, you can ignore this email.</p>
70
70
  `,text:`Reset your password: {{resetUrl}}
71
71
 
72
- 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:O(),name:"email-verification",subject:"Verify your email address",html:`
72
+ 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:N(),name:"email-verification",subject:"Verify your email address",html:`
73
73
  <h1>Verify Your Email</h1>
74
74
  <p>Hi {{user.name}},</p>
75
75
  <p><a href="{{verifyUrl}}">Click here to verify your email address</a></p>
76
76
  <p>This link expires in 24 hours.</p>
77
- `,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:O(),name:"team-invitation",subject:"{{inviter.name}} invited you to join {{team.name}}",html:`
77
+ `,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:N(),name:"team-invitation",subject:"{{inviter.name}} invited you to join {{team.name}}",html:`
78
78
  <h1>Team Invitation</h1>
79
79
  <p>Hi {{user.name}},</p>
80
80
  <p><strong>{{inviter.name}}</strong> has invited you to join the team <strong>{{team.name}}</strong>.</p>
81
81
  <p><a href="{{acceptUrl}}">Accept Invitation</a></p>
82
82
  <p>This invitation expires in 3 days.</p>
83
- `,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:O(),name:"invoice",subject:"Invoice #{{invoice.number}} from {{appName}}",html:`
83
+ `,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:N(),name:"invoice",subject:"Invoice #{{invoice.number}} from {{appName}}",html:`
84
84
  <h1>Invoice #{{invoice.number}}</h1>
85
85
  <p>Hi {{customer.name}},</p>
86
86
  <p>Thank you for your purchase!</p>
@@ -88,14 +88,14 @@ This link expires in 1 hour.`,variables:["appName","user.name","resetUrl"],categ
88
88
  <p><strong>Date:</strong> {{invoice.date}}</p>
89
89
  <p><a href="{{invoiceUrl}}">View Invoice</a></p>
90
90
  `,text:`Invoice #{{invoice.number}}
91
- 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:O(),name:"subscription-confirmation",subject:"Subscription Confirmation",html:`
91
+ 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:N(),name:"subscription-confirmation",subject:"Subscription Confirmation",html:`
92
92
  <h1>Subscription Confirmed</h1>
93
93
  <p>Hi {{user.name}},</p>
94
94
  <p>Your {{plan.name}} plan is now active.</p>
95
95
  <p><strong>Price:</strong> {{plan.price}} / {{plan.interval}}</p>
96
96
  <p>Your next billing date is {{nextBillingDate}}.</p>
97
97
  `,text:`Your {{plan.name}} plan is active.
98
- 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:O(),name:"otp-code",subject:"Your {{appName}} verification code: {{code}}",html:`
98
+ 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:N(),name:"otp-code",subject:"Your {{appName}} verification code: {{code}}",html:`
99
99
  <h1>Your Verification Code</h1>
100
100
  <p>Hi {{user.name}},</p>
101
101
  <p>Your one-time verification code is:</p>
@@ -104,28 +104,28 @@ Next billing: {{nextBillingDate}}`,variables:["user.name","plan.name","plan.pric
104
104
  <p>If you didn't request this code, you can safely ignore this email.</p>
105
105
  `,text:`Your verification code: {{code}}
106
106
 
107
- 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:O(),name:"subscription-canceled",subject:"Your subscription has been canceled",html:`
107
+ 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:N(),name:"subscription-canceled",subject:"Your subscription has been canceled",html:`
108
108
  <h1>Subscription Canceled</h1>
109
109
  <p>Hi {{user.name}},</p>
110
110
  <p>Your {{plan.name}} subscription has been canceled.</p>
111
111
  <p>You have access until {{accessUntilDate}}.</p>
112
112
  `,text:`Your {{plan.name}} subscription is canceled.
113
- 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,i)=>this.getNestedValue(t,n)?i:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,n,i)=>{let a=this.getNestedValue(t,n);return Array.isArray(a)?a.map((o,c)=>{let u={...t,this:o,$index:c};return this.interpolate(i,u)}).join(""):""}),s=s.replace(/\{\{([\w.$]+)\}\}/g,(r,n)=>{let i=this.getNestedValue(t,n);return i!=null?String(i):""}),s}getNestedValue(e,t){return t.split(".").reduce((s,r)=>s?.[r],e)}},Xa=w("svelar.emailTemplates",()=>new Os)});var Hs={};E(Hs,{Mailable:()=>Ie,Mailer:()=>Bs});function Fs(l){return typeof l=="string"?l:`${l.name} <${l.address}>`}function A(l){return l?Array.isArray(l)?l:[l]:[]}function Si(l){return Buffer.isBuffer(l)?l.toString("base64"):Buffer.from(l).toString("base64")}var qt,js,Is,Ls,qs,Ie,Us,Bs,Ut=v(()=>{"use strict";T();qt=class{async send(e){let t=A(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:[]}}},js=class{async send(e){return{accepted:A(e.to),rejected:[]}}},Is=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?Fs(e.from):void 0,to:A(e.to).join(", "),cc:A(e.cc).join(", ")||void 0,bcc:A(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}}},Ls=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=A(e.to),r=A(e.cc),n=A(e.bcc),i={From:e.from?Fs(e.from):void 0,To:s.join(", "),Subject:e.subject,MessageStream:this.config.messageStream||"outbound"};r.length>0&&(i.Cc=r.join(", ")),n.length>0&&(i.Bcc=n.join(", ")),e.replyTo&&(i.ReplyTo=e.replyTo),e.html&&(i.HtmlBody=e.html),e.text&&(i.TextBody=e.text),!i.HtmlBody&&!i.TextBody&&(i.TextBody=""),e.tags&&(i.Tag=Object.values(e.tags)[0]),e.attachments?.length&&(i.Attachments=e.attachments.map(c=>({Name:c.filename,Content:Si(c.content),ContentType:c.contentType||"application/octet-stream"})));let a=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(i)});if(!a.ok){let c=await a.json().catch(()=>({Message:a.statusText}));throw new Error(`Postmark error ${a.status}: ${c.Message||JSON.stringify(c)}`)}let o=await a.json();return{accepted:s,rejected:[],messageId:o.MessageID}}},qs=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=A(e.to),r=A(e.cc),n=A(e.bcc),i={from:e.from?Fs(e.from):void 0,to:s,subject:e.subject};r.length>0&&(i.cc=r),n.length>0&&(i.bcc=n),e.replyTo&&(i.reply_to=[e.replyTo]),e.html&&(i.html=e.html),e.text&&(i.text=e.text),e.tags&&(i.tags=Object.entries(e.tags).map(([c,u])=>({name:c,value:u}))),e.attachments?.length&&(i.attachments=e.attachments.map(c=>({filename:c.filename,content:Si(c.content),content_type:c.contentType||"application/octet-stream"})));let a=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(i)});if(!a.ok){let c=await a.json().catch(()=>({message:a.statusText}));throw new Error(`Resend error ${a.status}: ${c.message||JSON.stringify(c)}`)}let o=await a.json();return{accepted:s,rejected:[],messageId:o.id}}},Ie=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}},Us=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 qt;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 Is(s);break;case"postmark":r=new Ls(s);break;case"resend":r=new qs(s);break;case"log":r=new qt;break;case"null":r=new js;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}},Bs=w("svelar.mail",()=>new Us)});import{createHmac as me,randomBytes as Le}from"crypto";function Ti(l){return(typeof l=="string"?Buffer.from(l):l).toString("base64url")}function Ri(l){return Buffer.from(l,"base64url").toString("utf-8")}function Ei(l,e,t,s){return me(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${l}.${e}`).digest("base64url")}function zs(l,e,t="HS256"){let s=Ti(JSON.stringify({alg:t,typ:"JWT"})),r=Ti(JSON.stringify(l)),n=Ei(s,r,e,t);return`${s}.${r}.${n}`}function Ks(l,e){let t=l.split(".");if(t.length!==3)return null;let[s,r,n]=t,i;try{i=JSON.parse(Ri(s))}catch{return null}let a=Ei(s,r,e,i.alg);if(n!==a)return null;try{let o=JSON.parse(Ri(r));return o.exp&&Date.now()/1e3>o.exp?null:o}catch{return null}}var Ft,pe,Bt,Ws=v(()=>{"use strict";oe();Ft=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(ue(),je)),r=e[this.config.identifierColumn],n=e[this.config.passwordColumn];if(!r||!n)return null;let i=await this.config.model.where(this.config.identifierColumn,r).first();if(!i)return null;let a=i.getAttribute(this.config.passwordColumn);return await s.verify(n,a)?(this.currentUser=i,t&&(t.set("auth_user_id",i.getAttribute("id")),t.regenerateId()),i):null}async attemptJwt(e){let{Hash:t}=await Promise.resolve().then(()=>(ue(),je));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 i=n.getAttribute(this.config.passwordColumn);return await t.verify(r,i)?(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}:{}},i=zs(n,t.secret,t.algorithm),a=new Date((r+s)*1e3),o={user:e,token:i,expiresAt:a};if(t.refreshTokens){let c=t.refreshExpiresIn??604800,u=Le(32).toString("base64url"),d=me("sha256",t.secret).update(u).digest("hex"),p=new Date((r+c)*1e3),{Connection:f}=await Promise.resolve().then(()=>(x(),C)),y=t.refreshTable??"refresh_tokens";await f.raw(`INSERT INTO ${y} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),d,p.toISOString(),new Date().toISOString()]),o.refreshToken=u,o.refreshExpiresAt=p}return o}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(()=>(x(),C)),n=t.refreshTable??"refresh_tokens",i=await r.raw(`SELECT user_id, expires_at, revoked_at FROM ${n} WHERE token = ?`,[s]);if(i.length===0)return null;let a=i[0];if(a.revoked_at||new Date(a.expires_at)<new Date)return null;await r.raw(`UPDATE ${n} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let o=await this.config.model.find(a.user_id);return o?(this.currentUser=o,this.issueTokenPair(o)):null}async revokeRefreshTokens(e){if(!this.config.jwt?.refreshTokens)return;let{Connection:t}=await Promise.resolve().then(()=>(x(),C)),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=Ks(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(()=>(ue(),je));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=Le(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=me("sha256",r).update(s).digest("hex"),{Connection:i}=await Promise.resolve().then(()=>(x(),C)),a=this.config.token?.table??"personal_access_tokens";return await i.raw(`INSERT INTO ${a} (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(()=>(x(),C)),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=me("sha256",r).update(e).digest("hex"),i=await t.raw(`SELECT user_id FROM ${s} WHERE token = ?`,[n]);if(i.length===0)return null;let a=await this.config.model.find(i[0].user_id);return a&&(this.currentUser=a),a}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(()=>(x(),C)),r=this.config.passwordResets?.table??"password_resets",n=this.config.passwordResets?.expiresIn??3600;await this.ensureTable(r,`
113
+ 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,n)=>this.getNestedValue(t,i)?n:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,i,n)=>{let a=this.getNestedValue(t,i);return Array.isArray(a)?a.map((l,c)=>{let d={...t,this:l,$index:c};return this.interpolate(n,d)}).join(""):""}),s=s.replace(/\{\{([\w.$]+)\}\}/g,(r,i)=>{let n=this.getNestedValue(t,i);return n!=null?String(n):""}),s}getNestedValue(e,t){return t.split(".").reduce((s,r)=>s?.[r],e)}},Qa=w("svelar.emailTemplates",()=>new js)});var Ks={};E(Ks,{Mailable:()=>Ie,Mailer:()=>zs});function Hs(o){return typeof o=="string"?o:`${o.name} <${o.address}>`}function A(o){return o?Array.isArray(o)?o:[o]:[]}function Ti(o){return Buffer.isBuffer(o)?o.toString("base64"):Buffer.from(o).toString("base64")}var qt,Os,qs,Us,Fs,Ie,Bs,zs,Ut=y(()=>{"use strict";S();qt=class{async send(e){let t=A(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:[]}}},Os=class{async send(e){return{accepted:A(e.to),rejected:[]}}},qs=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?Hs(e.from):void 0,to:A(e.to).join(", "),cc:A(e.cc).join(", ")||void 0,bcc:A(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}}},Us=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=A(e.to),r=A(e.cc),i=A(e.bcc),n={From:e.from?Hs(e.from):void 0,To:s.join(", "),Subject:e.subject,MessageStream:this.config.messageStream||"outbound"};r.length>0&&(n.Cc=r.join(", ")),i.length>0&&(n.Bcc=i.join(", ")),e.replyTo&&(n.ReplyTo=e.replyTo),e.html&&(n.HtmlBody=e.html),e.text&&(n.TextBody=e.text),!n.HtmlBody&&!n.TextBody&&(n.TextBody=""),e.tags&&(n.Tag=Object.values(e.tags)[0]),e.attachments?.length&&(n.Attachments=e.attachments.map(c=>({Name:c.filename,Content:Ti(c.content),ContentType:c.contentType||"application/octet-stream"})));let a=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(n)});if(!a.ok){let c=await a.json().catch(()=>({Message:a.statusText}));throw new Error(`Postmark error ${a.status}: ${c.Message||JSON.stringify(c)}`)}let l=await a.json();return{accepted:s,rejected:[],messageId:l.MessageID}}},Fs=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=A(e.to),r=A(e.cc),i=A(e.bcc),n={from:e.from?Hs(e.from):void 0,to:s,subject:e.subject};r.length>0&&(n.cc=r),i.length>0&&(n.bcc=i),e.replyTo&&(n.reply_to=[e.replyTo]),e.html&&(n.html=e.html),e.text&&(n.text=e.text),e.tags&&(n.tags=Object.entries(e.tags).map(([c,d])=>({name:c,value:d}))),e.attachments?.length&&(n.attachments=e.attachments.map(c=>({filename:c.filename,content:Ti(c.content),content_type:c.contentType||"application/octet-stream"})));let a=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(n)});if(!a.ok){let c=await a.json().catch(()=>({message:a.statusText}));throw new Error(`Resend error ${a.status}: ${c.message||JSON.stringify(c)}`)}let l=await a.json();return{accepted:s,rejected:[],messageId:l.id}}},Ie=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}},Bs=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 qt;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 qs(s);break;case"postmark":r=new Us(s);break;case"resend":r=new Fs(s);break;case"log":r=new qt;break;case"null":r=new Os;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}},zs=w("svelar.mail",()=>new Bs)});import{createHmac as ue,randomBytes as _e}from"crypto";function Ei(o){return(typeof o=="string"?Buffer.from(o):o).toString("base64url")}function ki(o){return Buffer.from(o,"base64url").toString("utf-8")}function $i(o,e,t,s){return ue(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${o}.${e}`).digest("base64url")}function Ws(o,e,t="HS256"){let s=Ei(JSON.stringify({alg:t,typ:"JWT"})),r=Ei(JSON.stringify(o)),i=$i(s,r,e,t);return`${s}.${r}.${i}`}function Js(o,e){let t=o.split(".");if(t.length!==3)return null;let[s,r,i]=t,n;try{n=JSON.parse(ki(s))}catch{return null}let a=$i(s,r,e,n.alg);if(i!==a)return null;try{let l=JSON.parse(ki(r));return l.exp&&Date.now()/1e3>l.exp?null:l}catch{return null}}var Ft,me,Bt,Vs=y(()=>{"use strict";ae();Ft=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(de(),Ne)),r=e[this.config.identifierColumn],i=e[this.config.passwordColumn];if(!r||!i)return null;let n=await this.config.model.where(this.config.identifierColumn,r).first();if(!n)return null;let a=n.getAttribute(this.config.passwordColumn);return await s.verify(i,a)?(this.currentUser=n,t&&(t.set("auth_user_id",n.getAttribute("id")),t.regenerateId()),n):null}async attemptJwt(e){let{Hash:t}=await Promise.resolve().then(()=>(de(),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 i=await this.config.model.where(this.config.identifierColumn,s).first();if(!i)return null;let n=i.getAttribute(this.config.passwordColumn);return await t.verify(r,n)?(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}:{}},n=Ws(i,t.secret,t.algorithm),a=new Date((r+s)*1e3),l={user:e,token:n,expiresAt:a};if(t.refreshTokens){let c=t.refreshExpiresIn??604800,d=_e(32).toString("base64url"),p=ue("sha256",t.secret).update(d).digest("hex"),h=new Date((r+c)*1e3),{Connection:u}=await Promise.resolve().then(()=>(C(),P)),v=t.refreshTable??"refresh_tokens";await u.raw(`INSERT INTO ${v} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),p,h.toISOString(),new Date().toISOString()]),l.refreshToken=d,l.refreshExpiresAt=h}return l}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=ue("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(C(),P)),i=t.refreshTable??"refresh_tokens",n=await r.raw(`SELECT user_id, expires_at, revoked_at FROM ${i} WHERE token = ?`,[s]);if(n.length===0)return null;let a=n[0];if(a.revoked_at||new Date(a.expires_at)<new Date)return null;await r.raw(`UPDATE ${i} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let l=await this.config.model.find(a.user_id);return l?(this.currentUser=l,this.issueTokenPair(l)):null}async revokeRefreshTokens(e){if(!this.config.jwt?.refreshTokens)return;let{Connection:t}=await Promise.resolve().then(()=>(C(),P)),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=Js(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(()=>(de(),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=_e(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=ue("sha256",r).update(s).digest("hex"),{Connection:n}=await Promise.resolve().then(()=>(C(),P)),a=this.config.token?.table??"personal_access_tokens";return await n.raw(`INSERT INTO ${a} (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(()=>(C(),P)),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=ue("sha256",r).update(e).digest("hex"),n=await t.raw(`SELECT user_id FROM ${s} WHERE token = ?`,[i]);if(n.length===0)return null;let a=await this.config.model.find(n[0].user_id);return a&&(this.currentUser=a),a}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(()=>(C(),P)),r=this.config.passwordResets?.table??"password_resets",i=this.config.passwordResets?.expiresIn??3600;await this.ensureTable(r,`
114
114
  CREATE TABLE IF NOT EXISTS ${r} (
115
115
  email TEXT NOT NULL,
116
116
  token TEXT NOT NULL,
117
117
  expires_at TEXT NOT NULL,
118
118
  created_at TEXT NOT NULL
119
119
  )
120
- `),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let i=Le(32).toString("base64url"),a=this.hashToken(i),o=new Date(Date.now()+n*1e3).toISOString();await s.raw(`INSERT INTO ${r} (email, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e,a,o,new Date().toISOString()]);let c=this.config.appUrl??process.env.APP_URL??"http://localhost:5173",u=this.config.appName??process.env.APP_NAME??"Svelar",d=`${c}/reset-password?token=${i}&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(()=>(x(),C)),{Hash:n}=await Promise.resolve().then(()=>(ue(),je)),i=this.config.passwordResets?.table??"password_resets",a=this.hashToken(e),o=await r.raw(`SELECT email, expires_at FROM ${i} WHERE token = ? AND email = ?`,[a,t]);if(o.length===0)return!1;let c=o[0];if(new Date(c.expires_at)<new Date)return await r.raw(`DELETE FROM ${i} 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 ${i} WHERE email = ?`,[t]),await this.revokeRefreshTokens(u.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(x(),C)),s=this.config.emailVerification?.table??"email_verifications",r=this.config.emailVerification?.expiresIn??86400,n=e.getAttribute(this.config.identifierColumn);await this.ensureTable(s,`
120
+ `),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let n=_e(32).toString("base64url"),a=this.hashToken(n),l=new Date(Date.now()+i*1e3).toISOString();await s.raw(`INSERT INTO ${r} (email, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e,a,l,new Date().toISOString()]);let c=this.config.appUrl??process.env.APP_URL??"http://localhost:5173",d=this.config.appName??process.env.APP_NAME??"Svelar",p=`${c}/reset-password?token=${n}&email=${encodeURIComponent(e)}`;return await this.sendAuthEmail("password-reset",e,{appName:d,"user.name":t.getAttribute("name")??e,resetUrl:p}),!0}async resetPassword(e,t,s){let{Connection:r}=await Promise.resolve().then(()=>(C(),P)),{Hash:i}=await Promise.resolve().then(()=>(de(),Ne)),n=this.config.passwordResets?.table??"password_resets",a=this.hashToken(e),l=await r.raw(`SELECT email, expires_at FROM ${n} WHERE token = ? AND email = ?`,[a,t]);if(l.length===0)return!1;let c=l[0];if(new Date(c.expires_at)<new Date)return await r.raw(`DELETE FROM ${n} WHERE email = ?`,[t]),!1;let d=await this.config.model.where(this.config.identifierColumn,t).first();if(!d)return!1;let p=await i.make(s);return await this.config.model.where("id",d.getAttribute("id")).update({[this.config.passwordColumn]:p}),await r.raw(`DELETE FROM ${n} WHERE email = ?`,[t]),await this.revokeRefreshTokens(d.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(C(),P)),s=this.config.emailVerification?.table??"email_verifications",r=this.config.emailVerification?.expiresIn??86400,i=e.getAttribute(this.config.identifierColumn);await this.ensureTable(s,`
121
121
  CREATE TABLE IF NOT EXISTS ${s} (
122
122
  user_id TEXT NOT NULL,
123
123
  token TEXT NOT NULL,
124
124
  expires_at TEXT NOT NULL,
125
125
  created_at TEXT NOT NULL
126
126
  )
127
- `),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let i=Le(32).toString("base64url"),a=this.hashToken(i),o=new Date(Date.now()+r*1e3).toISOString();await t.raw(`INSERT INTO ${s} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),a,o,new Date().toISOString()]);let u=`${this.config.appUrl??process.env.APP_URL??"http://localhost:5173"}/verify-email?token=${i}&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(()=>(x(),C)),r=this.config.emailVerification?.table??"email_verifications",n=this.config.emailVerification?.verifiedColumn??"email_verified_at",i=this.hashToken(e),a=await s.raw(`SELECT user_id, expires_at FROM ${r} WHERE token = ? AND user_id = ?`,[i,t]);return a.length===0?!1:new Date(a[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(()=>(x(),C)),n=this.config.otp?.table??"otp_codes",i=this.config.otp?.expiresIn??600,a=this.config.otp?.length??6;await this.ensureTable(n,`
128
- CREATE TABLE IF NOT EXISTS ${n} (
127
+ `),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let n=_e(32).toString("base64url"),a=this.hashToken(n),l=new Date(Date.now()+r*1e3).toISOString();await t.raw(`INSERT INTO ${s} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),a,l,new Date().toISOString()]);let d=`${this.config.appUrl??process.env.APP_URL??"http://localhost:5173"}/verify-email?token=${n}&id=${e.getAttribute("id")}`;await this.sendAuthEmail("email-verification",i,{"user.name":e.getAttribute("name")??i,verifyUrl:d})}async verifyEmail(e,t){let{Connection:s}=await Promise.resolve().then(()=>(C(),P)),r=this.config.emailVerification?.table??"email_verifications",i=this.config.emailVerification?.verifiedColumn??"email_verified_at",n=this.hashToken(e),a=await s.raw(`SELECT user_id, expires_at FROM ${r} WHERE token = ? AND user_id = ?`,[n,t]);return a.length===0?!1:new Date(a[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(()=>(C(),P)),i=this.config.otp?.table??"otp_codes",n=this.config.otp?.expiresIn??600,a=this.config.otp?.length??6;await this.ensureTable(i,`
128
+ CREATE TABLE IF NOT EXISTS ${i} (
129
129
  email TEXT NOT NULL,
130
130
  code TEXT NOT NULL,
131
131
  purpose TEXT NOT NULL DEFAULT 'login',
@@ -133,32 +133,35 @@ Access until: {{accessUntilDate}}`,variables:["user.name","plan.name","accessUnt
133
133
  used_at TEXT,
134
134
  created_at TEXT NOT NULL
135
135
  )
136
- `),await r.raw(`DELETE FROM ${n} WHERE email = ? AND purpose = ?`,[e,t]);let o=this.generateOtpCode(a),c=this.hashToken(o),u=new Date(Date.now()+i*1e3).toISOString();await r.raw(`INSERT INTO ${n} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,c,t,u,new Date().toISOString()]);let d=this.config.appName??process.env.APP_NAME??"Svelar",p=Math.ceil(i/60);return await this.sendAuthEmail("otp-code",e,{appName:d,"user.name":s.getAttribute("name")??e,code:o,purpose:t,expiresMinutes:String(p)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(x(),C)),n=this.config.otp?.table??"otp_codes",i=this.hashToken(t),a=await r.raw(`SELECT email, expires_at, used_at FROM ${n} WHERE code = ? AND email = ? AND purpose = ? AND used_at IS NULL`,[i,e,s]);if(a.length===0)return null;if(new Date(a[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(),i,e,s]);let o=await this.config.model.where(this.config.identifierColumn,e).first();return o&&(this.currentUser=o),o}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(()=>(x(),C)),t=new Date().toISOString(),s=0,r=0,n=0,i=this.config.passwordResets?.table??"password_resets",a=this.config.emailVerification?.table??"email_verifications",o=this.config.otp?.table??"otp_codes";try{s=(await e.raw(`DELETE FROM ${i} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{r=(await e.raw(`DELETE FROM ${a} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{n=(await e.raw(`DELETE FROM ${o} 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 me("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=Le(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(()=>(x(),C));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(Pi(),Ci)),{Mailer:n}=await Promise.resolve().then(()=>(Ut(),Hs)),i=await r.render(e,s);await n.send({to:t,subject:i.subject,html:i.html,text:i.text})}catch(r){console.error(`[Auth] Failed to send ${e} email to ${t}:`,r.message)}}},pe=class extends R{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 i=n.slice(7);try{r=await this.authManager.resolveFromToken(i)}catch{r=await this.authManager.resolveFromApiToken(i)}}}return t.event.locals.user=r,t.event.locals.auth=this.authManager,s()}},Bt=class extends R{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 Za,mkdir as eo}from"fs/promises";import{dirname as to}from"path";function _(){return new Date().toISOString()}var Ht,qe,Js,Vs,Qs,Gs,Ys,zt,Xs=v(()=>{"use strict";T();Ht={debug:0,info:1,warn:2,error:3,fatal:4},qe=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(Ht[e.level]<Ht[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),i=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"",a=e.level==="error"||e.level==="fatal"?"error":"log";console[a](`${r}[${e.timestamp}] ${n}${s} ${e.message}${i}`)}},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(Ht[e.level]<Ht[this.minLevel])return;this.initialized||(await eo(to(this.path),{recursive:!0}),this.initialized=!0);let t;if(this.format==="json")t=JSON.stringify(e)+`
136
+ `),await r.raw(`DELETE FROM ${i} WHERE email = ? AND purpose = ?`,[e,t]);let l=this.generateOtpCode(a),c=this.hashToken(l),d=new Date(Date.now()+n*1e3).toISOString();await r.raw(`INSERT INTO ${i} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,c,t,d,new Date().toISOString()]);let p=this.config.appName??process.env.APP_NAME??"Svelar",h=Math.ceil(n/60);return await this.sendAuthEmail("otp-code",e,{appName:p,"user.name":s.getAttribute("name")??e,code:l,purpose:t,expiresMinutes:String(h)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(C(),P)),i=this.config.otp?.table??"otp_codes",n=this.hashToken(t),a=await r.raw(`SELECT email, expires_at, used_at FROM ${i} WHERE code = ? AND email = ? AND purpose = ? AND used_at IS NULL`,[n,e,s]);if(a.length===0)return null;if(new Date(a[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(),n,e,s]);let l=await this.config.model.where(this.config.identifierColumn,e).first();return l&&(this.currentUser=l),l}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(()=>(C(),P)),t=new Date().toISOString(),s=0,r=0,i=0,n=this.config.passwordResets?.table??"password_resets",a=this.config.emailVerification?.table??"email_verifications",l=this.config.otp?.table??"otp_codes";try{s=(await e.raw(`DELETE FROM ${n} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{r=(await e.raw(`DELETE FROM ${a} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{i=(await e.raw(`DELETE FROM ${l} 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 ue("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=_e(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(()=>(C(),P));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(Si(),Ri)),{Mailer:i}=await Promise.resolve().then(()=>(Ut(),Ks)),n=await r.render(e,s);await i.send({to:t,subject:n.subject,html:n.html,text:n.text})}catch(r){console.error(`[Auth] Failed to send ${e} email to ${t}:`,r.message)}}},me=class extends T{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 n=i.slice(7);try{r=await this.authManager.resolveFromToken(n)}catch{r=await this.authManager.resolveFromApiToken(n)}}}return t.event.locals.user=r,t.event.locals.auth=this.authManager,s()}},Bt=class extends T{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 Ga,mkdir as Ya}from"fs/promises";import{dirname as Za}from"path";function M(){return new Date().toISOString()}var Ht,je,Qs,Gs,Ys,Zs,Xs,zt,er=y(()=>{"use strict";S();Ht={debug:0,info:1,warn:2,error:3,fatal:4},je=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(Ht[e.level]<Ht[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),n=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"",a=e.level==="error"||e.level==="fatal"?"error":"log";console[a](`${r}[${e.timestamp}] ${i}${s} ${e.message}${n}`)}},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(Ht[e.level]<Ht[this.minLevel])return;this.initialized||(await Ya(Za(this.path),{recursive:!0}),this.initialized=!0);let t;if(this.format==="json")t=JSON.stringify(e)+`
137
137
  `;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}
138
- `}await Za(this.path,t)}},Vs=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)}}},Qs=class{minLevel="debug";write(){}},Gs=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 Ys(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 qe({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 qe(e);case"file":return new Js(e);case"stack":return new Vs(e,t=>this.resolveChannel(t));case"null":return new Qs;default:return new qe(e)}}},Ys=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:_()})}};zt=w("svelar.log",()=>new Gs)});function Vt(l,e){throw new D(l,e??so(l))}function ki(l,e,t){l&&Vt(e,t)}function $i(l,e,t){l||Vt(e,t)}function so(l){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"}[l]??"An error occurred"}var D,Kt,Zs,er,Wt,Jt,he,tr=v(()=>{"use strict";Xs();D=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},Kt=class extends D{constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},Zs=class extends D{constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},er=class extends D{constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},Wt=class extends D{constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},Jt=class extends Kt{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};he=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[Wt,Kt,Zs,er],...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 D?{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(zt.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 D){let s={message:e.message};return e instanceof Wt&&(s.errors=e.errors),e.details&&Object.assign(s,e.details),this.config.debug&&(s.exception=e.name,s.stack=e.stack?.split(`
138
+ `}await Ga(this.path,t)}},Gs=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)}}},Ys=class{minLevel="debug";write(){}},Zs=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 Xs(this.resolveChannel(e))}debug(e,t={}){this.writeToDefault({level:"debug",message:e,context:t,timestamp:M()})}info(e,t={}){this.writeToDefault({level:"info",message:e,context:t,timestamp:M()})}warn(e,t={}){this.writeToDefault({level:"warn",message:e,context:t,timestamp:M()})}error(e,t={}){this.writeToDefault({level:"error",message:e,context:t,timestamp:M()})}fatal(e,t={}){this.writeToDefault({level:"fatal",message:e,context:t,timestamp:M()})}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 je({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 je(e);case"file":return new Qs(e);case"stack":return new Gs(e,t=>this.resolveChannel(t));case"null":return new Ys;default:return new je(e)}}},Xs=class{constructor(e){this.channel=e}debug(e,t={}){this.channel.write({level:"debug",message:e,context:t,timestamp:M()})}info(e,t={}){this.channel.write({level:"info",message:e,context:t,timestamp:M()})}warn(e,t={}){this.channel.write({level:"warn",message:e,context:t,timestamp:M()})}error(e,t={}){this.channel.write({level:"error",message:e,context:t,timestamp:M()})}fatal(e,t={}){this.channel.write({level:"fatal",message:e,context:t,timestamp:M()})}};zt=w("svelar.log",()=>new Zs)});function Vt(o,e){throw new D(o,e??Xa(o))}function Ai(o,e,t){o&&Vt(e,t)}function Di(o,e,t){o||Vt(e,t)}function Xa(o){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"}[o]??"An error occurred"}var D,Kt,tr,sr,Wt,Jt,pe,rr=y(()=>{"use strict";er();D=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},Kt=class extends D{constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},tr=class extends D{constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},sr=class extends D{constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},Wt=class extends D{constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},Jt=class extends Kt{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};pe=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[Wt,Kt,tr,sr],...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 D?{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(zt.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 D){let s={message:e.message};return e instanceof Wt&&(s.errors=e.errors),e.details&&Object.assign(s,e.details),this.config.debug&&(s.exception=e.name,s.stack=e.stack?.split(`
139
139
  `).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(`
140
- `).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function Ai(l={}){let{auth:e,secret:t=process.env.APP_KEY||(()=>{throw new Error("APP_KEY is not set. Set it in your .env file.")})(),sessionStore:s,sessionLifetime:r=86400,rateLimit:n=100,rateLimitWindow:i=6e4,csrfPaths:a=["/api/"],csrfExcludePaths:o=["/api/webhooks"],authThrottleAttempts:c=5,authThrottleDecay:u=1,debug:d=process.env.NODE_ENV!=="production",middleware:p=[],namedMiddleware:f={},i18n:y,errorConfig:S={}}=l,$=[new ne,new re({maxRequests:n,windowMs:i}),new ie({onlyPaths:a,excludePaths:o}),new de({store:s??new z,secret:t,lifetime:r})];e&&$.push(new pe(e)),$.push(...p);let ls={"auth-throttle":new ae({maxAttempts:c,decayMinutes:u}),...f},ve=new he({debug:d,...S}),Be=sr({middleware:$,namedMiddleware:ls,onError:(we,M)=>ve.handle(we,M)}),be;if(y){let{paraglideMiddleware:we,getTextDirection:M=()=>"ltr"}=y;be=rr(async({event:K,resolve:yn})=>we(K.request,({request:vn,locale:Dr})=>(K.request=vn,yn(K,{transformPageChunk:({html:bn})=>bn.replace("%lang%",Dr).replace("%dir%",M(Dr))}))),Be)}else be=Be;return{handle:be,handleError:ve.handleSvelteKitError()}}function sr(l={}){let e=new q;if(l.middleware)for(let t of l.middleware)e.use(t);if(l.namedMiddleware)for(let[t,s]of Object.entries(l.namedMiddleware))e.register(t,s);return async function({event:s,resolve:r}){let n={event:s,params:s.params??{},locals:s.locals??{}};try{l.app&&!l.app.isBooted()&&await l.app.bootstrap();let i=await e.execute(n,async()=>r(s));return i instanceof Response?i:r(s)}catch(i){if(l.onError){let a=await l.onError(i,s);if(a instanceof Response)return a}return console.error("[Svelar] Unhandled error in hooks:",i),new Response(JSON.stringify({message:process.env.NODE_ENV==="production"?"Internal server error":i.message}),{status:500,headers:{"Content-Type":"application/json"}})}}}function rr(...l){return async function({event:t,resolve:s}){let r=s;for(let n=l.length-1;n>=0;n--){let i=l[n],a=r;r=o=>i({event:o,resolve:a})}return r(t)}}var ir=v(()=>{"use strict";oe();Ds();Ws();tr()});function Di(l,e){let t=process.env[l];return t===void 0?e!==void 0?e:"":t==="true"?!0:t==="false"?!1:t==="null"?null:/^\d+$/.test(t)?Number(t):t}var nr,Ni,_i=v(()=>{"use strict";T();nr=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:i}=await import("fs"),{pathToFileURL:a}=await import("url"),o=t(e);if(!n(o))return[];let c=i(o).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith(".")),u=[];for(let d of c){let p=s(d,r(d)),f=t(o,d);try{let S=await import(a(f).href),$=S.default??S.config??S;$&&typeof $=="object"&&!Array.isArray($)&&(this.set(p,$),u.push(p))}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 i=1;i<s.length-1;i++)(n[s[i]]===void 0||typeof n[s[i]]!="object")&&(n[s[i]]={}),n=n[s[i]];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}},Ni=w("svelar.config",()=>new nr)});import{z as P}from"zod";function Oi(l,e){let t=l.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"],i=s;for(let o=0;o<n.length-1;o++){let c=n[o];c in i||(i[c]={}),i=i[c]}let a=n[n.length-1];i[a]||(i[a]=[]),i[a].push(r.message)}return{success:!1,errors:s}}var Mi,ji=v(()=>{"use strict";Mi={required:()=>P.string().min(1,"This field is required"),email:()=>P.string().email("Must be a valid email address"),string:(l,e)=>{let t=P.string();return l!==void 0&&(t=t.min(l)),e!==void 0&&(t=t.max(e)),t},number:(l,e)=>{let t=P.number();return l!==void 0&&(t=t.min(l)),e!==void 0&&(t=t.max(e)),t},integer:()=>P.number().int(),boolean:()=>P.boolean(),date:()=>P.coerce.date(),url:()=>P.string().url(),uuid:()=>P.string().uuid(),enum:l=>P.enum(l),array:l=>P.array(l),nullable:l=>l.nullable(),optional:l=>l.optional(),confirmed:(l="password")=>P.object({[l]:P.string(),[`${l}_confirmation`]:P.string()}).refine(e=>e[l]===e[`${l}_confirmation`],{message:"Confirmation does not match",path:[`${l}_confirmation`]}),min:l=>P.number().min(l),max:l=>P.number().max(l),between:(l,e)=>P.number().min(l).max(e),regex:(l,e)=>P.string().regex(l,e),ip:()=>P.string().refine(l=>{let e=l.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:()=>P.string().refine(l=>{try{return JSON.parse(l),!0}catch{return!1}},{message:"Must be valid JSON"})}});var Ii={};E(Ii,{FormAuthorizationError:()=>fe,FormRequest:()=>Ue,FormValidationError:()=>ge});var Ue,ge,fe,ar=v(()=>{"use strict";Ue=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new ge(e)}failedAuthorization(){throw new fe}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},a=t.rules().safeParse(n);if(!a.success){let o={},c=t.messages(),u=t.attributes();for(let d of a.error.issues){let p=d.path.join("."),f=u[p]??p;o[f]||(o[f]=[]);let y=`${p}.${d.code}`,S=c[y]??c[p];o[f].push(S??d.message)}t.failedValidation(o)}return t.passedValidation(a.data)}},ge=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"}})}},fe=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 Li,writeFile as ro,unlink as io,mkdir as Fe,readdir as or,stat as qi,copyFile as no,rename as ao}from"fs/promises";import{existsSync as oo}from"fs";import{join as lo,dirname as Qt}from"path";var lr,Gt,cr,Ui,Fi=v(()=>{"use strict";T();lr=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return lo(this.config.root,e)}async get(e){return Li(this.resolve(e))}async getText(e){return Li(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await Fe(Qt(s),{recursive:!0}),await ro(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await Fe(Qt(r),{recursive:!0}),await s(r,t)}async exists(e){return oo(this.resolve(e))}async delete(e){try{return await io(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await Fe(Qt(s),{recursive:!0}),await no(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await Fe(Qt(s),{recursive:!0}),await ao(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await or(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 or(s,{withFileTypes:!0});for(let n of r){let i=e?`${e}/${n.name}`:n.name;n.isFile()?t.push(i):n.isDirectory()&&t.push(...await this.allFiles(i))}}catch{}return t}async directories(e=""){let t=this.resolve(e);try{return(await or(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await Fe(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 qi(this.resolve(e))).size}async lastModified(e){return(await qi(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},Gt=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(i=>i.Key).filter(i=>i!==r).map(i=>{let a=this.config.prefix;return a?i.slice(a.length+1):i})}catch{return[]}}async allFiles(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:""),n=[],i;do{let a=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:i}));for(let o of a.Contents??[]){let c=this.config.prefix,u=c?o.Key.slice(c.length+1):o.Key;u&&n.push(u)}i=a.IsTruncated?a.NextContinuationToken:void 0}while(i);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(i=>{let a=this.config.prefix;return(a?i.Prefix.slice(a.length+1):i.Prefix).replace(/\/$/,"")}).filter(i=>i.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(),i=new r.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)});return await s.getSignedUrl(n,i,{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}))}}},cr=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 lr(e);case"s3":return new Gt(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof Gt))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},Ui=w("svelar.storage",()=>new cr)});import{readFile as co,writeFile as uo,unlink as Bi,mkdir as Hi}from"fs/promises";import{join as mo,dirname as po}from"path";import{createHash as ho}from"crypto";var dr,ur,mr,pr,zi,Ki=v(()=>{"use strict";T();dr=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)}},ur=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=ho("md5").update(e).digest("hex");return mo(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await co(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await Bi(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 Hi(po(r),{recursive:!0}),await uo(r,JSON.stringify(n))}async forget(e){try{return await Bi(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 Hi(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)}},mr=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}},pr=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 dr;case"file":return new ur(e);case"null":return new mr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},zi=w("svelar.cache",()=>new pr)});var Yt,hr,gr,fr,Wi,Ji=v(()=>{"use strict";T();Yt=class{},hr=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(()=>(Ut(),Hs));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)}}},gr=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(()=>(x(),C));await r.raw(`INSERT INTO ${this.table} (id, notifiable_id, type, data, read_at, created_at)
141
- 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)}}},fr=class{channels=new Map;constructor(){this.channels.set("mail",new hr),this.channels.set("database",new gr)}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 i of n){let a=this.channels.get(i);if(a)try{await a.send(r,t)}catch(o){console.error(`[Notifications] Channel "${i}" failed:`,o)}else console.warn(`[Notifications] Unknown channel: ${i}`)}}}async sendVia(e,t,s){for(let r of s){let n=this.channels.get(r);n&&await n.send(e,t)}}},Wi=w("svelar.notifier",()=>new fr)});function yr(l){return l.startsWith("private-")?"private":l.startsWith("presence-")?"presence":"public"}var vr,Xt,br,wr,Vi,Qi=v(()=>{"use strict";T();vr=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=yr(e)}stream(e,t){let s=this,r=new ReadableStream({start(n){let i={channel:s.name};s.type==="presence"&&(i.members=s.getMembers());let a=`event: connected
142
- data: ${JSON.stringify(i)}
140
+ `).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function Li(o={}){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:n=6e4,csrfPaths:a=["/api/"],csrfExcludePaths:l=["/api/webhooks"],authThrottleAttempts:c=5,authThrottleDecay:d=1,debug:p=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:u={},i18n:v,errorConfig:x={}}=o,k=[new ie,new se({maxRequests:i,windowMs:n}),new re({onlyPaths:a,excludePaths:l}),new ce({store:s??new H,secret:t,lifetime:r})];e&&k.push(new me(e)),k.push(...h);let ls={"auth-throttle":new ne({maxAttempts:c,decayMinutes:d}),...u},cs=new pe({debug:p,...x}),Ue=ir({middleware:k,namedMiddleware:ls,onError:(ye,be)=>cs.handle(ye,be)}),z;if(v){let{paraglideMiddleware:ye,getTextDirection:be=()=>"ltr"}=v;z=nr(async({event:$,resolve:Fe})=>ye($.request,({request:ds,locale:Be})=>($.request=ds,Fe($,{transformPageChunk:({html:He})=>He.replace("%lang%",Be).replace("%dir%",be(Be))}))),Ue)}else z=Ue;return{handle:z,handleError:cs.handleSvelteKitError()}}function ir(o={}){let e=new O;if(o.middleware)for(let t of o.middleware)e.use(t);if(o.namedMiddleware)for(let[t,s]of Object.entries(o.namedMiddleware))e.register(t,s);return async function({event:s,resolve:r}){let i={event:s,params:s.params??{},locals:s.locals??{}};try{o.app&&!o.app.isBooted()&&await o.app.bootstrap();let n=await e.execute(i,async()=>r(s));return n instanceof Response?n:r(s)}catch(n){if(o.onError){let a=await o.onError(n,s);if(a instanceof Response)return a}return console.error("[Svelar] Unhandled error in hooks:",n),new Response(JSON.stringify({message:process.env.NODE_ENV==="production"?"Internal server error":n.message}),{status:500,headers:{"Content-Type":"application/json"}})}}}function nr(...o){return async function({event:t,resolve:s}){let r=s;for(let i=o.length-1;i>=0;i--){let n=o[i],a=r;r=l=>n({event:l,resolve:a})}return r(t)}}var ar=y(()=>{"use strict";ae();Ms();Vs();rr()});function Mi(o,e){let t=process.env[o];return t===void 0?e!==void 0?e:"":t==="true"?!0:t==="false"?!1:t==="null"?null:/^\d+$/.test(t)?Number(t):t}var or,Ni,Ii=y(()=>{"use strict";S();or=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:n}=await import("fs"),{pathToFileURL:a}=await import("url"),l=t(e);if(!i(l))return[];let c=n(l).filter(p=>(p.endsWith(".ts")||p.endsWith(".js"))&&!p.startsWith(".")),d=[];for(let p of c){let h=s(p,r(p)),u=t(l,p);try{let x=await import(a(u).href),k=x.default??x.config??x;k&&typeof k=="object"&&!Array.isArray(k)&&(this.set(h,k),d.push(h))}catch{}}return d}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 n=1;n<s.length-1;n++)(i[s[n]]===void 0||typeof i[s[n]]!="object")&&(i[s[n]]={}),i=i[s[n]];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}},Ni=w("svelar.config",()=>new or)});import{z as R}from"zod";function ji(o,e){let t=o.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"],n=s;for(let l=0;l<i.length-1;l++){let c=i[l];c in n||(n[c]={}),n=n[c]}let a=i[i.length-1];n[a]||(n[a]=[]),n[a].push(r.message)}return{success:!1,errors:s}}var _i,Oi=y(()=>{"use strict";_i={required:()=>R.string().min(1,"This field is required"),email:()=>R.string().email("Must be a valid email address"),string:(o,e)=>{let t=R.string();return o!==void 0&&(t=t.min(o)),e!==void 0&&(t=t.max(e)),t},number:(o,e)=>{let t=R.number();return o!==void 0&&(t=t.min(o)),e!==void 0&&(t=t.max(e)),t},integer:()=>R.number().int(),boolean:()=>R.boolean(),date:()=>R.coerce.date(),url:()=>R.string().url(),uuid:()=>R.string().uuid(),enum:o=>R.enum(o),array:o=>R.array(o),nullable:o=>o.nullable(),optional:o=>o.optional(),confirmed:(o="password")=>R.object({[o]:R.string(),[`${o}_confirmation`]:R.string()}).refine(e=>e[o]===e[`${o}_confirmation`],{message:"Confirmation does not match",path:[`${o}_confirmation`]}),min:o=>R.number().min(o),max:o=>R.number().max(o),between:(o,e)=>R.number().min(o).max(e),regex:(o,e)=>R.string().regex(o,e),ip:()=>R.string().refine(o=>{let e=o.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:()=>R.string().refine(o=>{try{return JSON.parse(o),!0}catch{return!1}},{message:"Must be valid JSON"})}});var qi={};E(qi,{FormAuthorizationError:()=>ge,FormRequest:()=>Oe,FormValidationError:()=>he});var Oe,he,ge,lr=y(()=>{"use strict";Oe=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new he(e)}failedAuthorization(){throw new ge}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},a=t.rules().safeParse(i);if(!a.success){let l={},c=t.messages(),d=t.attributes();for(let p of a.error.issues){let h=p.path.join("."),u=d[h]??h;l[u]||(l[u]=[]);let v=`${h}.${p.code}`,x=c[v]??c[h];l[u].push(x??p.message)}t.failedValidation(l)}return t.passedValidation(a.data)}},he=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"}})}},ge=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 Ui,writeFile as eo,unlink as to,mkdir as qe,readdir as cr,stat as Fi,copyFile as so,rename as ro}from"fs/promises";import{existsSync as io}from"fs";import{join as no,dirname as Qt}from"path";var dr,Gt,ur,Bi,Hi=y(()=>{"use strict";S();dr=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return no(this.config.root,e)}async get(e){return Ui(this.resolve(e))}async getText(e){return Ui(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await qe(Qt(s),{recursive:!0}),await eo(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await qe(Qt(r),{recursive:!0}),await s(r,t)}async exists(e){return io(this.resolve(e))}async delete(e){try{return await to(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await qe(Qt(s),{recursive:!0}),await so(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await qe(Qt(s),{recursive:!0}),await ro(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await cr(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 cr(s,{withFileTypes:!0});for(let i of r){let n=e?`${e}/${i.name}`:i.name;i.isFile()?t.push(n):i.isDirectory()&&t.push(...await this.allFiles(n))}}catch{}return t}async directories(e=""){let t=this.resolve(e);try{return(await cr(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await qe(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 Fi(this.resolve(e))).size}async lastModified(e){return(await Fi(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},Gt=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(n=>n.Key).filter(n=>n!==r).map(n=>{let a=this.config.prefix;return a?n.slice(a.length+1):n})}catch{return[]}}async allFiles(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:""),i=[],n;do{let a=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:n}));for(let l of a.Contents??[]){let c=this.config.prefix,d=c?l.Key.slice(c.length+1):l.Key;d&&i.push(d)}n=a.IsTruncated?a.NextContinuationToken:void 0}while(n);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(n=>{let a=this.config.prefix;return(a?n.Prefix.slice(a.length+1):n.Prefix).replace(/\/$/,"")}).filter(n=>n.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(),n=new r.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)});return await s.getSignedUrl(i,n,{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}))}}},ur=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 dr(e);case"s3":return new Gt(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof Gt))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},Bi=w("svelar.storage",()=>new ur)});import{readFile as ao,writeFile as oo,unlink as zi,mkdir as Ki}from"fs/promises";import{join as lo,dirname as co}from"path";import{createHash as uo}from"crypto";var mr,pr,hr,gr,Wi,Ji=y(()=>{"use strict";S();mr=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)}},pr=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=uo("md5").update(e).digest("hex");return lo(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await ao(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await zi(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 Ki(co(r),{recursive:!0}),await oo(r,JSON.stringify(i))}async forget(e){try{return await zi(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 Ki(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)}},hr=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}},gr=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 mr;case"file":return new pr(e);case"null":return new hr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},Wi=w("svelar.cache",()=>new gr)});var Yt,fr,yr,br,Vi,Qi=y(()=>{"use strict";S();Yt=class{},fr=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(()=>(Ut(),Ks));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)}}},yr=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(()=>(C(),P));await r.raw(`INSERT INTO ${this.table} (id, notifiable_id, type, data, read_at, created_at)
141
+ 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)}}},br=class{channels=new Map;constructor(){this.channels.set("mail",new fr),this.channels.set("database",new yr)}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 n of i){let a=this.channels.get(n);if(a)try{await a.send(r,t)}catch(l){console.error(`[Notifications] Channel "${n}" failed:`,l)}else console.warn(`[Notifications] Unknown channel: ${n}`)}}}async sendVia(e,t,s){for(let r of s){let i=this.channels.get(r);i&&await i.send(e,t)}}},Vi=w("svelar.notifier",()=>new br)});function vr(o){return o.startsWith("private-")?"private":o.startsWith("presence-")?"presence":"public"}var wr,Zt,Cr,xr,Gi,Yi=y(()=>{"use strict";S();wr=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=vr(e)}stream(e,t){let s=this,r=new ReadableStream({start(i){let n={channel:s.name};s.type==="presence"&&(n.members=s.getMembers());let a=`event: connected
142
+ data: ${JSON.stringify(n)}
143
143
  id: ${Date.now()}
144
144
 
145
- `;n.enqueue(new TextEncoder().encode(a));let o={controller:n,userId:e,userInfo:t};s.subscribers.push(o),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},o)},cancel(){let n=s.subscribers.findIndex(a=>a.controller===this._controller),i=s.subscribers.length;s.subscribers=s.subscribers.filter(a=>{try{return a.controller.enqueue(new TextEncoder().encode(`:
145
+ `;i.enqueue(new TextEncoder().encode(a));let l={controller:i,userId:e,userInfo:t};s.subscribers.push(l),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},l)},cancel(){let i=s.subscribers.findIndex(a=>a.controller===this._controller),n=s.subscribers.length;s.subscribers=s.subscribers.filter(a=>{try{return a.controller.enqueue(new TextEncoder().encode(`:
146
146
 
147
- `)),!0}catch{return!1}}),s.type==="presence"&&e!==void 0&&s.subscribers.length<i&&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
+ `)),!0}catch{return!1}}),s.type==="presence"&&e!==void 0&&s.subscribers.length<n&&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}
148
148
  data: ${JSON.stringify(t)}
149
149
  id: ${Date.now()}
150
150
 
151
- `,n=new TextEncoder().encode(r);for(let i of this.subscribers)if(!(s!==void 0&&i.userId!==s))try{i.controller.enqueue(n)}catch{}}sendInternal(e,t,s){let r=`event: ${e}
151
+ `,i=new TextEncoder().encode(r);for(let n of this.subscribers)if(!(s!==void 0&&n.userId!==s))try{n.controller.enqueue(i)}catch{}}sendInternal(e,t,s){let r=`event: ${e}
152
152
  data: ${JSON.stringify(t)}
153
153
  id: ${Date.now()}
154
154
 
155
- `,n=new TextEncoder().encode(r);for(let i of this.subscribers)if(i!==s)try{i.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}
155
+ `,i=new TextEncoder().encode(r);for(let n of this.subscribers)if(n!==s)try{n.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}
156
156
  data: ${JSON.stringify(t)}
157
157
  id: ${Date.now()}
158
158
 
159
- `,n=new TextEncoder().encode(r);for(let i of this.subscribers)if(i.userId!==s)try{i.controller.enqueue(n)}catch{}}},Xt=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)}),i=Math.floor(Date.now()/1e3).toString(),a=await this.md5(n),o=["POST",`/apps/${this.config.appId}/events`,[`auth_key=${this.config.key}`,`auth_timestamp=${i}`,"auth_version=1.0",`body_md5=${a}`].join("&")].join(`
160
- `),c=await this.hmacSha256(this.config.secret,o),u=this.config.useTLS!==!1?"https":"http",d=this.config.host??`api-${this.config.cluster??"mt1"}.pusher.com`,p=this.config.port??(this.config.useTLS!==!1?443:80),f=`${u}://${d}:${p}/apps/${this.config.appId}/events?auth_key=${this.config.key}&auth_timestamp=${i}&auth_version=1.0&body_md5=${a}&auth_signature=${c}`,y=await fetch(f,{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(!y.ok){let S=await y.text();throw new Error(`Pusher API error (${y.status}): ${S}`)}}async authenticate(e,t,s){let r=`${e}:${t}`,n;s&&(n=JSON.stringify(s),r+=`:${n}`);let i=await this.hmacSha256(this.config.secret,r),a=`${this.config.key}:${i}`;return n?{auth:a,channel_data:n}:{auth:a}}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")}},br=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)}},wr=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 Xt(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new vr(e)),this.sseChannels.get(e)}async authorize(e,t){if(yr(e)==="public")return!0;for(let[r,n]of this.channelAuth){let i=this.matchPattern(r,e);if(i!==null)return await n(t,i)}return!1}async authenticatePusher(e,t,s){if(!this.pusherDriver)throw new Error("Pusher driver is not configured. Call Broadcast.configure() first.");let r=yr(e);if(r==="public")return!1;let n=await this.authorize(e,s);if(n===!1)return!1;if(r==="presence"){let i=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,i)}return this.pusherDriver.authenticate(t,e)}event(e,t){return new br(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 Xt(n)),await this.pusherDriver.send(e,t,s);break;case"log":console.log(`[Broadcast] ${e} \u2192 ${t}:`,JSON.stringify(s));break;default:for(let[,i]of this.sseChannels)i.name===e&&i.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,o=>o==="{"||o==="}"?o:`\\${o}`).replace(/\\\{(\w+)\\\}/g,(o,c)=>(s.push(c),"([^.]+)")).replace(/\{(\w+)\}/g,(o,c)=>(s.push(c),"([^.]+)")),n=new RegExp(`^${r}$`),i=t.match(n);if(!i)return null;let a={};for(let o=0;o<s.length;o++)a[s[o]]=i[o+1];return a}},Vi=w("svelar.broadcast",()=>new wr)});function Zt(l,e,t){Gi&&Gi(l,e,{description:t})}async function Yi(l,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:n={},...i}=e,a=(i.method||"GET").toUpperCase(),o=new Headers(i.headers);if(["POST","PUT","PATCH","DELETE"].includes(a)){let c=Cr(t);c&&o.set(s,c)}i.body&&typeof i.body=="string"&&!o.has("Content-Type")&&o.set("Content-Type","application/json"),o.has("Accept")||o.set("Accept","application/json");try{let c=await fetch(l,{...i,headers:o});return!c.ok&&r&&await fo(c,{...go,...n}),c}catch(c){throw r&&Zt("error","Network Error","Unable to connect. Check your internet connection."),c}}async function fo(l,e){let t="";try{if((l.headers.get("content-type")??"").includes("application/json")){let i=await l.clone().json();if(t=i.message??"",l.status===422&&i.errors){let a=Object.entries(i.errors).map(([o,c])=>`${o}: ${c.join(", ")}`).slice(0,3).join(`
161
- `);Zt("warning",e[422]??"Validation Error",a);return}}}catch{}let s=t||e[l.status]||`Error ${l.status}`,r=l.status>=500?"error":l.status===429?"warning":"error";if(l.status===401){Zt("warning",s,"Please sign in to continue.");return}Zt(r,s)}function Cr(l="XSRF-TOKEN"){if(typeof document>"u")return null;let e=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function Xi(l,e){if(!e)return l;let t=new URL(l,"http://localhost");for(let[s,r]of Object.entries(e))r!=null&&t.searchParams.set(s,String(r));return t.pathname+t.search}var go,Gi,xr,ye,Tu,Zi=v(()=>{"use strict";go={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."},Gi=null;xr=class l{_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 l;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},i;s!==void 0&&(n["Content-Type"]||(n["Content-Type"]="application/json"),i=typeof s=="string"?s:JSON.stringify(s)),n.Accept||(n.Accept="application/json");let a=null,o=1+this._retries;for(let c=0;c<o;c++){c>0&&await new Promise(u=>setTimeout(u,this._retryDelay*c));try{let u=new AbortController,d=setTimeout(()=>u.abort(),this._timeout),p=await fetch(r,{method:e,headers:n,body:i,signal:u.signal});if(clearTimeout(d),!p.ok&&p.status<500&&c<o-1,!p.ok&&p.status>=500&&c<o-1){a=new ye(`HTTP ${p.status}: ${p.statusText}`,p.status,await p.text());continue}let f=p.headers.get("content-type")??"",y;if(f.includes("application/json")?y=await p.json():y=await p.text(),!p.ok)throw new ye(`HTTP ${p.status}: ${typeof y=="string"?y:JSON.stringify(y)}`,p.status,y);return{data:y,status:p.status,headers:p.headers,ok:!0}}catch(u){if(u instanceof ye)throw u;if(a=u,u.name==="AbortError"&&(a=new ye("Request timed out",0,null)),c>=o-1)break}}throw a??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,i]of s)r.searchParams.set(n,i);t=r.toString()}return t}},ye=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},Tu=new xr});function en(l){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=l;return({event:n,resolve:i})=>e(n.request,({request:a,locale:o})=>(n.request=a,i(n,{transformPageChunk:({html:c})=>c.replace(s,o).replace(r,t(o))})))}function tn(l){return e=>l.deLocalizeUrl(e.url).pathname}var sn=v(()=>{"use strict"});function rn(l,e,t={}){return async s=>{let{superValidate:r,fail:n,message:i}=await import("sveltekit-superforms"),{zod:a}=await import("sveltekit-superforms/adapters"),o=await r(s,a(l));if(!o.valid)return n(400,{form:o});try{let c=await e(o.data,s);if(t.redirectTo){let{redirect:u}=await import("@sveltejs/kit");throw u(303,t.redirectTo)}return c??{form:o}}catch(c){if(c?.status>=300&&c?.status<400)throw c;return i(o,t.errorMessage||c.message||"An error occurred",{status:c.status||400})}}}async function nn(l,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(l))}async function an(l,e){let t=await l.request.formData(),s={};for(let[n,i]of t.entries())s[n]=i;let r=e.safeParse(s);if(!r.success){let{FormValidationError:n}=await Promise.resolve().then(()=>(ar(),Ii));throw new n(r.error.flatten().fieldErrors)}return r.data}var on=v(()=>{"use strict"});var ln={};E(ln,{Application:()=>Dt,AuthManager:()=>Ft,AuthenticateMiddleware:()=>pe,BelongsTo:()=>ee,BelongsToMany:()=>te,Broadcast:()=>Vi,Cache:()=>zi,ColumnBuilder:()=>I,Connection:()=>g,Container:()=>H,Controller:()=>Ot,CorsMiddleware:()=>Nt,CsrfMiddleware:()=>ie,DatabaseSessionStore:()=>jt,ErrorHandler:()=>he,Event:()=>se,EventDispatcher:()=>Ae,FileSessionStore:()=>It,ForbiddenError:()=>_e,FormAuthorizationError:()=>fe,FormRequest:()=>Ue,FormValidationError:()=>ge,HasMany:()=>Z,HasOne:()=>X,Hash:()=>Ms,HttpError:()=>D,Job:()=>Q,Log:()=>zt,LoggingMiddleware:()=>_t,Mailable:()=>Ie,Mailer:()=>Bs,MemorySessionStore:()=>z,Middleware:()=>R,MiddlewareStack:()=>q,Migration:()=>Ce,Migrator:()=>Pe,Model:()=>$t,ModelNotFoundError:()=>Jt,NotFoundError:()=>De,Notification:()=>Yt,Notifier:()=>Wi,OriginMiddleware:()=>ne,QueryBuilder:()=>N,Queue:()=>Rs,RateLimitMiddleware:()=>re,RedisSessionStore:()=>Lt,RequireAuthMiddleware:()=>Bt,Schema:()=>L,Seeder:()=>At,ServiceProvider:()=>$e,Session:()=>ce,SessionMiddleware:()=>de,SignatureMiddleware:()=>Mt,Storage:()=>Ui,TableBuilder:()=>J,ThrottleMiddleware:()=>ae,UnauthorizedError:()=>Ne,ValidationError:()=>U,abort:()=>Vt,abortIf:()=>ki,abortUnless:()=>$i,apiFetch:()=>Yi,buildUrl:()=>Xi,config:()=>Ni,container:()=>fi,createFormAction:()=>rn,createI18nHandle:()=>en,createReroute:()=>tn,createSvelarApp:()=>Ai,createSvelarHooks:()=>sr,env:()=>Di,getCsrfToken:()=>Cr,loadForm:()=>nn,resource:()=>vi,rules:()=>Mi,schema:()=>ri,sequence:()=>rr,signJwt:()=>zs,validate:()=>Oi,validateForm:()=>an,verifyJwt:()=>Ks,z:()=>P});var cn=v(()=>{"use strict";hi();Es();ks();x();fs();ys();gi();As();$s();yi();oe();bi();ir();_i();ji();Ws();ue();Ds();tr();kt();ar();Fi();Xs();Ki();G();Ut();Ji();Qi();Zi();sn();on();ir()});var Sr={};E(Sr,{PluginRegistry:()=>rs});var Pr,rs,is=v(()=>{"use strict";T();Pr=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=[],i=e(process.cwd(),"node_modules");if(!t(i))return n;try{let a=s(i,{withFileTypes:!0});for(let o of a){if(!o.isDirectory())continue;let c=o.name;if(c.startsWith("."))continue;let u=c.startsWith("svelar-");if(!u)continue;let d=e(i,c,"package.json");if(t(d))try{let p=await r(d,"utf-8"),f=JSON.parse(p),y=f.keywords?.includes("svelar-plugin");if(!u&&!y)continue;let S={name:f.name||c,version:f.version||"0.0.0",description:f.description||"",packageName:c,installed:!0,enabled:!1,hasConfig:!!f.svelar?.config,hasMigrations:!!f.svelar?.migrations};n.push(S),this.plugins.set(S.name,S)}catch{}}}catch{}return 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)}},rs=w("svelar.pluginRegistry",()=>new Pr)});var dn={};E(dn,{PluginPublisher:()=>Rr});var Tr,Rr,Er=v(()=>{"use strict";T();Tr=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:n,dirname:i}=await import("path"),{existsSync:a}=await import("fs"),o={configs:[],migrations:[],assets:[]},c=e.publishables?.()||{};for(let[u,d]of Object.entries(c))for(let p of d){if(t?.only&&p.type!==t.only)continue;let f=n(process.cwd(),p.dest),y=i(f);if(!(a(f)&&!t?.force))try{await s(y,{recursive:!0}),await r(p.source,f),p.type==="config"?o.configs.push(f):p.type==="migration"?o.migrations.push(f):p.type==="asset"&&o.assets.push(f)}catch(S){console.warn(`Failed to publish ${p.source} to ${f}:`,S)}}return o}async preview(e){let t={configs:[],migrations:[],assets:[]},s=e.publishables?.()||{};for(let[r,n]of Object.entries(s))for(let i of n){let a=He("path").join(process.cwd(),i.dest);i.type==="config"?t.configs.push(a):i.type==="migration"?t.migrations.push(a):i.type==="asset"&&t.assets.push(a)}return t}},Rr=w("svelar.pluginPublisher",()=>new Tr)});var un={};E(un,{PluginInstaller:()=>yo});var kr,yo,mn=v(()=>{"use strict";T();is();Er();kr=class{async install(e,t){let{spawn:s}=await import("child_process"),{promisify:r}=await import("util"),{join:n}=await import("path"),{readFile:i}=await import("fs/promises"),{existsSync:a}=await import("fs");try{await this.runNpmInstall(e);let o=rs,c=await o.discover(),u;for(let p of c)if(p.packageName===e||p.name===e){u=p;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.`};o.enable(u.name);let d=null;if(t?.publish!==!1)try{let p=await this.loadPluginClass(u.packageName);p&&(d=await Rr.publish(new p))}catch(p){console.warn("Failed to publish plugin assets:",p)}return{success:!0,pluginName:u.name,version:u.version,published:d}}catch(o){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:o?.message??String(o)}}}async uninstall(e){try{let t=rs,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}=He("child_process"),n=r("npm",["install",e],{cwd:process.cwd(),stdio:"inherit"});n.on("close",i=>{i===0?t():s(new Error(`npm install exited with code ${i}`))}),n.on("error",s)})}async runNpmUninstall(e){return new Promise((t,s)=>{let{spawn:r}=He("child_process"),n=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});n.on("close",i=>{i===0?t():s(new Error(`npm uninstall exited with code ${i}`))}),n.on("error",s)})}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}},yo=w("svelar.pluginInstaller",()=>new kr)});import{dirname as hn,join as $r}from"path";import{fileURLToPath as gn,pathToFileURL as vo}from"url";import{register as bo}from"module";import{readFileSync as fn,existsSync as wo}from"fs";var ze=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);r||(console.error(`\x1B[31mUnknown command:\x1B[0m ${t}`),console.log("Run \x1B[36msvelar --help\x1B[0m for available commands."),process.exit(1));let{args:n,flags:i}=this.parseArgs(s,r);try{await r.handle(n,i)}catch(a){let o=a instanceof Error?a.message:String(a);console.error(`\x1B[31mError:\x1B[0m ${o}`),a?.stack&&console.error(a.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 i=e[n];if(i.startsWith("--")){let a=i.slice(2),o=a.indexOf("=");if(o!==-1){let d=a.slice(0,o);r[d]=a.slice(o+1);continue}let c=a;t.flags.find(d=>d.name===c)?.type==="boolean"?r[c]=!0:n+1<e.length&&!e[n+1].startsWith("-")?r[c]=e[++n]:r[c]=!0}else if(i.startsWith("-")&&i.length===2){let a=i.slice(1),o=t.flags.find(c=>c.alias===a);o&&(o.type==="boolean"?r[o.name]=!0:n+1<e.length&&(r[o.name]=e[++n]))}else s.push(i)}return{args:s,flags:r}}showHelp(){console.log(`
159
+ `,i=new TextEncoder().encode(r);for(let n of this.subscribers)if(n.userId!==s)try{n.controller.enqueue(i)}catch{}}},Zt=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)}),n=Math.floor(Date.now()/1e3).toString(),a=await this.md5(i),l=["POST",`/apps/${this.config.appId}/events`,[`auth_key=${this.config.key}`,`auth_timestamp=${n}`,"auth_version=1.0",`body_md5=${a}`].join("&")].join(`
160
+ `),c=await this.hmacSha256(this.config.secret,l),d=this.config.useTLS!==!1?"https":"http",p=this.config.host??`api-${this.config.cluster??"mt1"}.pusher.com`,h=this.config.port??(this.config.useTLS!==!1?443:80),u=`${d}://${p}:${h}/apps/${this.config.appId}/events?auth_key=${this.config.key}&auth_timestamp=${n}&auth_version=1.0&body_md5=${a}&auth_signature=${c}`,v=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:i});if(!v.ok){let x=await v.text();throw new Error(`Pusher API error (${v.status}): ${x}`)}}async authenticate(e,t,s){let r=`${e}:${t}`,i;s&&(i=JSON.stringify(s),r+=`:${i}`);let n=await this.hmacSha256(this.config.secret,r),a=`${this.config.key}:${n}`;return i?{auth:a,channel_data:i}:{auth:a}}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")}},Cr=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)}},xr=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 Zt(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new wr(e)),this.sseChannels.get(e)}async authorize(e,t){if(vr(e)==="public")return!0;for(let[r,i]of this.channelAuth){let n=this.matchPattern(r,e);if(n!==null)return await i(t,n)}return!1}async authenticatePusher(e,t,s){if(!this.pusherDriver)throw new Error("Pusher driver is not configured. Call Broadcast.configure() first.");let r=vr(e);if(r==="public")return!1;let i=await this.authorize(e,s);if(i===!1)return!1;if(r==="presence"){let n=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,n)}return this.pusherDriver.authenticate(t,e)}event(e,t){return new Cr(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 Zt(i)),await this.pusherDriver.send(e,t,s);break;case"log":console.log(`[Broadcast] ${e} \u2192 ${t}:`,JSON.stringify(s));break;default:for(let[,n]of this.sseChannels)n.name===e&&n.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,l=>l==="{"||l==="}"?l:`\\${l}`).replace(/\\\{(\w+)\\\}/g,(l,c)=>(s.push(c),"([^.]+)")).replace(/\{(\w+)\}/g,(l,c)=>(s.push(c),"([^.]+)")),i=new RegExp(`^${r}$`),n=t.match(i);if(!n)return null;let a={};for(let l=0;l<s.length;l++)a[s[l]]=n[l+1];return a}},Gi=w("svelar.broadcast",()=>new xr)});function Xt(o,e,t){Zi&&Zi(o,e,{description:t})}async function Xi(o,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:i={},...n}=e,a=(n.method||"GET").toUpperCase(),l=new Headers(n.headers);if(["POST","PUT","PATCH","DELETE"].includes(a)){let c=Rr(t);c&&l.set(s,c)}n.body&&typeof n.body=="string"&&!l.has("Content-Type")&&l.set("Content-Type","application/json"),l.has("Accept")||l.set("Accept","application/json");try{let c=await fetch(o,{...n,headers:l});return!c.ok&&r&&await po(c,{...mo,...i}),c}catch(c){throw r&&Xt("error","Network Error","Unable to connect. Check your internet connection."),c}}async function po(o,e){let t="";try{if((o.headers.get("content-type")??"").includes("application/json")){let n=await o.clone().json();if(t=n.message??"",o.status===422&&n.errors){let a=Object.entries(n.errors).map(([l,c])=>`${l}: ${c.join(", ")}`).slice(0,3).join(`
161
+ `);Xt("warning",e[422]??"Validation Error",a);return}}}catch{}let s=t||e[o.status]||`Error ${o.status}`,r=o.status>=500?"error":o.status===429?"warning":"error";if(o.status===401){Xt("warning",s,"Please sign in to continue.");return}Xt(r,s)}function Rr(o="XSRF-TOKEN"){if(typeof document>"u")return null;let e=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function en(o,e){if(!e)return o;let t=new URL(o,"http://localhost");for(let[s,r]of Object.entries(e))r!=null&&t.searchParams.set(s,String(r));return t.pathname+t.search}var mo,Zi,Pr,fe,Cu,tn=y(()=>{"use strict";mo={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."},Zi=null;Pr=class o{_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 o;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},n;s!==void 0&&(i["Content-Type"]||(i["Content-Type"]="application/json"),n=typeof s=="string"?s:JSON.stringify(s)),i.Accept||(i.Accept="application/json");let a=null,l=1+this._retries;for(let c=0;c<l;c++){c>0&&await new Promise(d=>setTimeout(d,this._retryDelay*c));try{let d=new AbortController,p=setTimeout(()=>d.abort(),this._timeout),h=await fetch(r,{method:e,headers:i,body:n,signal:d.signal});if(clearTimeout(p),!h.ok&&h.status<500&&c<l-1,!h.ok&&h.status>=500&&c<l-1){a=new fe(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let u=h.headers.get("content-type")??"",v;if(u.includes("application/json")?v=await h.json():v=await h.text(),!h.ok)throw new fe(`HTTP ${h.status}: ${typeof v=="string"?v:JSON.stringify(v)}`,h.status,v);return{data:v,status:h.status,headers:h.headers,ok:!0}}catch(d){if(d instanceof fe)throw d;if(a=d,d.name==="AbortError"&&(a=new fe("Request timed out",0,null)),c>=l-1)break}}throw a??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,n]of s)r.searchParams.set(i,n);t=r.toString()}return t}},fe=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},Cu=new Pr});function sn(o){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=o;return({event:i,resolve:n})=>e(i.request,({request:a,locale:l})=>(i.request=a,n(i,{transformPageChunk:({html:c})=>c.replace(s,l).replace(r,t(l))})))}function rn(o){return e=>o.deLocalizeUrl(e.url).pathname}var nn=y(()=>{"use strict"});function an(o,e,t={}){return async s=>{let{superValidate:r,fail:i,message:n}=await import("sveltekit-superforms"),{zod:a}=await import("sveltekit-superforms/adapters"),l=await r(s,a(o));if(!l.valid)return i(400,{form:l});try{let c=await e(l.data,s);if(t.redirectTo){let{redirect:d}=await import("@sveltejs/kit");throw d(303,t.redirectTo)}return c??{form:l}}catch(c){if(c?.status>=300&&c?.status<400)throw c;return n(l,t.errorMessage||c.message||"An error occurred",{status:c.status||400})}}}async function on(o,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(o))}async function ln(o,e){let t=await o.request.formData(),s={};for(let[i,n]of t.entries())s[i]=n;let r=e.safeParse(s);if(!r.success){let{FormValidationError:i}=await Promise.resolve().then(()=>(lr(),qi));throw new i(r.error.flatten().fieldErrors)}return r.data}var cn=y(()=>{"use strict"});var dn={};E(dn,{Application:()=>Dt,AuthManager:()=>Ft,AuthenticateMiddleware:()=>me,BelongsTo:()=>X,BelongsToMany:()=>ee,Broadcast:()=>Gi,Cache:()=>Wi,ColumnBuilder:()=>_,Connection:()=>f,Container:()=>B,Controller:()=>It,CorsMiddleware:()=>Lt,CsrfMiddleware:()=>re,DatabaseSessionStore:()=>_t,ErrorHandler:()=>pe,Event:()=>te,EventDispatcher:()=>ke,FileSessionStore:()=>jt,ForbiddenError:()=>De,FormAuthorizationError:()=>ge,FormRequest:()=>Oe,FormValidationError:()=>he,HasMany:()=>Z,HasOne:()=>Y,Hash:()=>_s,HttpError:()=>D,Job:()=>V,Log:()=>zt,LoggingMiddleware:()=>Mt,Mailable:()=>Ie,Mailer:()=>zs,MemorySessionStore:()=>H,Middleware:()=>T,MiddlewareStack:()=>O,Migration:()=>we,Migrator:()=>Ce,Model:()=>$t,ModelNotFoundError:()=>Jt,NotFoundError:()=>$e,Notification:()=>Yt,Notifier:()=>Vi,OriginMiddleware:()=>ie,QueryBuilder:()=>L,Queue:()=>ks,RateLimitMiddleware:()=>se,RedisSessionStore:()=>Ot,RequireAuthMiddleware:()=>Bt,Schema:()=>j,Seeder:()=>At,ServiceProvider:()=>Ee,Session:()=>le,SessionMiddleware:()=>ce,SignatureMiddleware:()=>Nt,Storage:()=>Bi,TableBuilder:()=>W,ThrottleMiddleware:()=>ne,UnauthorizedError:()=>Ae,ValidationError:()=>q,abort:()=>Vt,abortIf:()=>Ai,abortUnless:()=>Di,apiFetch:()=>Xi,buildUrl:()=>en,config:()=>Ni,container:()=>bi,createFormAction:()=>an,createI18nHandle:()=>sn,createReroute:()=>rn,createSvelarApp:()=>Li,createSvelarHooks:()=>ir,env:()=>Mi,getCsrfToken:()=>Rr,loadForm:()=>on,resource:()=>wi,rules:()=>_i,schema:()=>ni,sequence:()=>nr,signJwt:()=>Ws,validate:()=>ji,validateForm:()=>ln,verifyJwt:()=>Js,z:()=>R});var un=y(()=>{"use strict";fi();$s();As();C();bs();vs();yi();Ls();Ds();vi();ae();Ci();ar();Ii();Oi();Vs();de();Ms();rr();kt();lr();Hi();er();Ji();Q();Ut();Qi();Yi();tn();nn();cn();ar()});var Er={};E(Er,{PluginRegistry:()=>rs});var Tr,rs,is=y(()=>{"use strict";S();Tr=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=[],n=e(process.cwd(),"node_modules");if(!t(n))return i;try{let a=s(n,{withFileTypes:!0});for(let l of a){if(!l.isDirectory())continue;let c=l.name;if(c.startsWith("."))continue;let d=c.startsWith("svelar-");if(!d)continue;let p=e(n,c,"package.json");if(t(p))try{let h=await r(p,"utf-8"),u=JSON.parse(h),v=u.keywords?.includes("svelar-plugin");if(!d&&!v)continue;let x={name:u.name||c,version:u.version||"0.0.0",description:u.description||"",packageName:c,installed:!0,enabled:!1,hasConfig:!!u.svelar?.config,hasMigrations:!!u.svelar?.migrations};i.push(x),this.plugins.set(x.name,x)}catch{}}}catch{}return 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)}},rs=w("svelar.pluginRegistry",()=>new Tr)});var pn={};E(pn,{PluginPublisher:()=>$r});var kr,$r,Ar=y(()=>{"use strict";S();kr=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:i,dirname:n}=await import("path"),{existsSync:a}=await import("fs"),l={configs:[],migrations:[],assets:[]},c=e.publishables?.()||{};for(let[d,p]of Object.entries(c))for(let h of p){if(t?.only&&h.type!==t.only)continue;let u=i(process.cwd(),h.dest),v=n(u);if(!(a(u)&&!t?.force))try{await s(v,{recursive:!0}),await r(h.source,u),h.type==="config"?l.configs.push(u):h.type==="migration"?l.migrations.push(u):h.type==="asset"&&l.assets.push(u)}catch(x){console.warn(`Failed to publish ${h.source} to ${u}:`,x)}}return l}async preview(e){let t={configs:[],migrations:[],assets:[]},s=e.publishables?.()||{};for(let[r,i]of Object.entries(s))for(let n of i){let a=ze("path").join(process.cwd(),n.dest);n.type==="config"?t.configs.push(a):n.type==="migration"?t.migrations.push(a):n.type==="asset"&&t.assets.push(a)}return t}},$r=w("svelar.pluginPublisher",()=>new kr)});var hn={};E(hn,{PluginInstaller:()=>yo});var Dr,yo,gn=y(()=>{"use strict";S();is();Ar();Dr=class{async install(e,t){let{spawn:s}=await import("child_process"),{promisify:r}=await import("util"),{join:i}=await import("path"),{readFile:n}=await import("fs/promises"),{existsSync:a}=await import("fs");try{await this.runNpmInstall(e);let l=rs,c=await l.discover(),d;for(let h of c)if(h.packageName===e||h.name===e){d=h;break}if(!d)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.`};l.enable(d.name);let p=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(d.packageName);h&&(p=await $r.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:d.name,version:d.version,published:p}}catch(l){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:l?.message??String(l)}}}async uninstall(e){try{let t=rs,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}=ze("child_process"),i=r("npm",["install",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",n=>{n===0?t():s(new Error(`npm install exited with code ${n}`))}),i.on("error",s)})}async runNpmUninstall(e){return new Promise((t,s)=>{let{spawn:r}=ze("child_process"),i=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",n=>{n===0?t():s(new Error(`npm uninstall exited with code ${n}`))}),i.on("error",s)})}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}},yo=w("svelar.pluginInstaller",()=>new Dr)});import{dirname as yn,join as Lr}from"path";import{fileURLToPath as bn,pathToFileURL as bo}from"url";import{register as vo}from"module";import{readFileSync as vn,existsSync as wo}from"fs";var Ke=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:n}=this.parseArgs(s,r);try{await r.handle(i,n)}catch(a){let l=a instanceof Error?a.message:String(a);console.error(`\x1B[31mError:\x1B[0m ${l}`),a?.stack&&console.error(a.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 n=e[i];if(n.startsWith("--")){let a=n.slice(2),l=a.indexOf("=");if(l!==-1){let p=a.slice(0,l);r[p]=a.slice(l+1);continue}let c=a;t.flags.find(p=>p.name===c)?.type==="boolean"?r[c]=!0:i+1<e.length&&!e[i+1].startsWith("-")?r[c]=e[++i]:r[c]=!0}else if(n.startsWith("-")&&n.length===2){let a=n.slice(1),l=t.flags.find(c=>c.alias===a);l&&(l.type==="boolean"?r[l.name]=!0:i+1<e.length&&(r[l.name]=e[++i]))}else s.push(n)}return{args:s,flags:r}}showCommandHelp(e){if(console.log(`
162
+ \x1B[33mDescription:\x1B[0m`),console.log(` ${e.description}
163
+ `),console.log("\x1B[33mUsage:\x1B[0m"),console.log(` svelar ${e.name} [options]
164
+ `),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(`
162
165
  \x1B[36m ____ _
163
166
  / ___|_ _____| | __ _ _ __
164
167
  \\___ \\ \\ / / _ \\ |/ _\` | '__|
@@ -169,7 +172,7 @@ id: ${Date.now()}
169
172
  svelar <command> [arguments] [options]
170
173
 
171
174
  \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(`
172
- \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()}};var h=class{arguments=[];flags=[];async bootstrap(){let{join:e}=await import("path"),{existsSync:t,readFileSync:s}=await import("fs"),{Connection:r}=await Promise.resolve().then(()=>(x(),C)),n=process.cwd();try{r.getDriver();return}catch{}let i=e(n,"svelar.database.json");if(t(i))try{let c=s(i,"utf-8"),u=JSON.parse(c);r.configure(u),this.info("Database configured from svelar.database.json");return}catch(c){this.warn(`Failed to parse svelar.database.json: ${String(c?.message??c)}`)}let a=process.env.DB_DRIVER??"sqlite",o=process.env.DB_PATH??"database.db";r.configure({default:a,connections:{[a]:{driver:a,filename:o,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 ${a} database${a==="sqlite"?`: ${o}`:""}`)}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((i,a)=>Math.max(i.length,...t.map(o=>(o[a]??"").length))),r=s.map(i=>"\u2500".repeat(i+2)).join("\u253C"),n=i=>i.map((a,o)=>` ${(a??"").padEnd(s[o])} `).join("\u2502");console.log(n(e)),console.log(r);for(let i of t)console.log(n(i))}newLine(){console.log()}};import{writeFileSync as ds,mkdirSync as us,existsSync as xn}from"fs";import{join as W}from"path";var Ke=class extends h{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.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let i=W(process.cwd(),"src","lib","modules",n);us(i,{recursive:!0});let a=W(i,`${s}.ts`);if(xn(a)){this.warn(`Model ${s} already exists at ${a}`);return}let o=`import { Model } from '@beeblock/svelar/orm';
175
+ \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()}};var g=class{arguments=[];flags=[];async bootstrap(){let{join:e}=await import("path"),{existsSync:t,readFileSync:s}=await import("fs"),{Connection:r}=await Promise.resolve().then(()=>(C(),P)),i=process.cwd();try{r.getDriver();return}catch{}let n=e(i,"svelar.database.json");if(t(n))try{let c=s(n,"utf-8"),d=JSON.parse(c);r.configure(d),this.info("Database configured from svelar.database.json");return}catch(c){this.warn(`Failed to parse svelar.database.json: ${String(c?.message??c)}`)}let a=process.env.DB_DRIVER??"sqlite",l=process.env.DB_PATH??"database.db";r.configure({default:a,connections:{[a]:{driver:a,filename:l,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 ${a} database${a==="sqlite"?`: ${l}`:""}`)}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((n,a)=>Math.max(n.length,...t.map(l=>(l[a]??"").length))),r=s.map(n=>"\u2500".repeat(n+2)).join("\u253C"),i=n=>n.map((a,l)=>` ${(a??"").padEnd(s[l])} `).join("\u2502");console.log(i(e)),console.log(r);for(let n of t)console.log(i(n))}newLine(){console.log()}};import{writeFileSync as ms,mkdirSync as ps,existsSync as Cn}from"fs";import{join as K}from"path";var We=class extends g{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.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let n=K(process.cwd(),"src","lib","modules",i);ps(n,{recursive:!0});let a=K(n,`${s}.ts`);if(Cn(a)){this.warn(`Model ${s} already exists at ${a}`);return}let l=`import { Model } from '@beeblock/svelar/orm';
173
176
 
174
177
  export class ${s} extends Model {
175
178
  static table = '${r}';
@@ -186,7 +189,7 @@ export class ${s} extends Model {
186
189
  // return this.hasMany(Post, 'user_id');
187
190
  // }
188
191
  }
189
- `;if(ds(a,o),this.success(`Model created: src/lib/modules/${n}/${s}.ts`),t.migration||t.all){let u=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,d=W(process.cwd(),"src","lib","database","migrations");us(d,{recursive:!0});let p=`import { Migration } from '@beeblock/svelar/database';
192
+ `;if(ms(a,l),this.success(`Model created: src/lib/modules/${i}/${s}.ts`),t.migration||t.all){let d=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,p=K(process.cwd(),"src","lib","database","migrations");ps(p,{recursive:!0});let h=`import { Migration } from '@beeblock/svelar/database';
190
193
 
191
194
  export default class Create${s}sTable extends Migration {
192
195
  async up() {
@@ -203,7 +206,7 @@ export default class Create${s}sTable extends Migration {
203
206
  await this.schema.dropTable('${r}');
204
207
  }
205
208
  }
206
- `;ds(W(d,`${u}.ts`),p),this.success(`Migration created: src/lib/database/migrations/${u}.ts`)}if(t.controller||t.resource||t.all){let c=`${s}Controller`,u=W(process.cwd(),"src","lib","modules",n);us(u,{recursive:!0});let p=t.resource||t.all?this.generateResourceController(s,c):this.generateBasicController(s,c);ds(W(u,`${c}.ts`),p),this.success(`Controller created: src/lib/modules/${n}/${c}.ts`)}}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
209
+ `;ms(K(p,`${d}.ts`),h),this.success(`Migration created: src/lib/database/migrations/${d}.ts`)}if(t.controller||t.resource||t.all){let c=`${s}Controller`,d=K(process.cwd(),"src","lib","modules",i);ps(d,{recursive:!0});let h=t.resource||t.all?this.generateResourceController(s,c):this.generateBasicController(s,c);ms(K(d,`${c}.ts`),h),this.success(`Controller created: src/lib/modules/${i}/${c}.ts`)}}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
207
210
  import { z } from '@beeblock/svelar/validation';
208
211
  import { ${e} } from './${e}.js';
209
212
 
@@ -255,11 +258,11 @@ export class ${t} extends Controller {
255
258
  return this.json(items);
256
259
  }
257
260
  }
258
- `}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 Cn,mkdirSync as Pn}from"fs";import{join as Nr}from"path";var We=class extends h{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=Nr(process.cwd(),"src","lib","database","migrations");Pn(r,{recursive:!0});let i=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_${s}`,a=this.toPascalCase(s),o=t.create??this.detectTableName(s,"create"),c=t.table??this.detectTableName(s,"add"),u;o?u=`import { Migration } from '@beeblock/svelar/database';
261
+ `}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 xn,mkdirSync as Pn}from"fs";import{join as Nr}from"path";var Je=class extends g{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=Nr(process.cwd(),"src","lib","database","migrations");Pn(r,{recursive:!0});let n=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_${s}`,a=this.toPascalCase(s),l=t.create??this.detectTableName(s,"create"),c=t.table??this.detectTableName(s,"add"),d;l?d=`import { Migration } from '@beeblock/svelar/database';
259
262
 
260
263
  export default class ${a} extends Migration {
261
264
  async up() {
262
- await this.schema.createTable('${o}', (table) => {
265
+ await this.schema.createTable('${l}', (table) => {
263
266
  table.increments('id');
264
267
  // Add your columns here
265
268
  table.timestamps();
@@ -267,10 +270,10 @@ export default class ${a} extends Migration {
267
270
  }
268
271
 
269
272
  async down() {
270
- await this.schema.dropTable('${o}');
273
+ await this.schema.dropTable('${l}');
271
274
  }
272
275
  }
273
- `:c?u=`import { Migration } from '@beeblock/svelar/database';
276
+ `:c?d=`import { Migration } from '@beeblock/svelar/database';
274
277
 
275
278
  export default class ${a} extends Migration {
276
279
  async up() {
@@ -284,7 +287,7 @@ export default class ${a} extends Migration {
284
287
  await this.schema.dropColumn('${c}', 'new_column');
285
288
  }
286
289
  }
287
- `:u=`import { Migration } from '@beeblock/svelar/database';
290
+ `:d=`import { Migration } from '@beeblock/svelar/database';
288
291
 
289
292
  export default class ${a} extends Migration {
290
293
  async up() {
@@ -295,7 +298,7 @@ export default class ${a} extends Migration {
295
298
  // Reverse the migration
296
299
  }
297
300
  }
298
- `,Cn(Nr(r,`${i}.ts`),u),this.success(`Migration created: src/lib/database/migrations/${i}.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 Sn,mkdirSync as Tn,existsSync as Rn}from"fs";import{join as _r}from"path";var Je=class extends h{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$/,""),i=t.module||n.toLowerCase();t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let a=_r(process.cwd(),"src","lib","modules",i);Tn(a,{recursive:!0});let o=_r(a,`${r}.ts`);if(Rn(o)){this.warn(`Controller ${r} already exists.`);return}let c=t.resource?this.generateResourceController(r,t.model):this.generateBasicController(r);Sn(o,c),this.success(`Controller created: src/lib/modules/${i}/${r}.ts`)}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
301
+ `,xn(Nr(r,`${n}.ts`),d),this.success(`Migration created: src/lib/database/migrations/${n}.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 Rn,mkdirSync as Sn,existsSync as Tn}from"fs";import{join as Ir}from"path";var Ve=class extends g{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$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=Ir(process.cwd(),"src","lib","modules",n);Sn(a,{recursive:!0});let l=Ir(a,`${r}.ts`);if(Tn(l)){this.warn(`Controller ${r} already exists.`);return}let c=t.resource?this.generateResourceController(r,t.model):this.generateBasicController(r);Rn(l,c),this.success(`Controller created: src/lib/modules/${n}/${r}.ts`)}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
299
302
  import { z } from '@beeblock/svelar/validation';
300
303
  ${t?`import { ${t} } from './${t}.js';
301
304
  `:""}
@@ -341,7 +344,7 @@ export class ${e} extends Controller {
341
344
  return this.json({ message: 'Hello from ${e}' });
342
345
  }
343
346
  }
344
- `}};import{writeFileSync as En,mkdirSync as kn,existsSync as $n}from"fs";import{join as Mr}from"path";var Ve=class extends h{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=Mr(process.cwd(),"src","lib","shared","middleware");kn(r,{recursive:!0});let n=Mr(r,`${s}.ts`);if($n(n)){this.warn(`Middleware ${s} already exists.`);return}let i=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
347
+ `}};import{writeFileSync as En,mkdirSync as kn,existsSync as $n}from"fs";import{join as _r}from"path";var Qe=class extends g{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=_r(process.cwd(),"src","lib","shared","middleware");kn(r,{recursive:!0});let i=_r(r,`${s}.ts`);if($n(i)){this.warn(`Middleware ${s} already exists.`);return}let n=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
345
348
 
346
349
  export class ${s} extends Middleware {
347
350
  async handle(ctx: MiddlewareContext, next: NextFunction): Promise<Response | void> {
@@ -354,7 +357,7 @@ export class ${s} extends Middleware {
354
357
  return response;
355
358
  }
356
359
  }
357
- `;En(n,i),this.success(`Middleware created: src/lib/shared/middleware/${s}.ts`)}};import{writeFileSync as An,mkdirSync as Dn,existsSync as Nn}from"fs";import{join as Or}from"path";var Qe=class extends h{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=Or(process.cwd(),"src","lib","shared","providers");Dn(r,{recursive:!0});let n=Or(r,`${s}.ts`);if(Nn(n)){this.warn(`Provider ${s} already exists.`);return}let i=`import { ServiceProvider } from '@beeblock/svelar/container';
360
+ `;En(i,n),this.success(`Middleware created: src/lib/shared/middleware/${s}.ts`)}};import{writeFileSync as An,mkdirSync as Dn,existsSync as Ln}from"fs";import{join as jr}from"path";var Ge=class extends g{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=jr(process.cwd(),"src","lib","shared","providers");Dn(r,{recursive:!0});let i=jr(r,`${s}.ts`);if(Ln(i)){this.warn(`Provider ${s} already exists.`);return}let n=`import { ServiceProvider } from '@beeblock/svelar/container';
358
361
  import type { Container } from '@beeblock/svelar/container';
359
362
 
360
363
  export class ${s} extends ServiceProvider {
@@ -375,7 +378,7 @@ export class ${s} extends ServiceProvider {
375
378
  // Initialization logic here
376
379
  }
377
380
  }
378
- `;An(n,i),this.success(`Provider created: src/lib/shared/providers/${s}.ts`)}};import{writeFileSync as _n,mkdirSync as Mn,existsSync as On}from"fs";import{join as jr}from"path";var Ge=class extends h{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=jr(process.cwd(),"src","lib","database","seeders");Mn(r,{recursive:!0});let n=jr(r,`${s}.ts`);if(On(n)){this.warn(`Seeder ${s} already exists.`);return}let i=`import { Seeder } from '@beeblock/svelar/database';
381
+ `;An(i,n),this.success(`Provider created: src/lib/shared/providers/${s}.ts`)}};import{writeFileSync as Mn,mkdirSync as Nn,existsSync as In}from"fs";import{join as Or}from"path";var Ye=class extends g{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=Or(process.cwd(),"src","lib","database","seeders");Nn(r,{recursive:!0});let i=Or(r,`${s}.ts`);if(In(i)){this.warn(`Seeder ${s} already exists.`);return}let n=`import { Seeder } from '@beeblock/svelar/database';
379
382
 
380
383
  export class ${s} extends Seeder {
381
384
  async run(): Promise<void> {
@@ -384,7 +387,7 @@ export class ${s} extends Seeder {
384
387
  // await User.create({ name: 'Admin', email: 'admin@example.com' });
385
388
  }
386
389
  }
387
- `;_n(n,i),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as jn,mkdirSync as In,existsSync as Ln}from"fs";import{join as Ir}from"path";var Ye=class extends h{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$/,""),i=t.module||n.toLowerCase();t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let a=Ir(process.cwd(),"src","lib","modules",i);In(a,{recursive:!0});let o=Ir(a,`${r}.ts`);if(Ln(o)){this.warn(`Service ${r} already exists.`);return}let c=t.crud?this.generateCrudService(r,t.model):this.generateBasicService(r);jn(o,c),this.success(`Service created: src/lib/modules/${i}/${r}.ts`)}generateCrudService(e,t){let s=t||"Model";return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
390
+ `;Mn(i,n),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as _n,mkdirSync as jn,existsSync as On}from"fs";import{join as qr}from"path";var Ze=class extends g{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$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=qr(process.cwd(),"src","lib","modules",n);jn(a,{recursive:!0});let l=qr(a,`${r}.ts`);if(On(l)){this.warn(`Service ${r} already exists.`);return}let c=t.crud?this.generateCrudService(r,t.model):this.generateBasicService(r);_n(l,c),this.success(`Service created: src/lib/modules/${n}/${r}.ts`)}generateCrudService(e,t){let s=t||"Model";return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
388
391
  import { ${s} } from './${s}.js';
389
392
 
390
393
  export class ${e} extends CrudService<${s}> {
@@ -409,7 +412,7 @@ export class ${e} extends Service {
409
412
  }
410
413
  }
411
414
  }
412
- `}};import{writeFileSync as qn,mkdirSync as Un,existsSync as Fn}from"fs";import{join as Lr}from"path";var Xe=class extends h{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$/,""),i=t.module||n.toLowerCase();t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let a=Lr(process.cwd(),"src","lib","modules",i);Un(a,{recursive:!0});let o=Lr(a,`${r}.ts`);if(Fn(o)){this.warn(`Repository ${r} already exists.`);return}let c=t.model||this.inferModelName(r),u=`import { Repository } from '@beeblock/svelar/repositories';
415
+ `}};import{writeFileSync as qn,mkdirSync as Un,existsSync as Fn}from"fs";import{join as Ur}from"path";var Xe=class extends g{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$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=Ur(process.cwd(),"src","lib","modules",n);Un(a,{recursive:!0});let l=Ur(a,`${r}.ts`);if(Fn(l)){this.warn(`Repository ${r} already exists.`);return}let c=t.model||this.inferModelName(r),d=`import { Repository } from '@beeblock/svelar/repositories';
413
416
  import { ${c} } from './${c}.js';
414
417
 
415
418
  export class ${r} extends Repository<${c}> {
@@ -426,7 +429,7 @@ export class ${r} extends Repository<${c}> {
426
429
  // return ${c}.where('active', true).orderBy('name').get();
427
430
  // }
428
431
  }
429
- `;qn(o,u),this.success(`Repository created: src/lib/modules/${i}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as Bn,mkdirSync as Hn,existsSync as zn}from"fs";import{join as qr}from"path";var Ze=class extends h{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$/,""),i=t.module||n.toLowerCase();t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let a=qr(process.cwd(),"src","lib","modules",i);Hn(a,{recursive:!0});let o=qr(a,`${r}.ts`);if(zn(o)){this.warn(`Action ${r} already exists.`);return}let c=`import { Action } from '@beeblock/svelar/actions';
432
+ `;qn(l,d),this.success(`Repository created: src/lib/modules/${n}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as Bn,mkdirSync as Hn,existsSync as zn}from"fs";import{join as Fr}from"path";var et=class extends g{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$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=Fr(process.cwd(),"src","lib","modules",n);Hn(a,{recursive:!0});let l=Fr(a,`${r}.ts`);if(zn(l)){this.warn(`Action ${r} already exists.`);return}let c=`import { Action } from '@beeblock/svelar/actions';
430
433
 
431
434
  interface ${r}Input {
432
435
  // Define input type
@@ -442,7 +445,7 @@ export class ${r} extends Action<${r}Input, ${r}Output> {
442
445
  throw new Error('Not implemented');
443
446
  }
444
447
  }
445
- `;Bn(o,c),this.success(`Action created: src/lib/modules/${i}/${r}.ts`)}};import{writeFileSync as Kn,mkdirSync as Wn,existsSync as Jn}from"fs";import{join as Ur}from"path";var et=class extends h{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$/,""),i=t.module||n.toLowerCase();t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let a=Ur(process.cwd(),"src","lib","modules",i);Wn(a,{recursive:!0});let o=Ur(a,`${r}.ts`);if(Jn(o)){this.warn(`Request ${r} already exists.`);return}let c=`import { FormRequest } from '@beeblock/svelar/routing';
448
+ `;Bn(l,c),this.success(`Action created: src/lib/modules/${n}/${r}.ts`)}};import{writeFileSync as Kn,mkdirSync as Wn,existsSync as Jn}from"fs";import{join as Br}from"path";var tt=class extends g{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$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=Br(process.cwd(),"src","lib","modules",n);Wn(a,{recursive:!0});let l=Br(a,`${r}.ts`);if(Jn(l)){this.warn(`Request ${r} already exists.`);return}let c=`import { FormRequest } from '@beeblock/svelar/routing';
446
449
  import { z } from '@beeblock/svelar/validation';
447
450
 
448
451
  export class ${r} extends FormRequest {
@@ -471,11 +474,11 @@ export class ${r} extends FormRequest {
471
474
  return data;
472
475
  }
473
476
  }
474
- `;Kn(o,c),this.success(`Request created: src/lib/modules/${i}/${r}.ts`)}};import{writeFileSync as Vn,mkdirSync as Qn,existsSync as Gn}from"fs";import{join as Fr}from"path";var tt=class extends h{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=Fr(process.cwd(),"src","lib","shared","plugins");Qn(r,{recursive:!0});let n=Fr(r,`${s}.ts`);if(Gn(n)){this.warn(`Plugin ${s} already exists.`);return}let i=s.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,""),a=`import { Plugin } from '@beeblock/svelar/plugins';
477
+ `;Kn(l,c),this.success(`Request created: src/lib/modules/${n}/${r}.ts`)}};import{writeFileSync as Vn,mkdirSync as Qn,existsSync as Gn}from"fs";import{join as Hr}from"path";var st=class extends g{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=Hr(process.cwd(),"src","lib","shared","plugins");Qn(r,{recursive:!0});let i=Hr(r,`${s}.ts`);if(Gn(i)){this.warn(`Plugin ${s} already exists.`);return}let n=s.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,""),a=`import { Plugin } from '@beeblock/svelar/plugins';
475
478
  import type { Container } from '@beeblock/svelar/container';
476
479
 
477
480
  export class ${s} extends Plugin {
478
- readonly name = '${i}';
481
+ readonly name = '${n}';
479
482
  readonly version = '1.0.0';
480
483
  description = '${s} for Svelar';
481
484
 
@@ -493,7 +496,7 @@ export class ${s} extends Plugin {
493
496
  // Clean up resources
494
497
  }
495
498
  }
496
- `;Vn(n,a),this.success(`Plugin created: src/lib/shared/plugins/${s}.ts`)}};import{writeFileSync as Yn,mkdirSync as Xn,existsSync as Zn}from"fs";import{join as Br}from"path";var st=class extends h{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=Br(process.cwd(),"src","lib","shared","scheduler");Xn(r,{recursive:!0});let n=Br(r,`${s}.ts`);if(Zn(n)){this.warn(`Task ${s} already exists.`);return}let i=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
499
+ `;Vn(i,a),this.success(`Plugin created: src/lib/shared/plugins/${s}.ts`)}};import{writeFileSync as Yn,mkdirSync as Zn,existsSync as Xn}from"fs";import{join as zr}from"path";var rt=class extends g{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=zr(process.cwd(),"src","lib","shared","scheduler");Zn(r,{recursive:!0});let i=zr(r,`${s}.ts`);if(Xn(i)){this.warn(`Task ${s} already exists.`);return}let n=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
497
500
 
498
501
  export class ${s} extends ScheduledTask {
499
502
  name = '${this.toKebabCase(s)}';
@@ -526,7 +529,7 @@ export class ${s} extends ScheduledTask {
526
529
  console.error('${s} failed:', error.message);
527
530
  }
528
531
  }
529
- `;Yn(n,i),this.success(`Scheduled task created: src/lib/shared/scheduler/${s}.ts`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as ea,mkdirSync as ta,existsSync as sa}from"fs";import{join as Hr}from"path";var rt=class extends h{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=Hr(process.cwd(),"src","lib","shared","jobs");ta(r,{recursive:!0});let n=Hr(r,`${s}.ts`);if(sa(n)){this.warn(`Job ${s} already exists.`);return}let i=`import { Job } from '@beeblock/svelar/queue';
532
+ `;Yn(i,n),this.success(`Scheduled task created: src/lib/shared/scheduler/${s}.ts`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as ea,mkdirSync as ta,existsSync as sa}from"fs";import{join as Kr}from"path";var it=class extends g{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=Kr(process.cwd(),"src","lib","shared","jobs");ta(r,{recursive:!0});let i=Kr(r,`${s}.ts`);if(sa(i)){this.warn(`Job ${s} already exists.`);return}let n=`import { Job } from '@beeblock/svelar/queue';
530
533
 
531
534
  export class ${s} extends Job {
532
535
  maxAttempts = 3; // Retry up to 3 times
@@ -550,7 +553,7 @@ export class ${s} extends Job {
550
553
  console.log('${s} retrying, attempt', attempt);
551
554
  }
552
555
  }
553
- `;ea(n,i),this.success(`Job created: src/lib/shared/jobs/${s}.ts`)}};import{writeFileSync as ra,mkdirSync as ia,existsSync as na}from"fs";import{join as zr}from"path";var it=class extends h{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=zr(process.cwd(),"src","lib","shared","commands");ia(n,{recursive:!0});let i=zr(n,`${r}.ts`);if(na(i)){this.warn(`Command ${r} already exists.`);return}let a=t.command??this.deriveCommandName(r),o=`import { Command } from '@beeblock/svelar/cli';
556
+ `;ea(i,n),this.success(`Job created: src/lib/shared/jobs/${s}.ts`)}};import{writeFileSync as ra,mkdirSync as ia,existsSync as na}from"fs";import{join as Wr}from"path";var nt=class extends g{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=Wr(process.cwd(),"src","lib","shared","commands");ia(i,{recursive:!0});let n=Wr(i,`${r}.ts`);if(na(n)){this.warn(`Command ${r} already exists.`);return}let a=t.command??this.deriveCommandName(r),l=`import { Command } from '@beeblock/svelar/cli';
554
557
 
555
558
  export class ${r} extends Command {
556
559
  name = '${a}';
@@ -573,7 +576,7 @@ export class ${r} extends Command {
573
576
  this.success('Done!');
574
577
  }
575
578
  }
576
- `;ra(i,o),this.success(`Command created: src/lib/shared/commands/${r}.ts`),this.info(`Command name: ${a}`),this.newLine(),this.info("Your command will be auto-discovered. Run it with:"),this.log(` npx svelar ${a}`)}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 aa,mkdirSync as oa,existsSync as la}from"fs";import{join as Kr}from"path";var nt=class extends h{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
579
+ `;ra(n,l),this.success(`Command created: src/lib/shared/commands/${r}.ts`),this.info(`Command name: ${a}`),this.newLine(),this.info("Your command will be auto-discovered. Run it with:"),this.log(` npx svelar ${a}`)}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 aa,mkdirSync as oa,existsSync as la}from"fs";import{join as Jr}from"path";var at=class extends g{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
577
580
 
578
581
  export default {
579
582
  name: env('APP_NAME', 'Svelar'),
@@ -782,7 +785,7 @@ export default {
782
785
  },
783
786
  },
784
787
  };
785
- `};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=Kr(process.cwd(),"config");oa(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),n=Kr(s,`${r}.ts`);if(la(n)){this.warn(`Config file config/${r}.ts already exists.`);return}let i=this.templates[r]??this.blankTemplate(r);aa(n,i),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';
788
+ `};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=Jr(process.cwd(),"config");oa(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),i=Jr(s,`${r}.ts`);if(la(i)){this.warn(`Config file config/${r}.ts already exists.`);return}let n=this.templates[r]??this.blankTemplate(r);aa(i,n),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';
786
789
 
787
790
  export default {
788
791
  // Add your ${e} configuration here
@@ -791,7 +794,7 @@ export default {
791
794
  // env<number>('MY_PORT', 3000)
792
795
  // env<boolean>('MY_FLAG', false)
793
796
  };
794
- `}};import{writeFileSync as ca,mkdirSync as da,existsSync as ua}from"fs";import{join as Wr}from"path";var at=class extends h{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=Wr(process.cwd(),"src","lib","shared","channels");da(n,{recursive:!0});let i=Wr(n,`${r}.ts`);if(ua(i)){this.warn(`Channel ${r} already exists.`);return}let a=r.replace(/Channel$/,""),o=a.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),c=a.charAt(0).toLowerCase()+a.slice(1)+"Id",u=t.presence,p=`${u?"presence":"private"}-${o}.{${c}}`,f=u?this.presenceTemplate(r,p,c):this.privateTemplate(r,p,c);ca(i,f),this.success(`Channel created: src/lib/shared/channels/${r}.ts`),this.info(`Channel pattern: ${p}`),this.newLine(),this.info("Register it in src/app.ts or a service provider:"),this.log(` import { register${r} } from './lib/shared/channels/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
797
+ `}};import{writeFileSync as ca,mkdirSync as da,existsSync as ua}from"fs";import{join as Vr}from"path";var ot=class extends g{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=Vr(process.cwd(),"src","lib","shared","channels");da(i,{recursive:!0});let n=Vr(i,`${r}.ts`);if(ua(n)){this.warn(`Channel ${r} already exists.`);return}let a=r.replace(/Channel$/,""),l=a.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),c=a.charAt(0).toLowerCase()+a.slice(1)+"Id",d=t.presence,h=`${d?"presence":"private"}-${l}.{${c}}`,u=d?this.presenceTemplate(r,h,c):this.privateTemplate(r,h,c);ca(n,u),this.success(`Channel created: src/lib/shared/channels/${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 './lib/shared/channels/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
795
798
 
796
799
  /**
797
800
  * ${e}
@@ -834,7 +837,7 @@ export function register${e}(): void {
834
837
  };
835
838
  });
836
839
  }
837
- `}};import{writeFileSync as ma,mkdirSync as pa,existsSync as ha}from"fs";import{join as xe}from"path";var ot=class extends h{name="make:docker";description="Scaffold Docker deployment files (Dockerfile, docker-compose.yml, PM2 config)";arguments=[];flags=[{name:"db",alias:"d",description:"Database driver: postgres, mysql, sqlite (default: postgres)",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:"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,i=t.redis??!0,a=t.gotenberg??!0,o=t.rustfs??!0,c=t.force??!1,u=["postgres","mysql","sqlite"];if(!u.includes(r)){this.error(`Unknown database driver: ${r}. Use one of: ${u.join(", ")}`);return}let d=[{path:xe(s,"Dockerfile"),content:this.dockerfileTemplate(),label:"Dockerfile"},{path:xe(s,"docker-compose.yml"),content:this.composeTemplate(r,n,i,a,o),label:"docker-compose.yml"},{path:xe(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:xe(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"}],p=0,f=0;for(let y of d){if(ha(y.path)&&!c){this.warn(`${y.label} already exists (use --force to overwrite)`),f++;continue}ma(y.path,y.content),this.success(`Created ${y.label}`),p++}if(r!=="sqlite"){let y=xe(s,"docker");pa(y,{recursive:!0})}this.newLine(),p>0?this.info(`${p} file(s) created${f>0?`, ${f} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Quick start:"),this.log(" # Build and start all services"),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(" docker compose logs -f app"),this.newLine(),this.log(" # Stop services"),this.log(" docker compose down"),this.newLine(),this.info("Make sure to update .env with production values before deploying.")}dockerfileTemplate(){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
840
+ `}};import{writeFileSync as ma,mkdirSync as pa,existsSync as ha}from"fs";import{join as ve}from"path";var lt=class extends g{name="make:docker";description="Scaffold Docker deployment files (Dockerfile, docker-compose.yml, PM2 config)";arguments=[];flags=[{name:"db",alias:"d",description:"Database driver: postgres, mysql, sqlite (default: postgres)",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,n=t.redis??!0,a=t.gotenberg??!0,l=t.rustfs??!0,c=t.meilisearch??!1,d=t.force??!1,p=["postgres","mysql","sqlite"];if(!p.includes(r)){this.error(`Unknown database driver: ${r}. Use one of: ${p.join(", ")}`);return}let h=[{path:ve(s,"Dockerfile"),content:this.dockerfileTemplate(),label:"Dockerfile"},{path:ve(s,"docker-compose.yml"),content:this.composeTemplate(r,i,n,a,l,c),label:"docker-compose.yml"},{path:ve(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:ve(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"}],u=0,v=0;for(let x of h){if(ha(x.path)&&!d){this.warn(`${x.label} already exists (use --force to overwrite)`),v++;continue}ma(x.path,x.content),this.success(`Created ${x.label}`),u++}if(r!=="sqlite"){let x=ve(s,"docker");pa(x,{recursive:!0})}this.newLine(),u>0?this.info(`${u} file(s) created${v>0?`, ${v} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Quick start:"),this.log(" # Build and start all services"),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(" docker compose logs -f app"),this.newLine(),this.log(" # Stop services"),this.log(" docker compose down"),this.newLine(),this.info("Make sure to update .env with production values before deploying.")}dockerfileTemplate(){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
838
841
  # Multi-stage build for a lean production image.
839
842
 
840
843
  # Stage 1: Install dependencies & build
@@ -887,7 +890,7 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \\
887
890
 
888
891
  # Start with PM2
889
892
  CMD ["pm2-runtime", "ecosystem.config.cjs"]
890
- `}composeTemplate(e,t,s,r,n=!0){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(" - 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"));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"),a.length>0){i.push(" depends_on:");for(let o of a)i.push(` ${o}:`),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(" ports:"),i.push(' - "${DB_PORT:-5432}:5432"'),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(" ports:"),i.push(' - "${DB_PORT:-3306}:3306"'),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(" ports:"),i.push(' - "${REDIS_PORT:-6379}:6379"'),i.push(" volumes:"),i.push(" - redisdata:/data"),i.push(" healthcheck:"),i.push(' test: ["CMD", "redis-cli", "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(" ports:"),i.push(' - "${SOKETI_PORT:-6001}:6001"'),i.push(' - "9601:9601" # Metrics'),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(" ports:"),i.push(' - "${GOTENBERG_PORT:-3001}:3000"'),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_API_PORT:-9000}:9000" # S3 API'),i.push(' - "${RUSTFS_CONSOLE_PORT:-9001}:9001" # Web Console'),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")),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:"),i.push(""),i.join(`
893
+ `}composeTemplate(e,t,s,r,i=!0,n=!1){let a=[];a.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"),a.push("# Generated by: npx svelar make:docker"),a.push("#"),a.push("# Usage:"),a.push("# docker compose up -d --build # Start all services"),a.push("# docker compose exec app npx svelar migrate # Run migrations"),a.push("# docker compose logs -f app # View app logs"),a.push("# docker compose down # Stop all services"),a.push(""),a.push("services:"),a.push(" app:"),a.push(" build: ."),a.push(" restart: unless-stopped"),a.push(" ports:"),a.push(' - "${APP_PORT:-3000}:3000"'),a.push(" env_file: .env"),a.push(" environment:"),a.push(" - NODE_ENV=production"),e==="postgres"?(a.push(" - DB_HOST=postgres"),a.push(" - DB_PORT=5432")):e==="mysql"&&(a.push(" - DB_HOST=mysql"),a.push(" - DB_PORT=3306")),s&&(a.push(" - REDIS_HOST=redis"),a.push(" - REDIS_PORT=6379"),a.push(" - REDIS_PASSWORD=${REDIS_PASSWORD:-svelarsecret}"),a.push(" - QUEUE_DRIVER=redis")),t&&(a.push(" - PUSHER_HOST=soketi"),a.push(" - PUSHER_PORT=6001")),r&&a.push(" - GOTENBERG_URL=http://gotenberg:3000"),i&&(a.push(" - S3_ENDPOINT=http://rustfs:9000"),a.push(" - S3_ACCESS_KEY=${RUSTFS_ROOT_USER:-svelar}"),a.push(" - S3_SECRET_KEY=${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),a.push(" - S3_BUCKET=${S3_BUCKET:-svelar}"),a.push(" - S3_REGION=us-east-1"),a.push(" - STORAGE_DISK=s3")),n&&(a.push(" - MEILISEARCH_HOST=http://meilisearch:7700"),a.push(" - MEILISEARCH_KEY=${MEILI_MASTER_KEY:-svelar-meili-master-key}"));let l=[];if(e==="postgres"&&l.push("postgres"),e==="mysql"&&l.push("mysql"),s&&l.push("redis"),t&&l.push("soketi"),r&&l.push("gotenberg"),i&&l.push("rustfs"),n&&l.push("meilisearch"),l.length>0){a.push(" depends_on:");for(let c of l)a.push(` ${c}:`),a.push(" condition: service_healthy")}return a.push(" volumes:"),a.push(" - app_storage:/app/storage"),e==="postgres"&&(a.push(""),a.push(" postgres:"),a.push(" image: postgres:16-alpine"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" environment:"),a.push(" POSTGRES_DB: ${DB_NAME:-svelar}"),a.push(" POSTGRES_USER: ${DB_USER:-svelar}"),a.push(" POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}"),a.push(" volumes:"),a.push(" - pgdata:/var/lib/postgresql/data"),a.push(" healthcheck:"),a.push(' test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-svelar}"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),e==="mysql"&&(a.push(""),a.push(" mysql:"),a.push(" image: mysql:8.0"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" environment:"),a.push(" MYSQL_DATABASE: ${DB_NAME:-svelar}"),a.push(" MYSQL_USER: ${DB_USER:-svelar}"),a.push(" MYSQL_PASSWORD: ${DB_PASSWORD:-secret}"),a.push(" MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}"),a.push(" volumes:"),a.push(" - mysqldata:/var/lib/mysql"),a.push(" healthcheck:"),a.push(' test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),s&&(a.push(""),a.push(" redis:"),a.push(" image: redis:7-alpine"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" command: redis-server --requirepass ${REDIS_PASSWORD:-svelarsecret}"),a.push(" volumes:"),a.push(" - redisdata:/data"),a.push(" healthcheck:"),a.push(' test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-svelarsecret}", "ping"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),t&&(a.push(""),a.push(" soketi:"),a.push(" image: quay.io/soketi/soketi:1.6-16-debian"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" # Expose 6001 to host only if clients connect directly (uncomment below)"),a.push(" # ports:"),a.push(' # - "${SOKETI_PORT:-6001}:6001"'),a.push(" environment:"),a.push(' SOKETI_DEBUG: "${SOKETI_DEBUG:-0}"'),a.push(" SOKETI_DEFAULT_APP_ID: ${PUSHER_APP_ID}"),a.push(" SOKETI_DEFAULT_APP_KEY: ${PUSHER_KEY}"),a.push(" SOKETI_DEFAULT_APP_SECRET: ${PUSHER_SECRET}"),a.push(' SOKETI_DEFAULT_APP_MAX_CONNS: "${SOKETI_MAX_CONNS:-1000}"'),a.push(' SOKETI_DEFAULT_APP_ENABLE_CLIENT_MESSAGES: "true"'),a.push(' SOKETI_DEFAULT_APP_MAX_BACKEND_EVENTS_PER_SEC: "-1"'),a.push(" healthcheck:"),a.push(' test: ["CMD", "wget", "-qO-", "http://localhost:6001"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 3")),r&&(a.push(""),a.push(" gotenberg:"),a.push(" image: gotenberg/gotenberg:8"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" environment:"),a.push(' CHROMIUM_DISABLE_JAVASCRIPT: "false"'),a.push(' CHROMIUM_ALLOW_LIST: "file:///tmp/.*"'),a.push(' API_TIMEOUT: "${GOTENBERG_TIMEOUT:-60s}"'),a.push(' LOG_LEVEL: "${GOTENBERG_LOG_LEVEL:-info}"'),a.push(" healthcheck:"),a.push(' test: ["CMD", "curl", "-f", "http://localhost:3000/health"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),i&&(a.push(""),a.push(" rustfs:"),a.push(" image: rustfs/rustfs:latest"),a.push(" restart: unless-stopped"),a.push(" ports:"),a.push(' - "${RUSTFS_CONSOLE_PORT:-9001}:9001" # Admin console (protect with firewall)'),a.push(" environment:"),a.push(" RUSTFS_ROOT_USER: ${RUSTFS_ROOT_USER:-svelar}"),a.push(" RUSTFS_ROOT_PASSWORD: ${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),a.push(' command: server /data --console-address ":9001"'),a.push(" volumes:"),a.push(" - rustfs_data:/data"),a.push(" healthcheck:"),a.push(' test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),n&&(a.push(""),a.push(" meilisearch:"),a.push(" image: getmeili/meilisearch:v1.13"),a.push(" restart: unless-stopped"),a.push(" # No ports exposed \u2014 only reachable by app via Docker network"),a.push(" # Uncomment below to access the dashboard from the host"),a.push(" # ports:"),a.push(' # - "${MEILI_PORT:-7700}:7700"'),a.push(" environment:"),a.push(" MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-svelar-meili-master-key}"),a.push(" MEILI_ENV: production"),a.push(" MEILI_DB_PATH: /meili_data"),a.push(' MEILI_NO_ANALYTICS: "true"'),a.push(" volumes:"),a.push(" - meili_data:/meili_data"),a.push(" healthcheck:"),a.push(' test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"]'),a.push(" interval: 10s"),a.push(" timeout: 5s"),a.push(" retries: 5")),a.push(""),a.push("volumes:"),a.push(" app_storage:"),e==="postgres"&&a.push(" pgdata:"),e==="mysql"&&a.push(" mysqldata:"),s&&a.push(" redisdata:"),i&&a.push(" rustfs_data:"),n&&a.push(" meili_data:"),a.push(""),a.join(`
891
894
  `)}dockerignoreTemplate(){return`# Dependencies
892
895
  node_modules
893
896
 
@@ -1010,7 +1013,7 @@ module.exports = {
1010
1013
  },
1011
1014
  ],
1012
1015
  };
1013
- `}};import{writeFileSync as ga,mkdirSync as fa,existsSync as Jr}from"fs";import{join as j}from"path";var lt=class extends h{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,i=t.pusher??!1,a=!n&&!i,o=[];(a||i)&&o.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")]}),(a||n)&&o.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]")]}),o.push({path:j(s,"src/lib/broadcasting.ts"),content:a||i?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[j(s,"src/lib")]});let c=j(s,"config/broadcasting.ts");Jr(c)||o.push({path:c,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[j(s,"config")]});let u=0,d=0;for(let p of o){if(Jr(p.path)&&!r){this.warn(`${p.label} already exists (use --force to overwrite)`),d++;continue}for(let f of p.dirs)fa(f,{recursive:!0});ga(p.path,p.content),this.success(`Created ${p.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:"),a||i?(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`/**
1016
+ `}};import{writeFileSync as ga,mkdirSync as fa,existsSync as Qr}from"fs";import{join as I}from"path";var ct=class extends g{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,n=t.pusher??!1,a=!i&&!n,l=[];(a||n)&&l.push({path:I(s,"src/routes/api/broadcasting/auth/+server.ts"),content:this.pusherAuthRoute(),label:"src/routes/api/broadcasting/auth/+server.ts",dirs:[I(s,"src/routes/api/broadcasting/auth")]}),(a||i)&&l.push({path:I(s,"src/routes/api/broadcasting/[channel]/+server.ts"),content:this.sseRoute(),label:"src/routes/api/broadcasting/[channel]/+server.ts",dirs:[I(s,"src/routes/api/broadcasting/[channel]")]}),l.push({path:I(s,"src/lib/broadcasting.ts"),content:a||n?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[I(s,"src/lib")]});let c=I(s,"config/broadcasting.ts");Qr(c)||l.push({path:c,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[I(s,"config")]});let d=0,p=0;for(let h of l){if(Qr(h.path)&&!r){this.warn(`${h.label} already exists (use --force to overwrite)`),p++;continue}for(let u of h.dirs)fa(u,{recursive:!0});ga(h.path,h.content),this.success(`Created ${h.label}`),d++}this.newLine(),d>0?this.info(`${d} file(s) created${p>0?`, ${p} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Next steps:"),a||n?(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`/**
1014
1017
  * Pusher/Soketi Channel Authorization Endpoint
1015
1018
  *
1016
1019
  * This route authenticates channel subscriptions from pusher-js.
@@ -1164,624 +1167,7 @@ export default {
1164
1167
  },
1165
1168
  },
1166
1169
  };
1167
- `}};import{writeFileSync as ya,mkdirSync as va,existsSync as ba}from"fs";import{join as k}from"path";var ct=class extends h{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:k(s,"src/routes/api/admin/health/+server.ts"),content:this.healthServerTemplate(),label:"api/admin/health/+server.ts"},{path:k(s,"src/routes/api/admin/queue/+server.ts"),content:this.queueServerTemplate(),label:"api/admin/queue/+server.ts"},{path:k(s,"src/routes/api/admin/queue/[id]/retry/+server.ts"),content:this.queueRetryServerTemplate(),label:"api/admin/queue/[id]/retry/+server.ts"},{path:k(s,"src/routes/api/admin/queue/[id]/+server.ts"),content:this.queueDeleteServerTemplate(),label:"api/admin/queue/[id]/+server.ts"},{path:k(s,"src/routes/api/admin/scheduler/+server.ts"),content:this.schedulerServerTemplate(),label:"api/admin/scheduler/+server.ts"},{path:k(s,"src/routes/api/admin/scheduler/[name]/run/+server.ts"),content:this.schedulerRunServerTemplate(),label:"api/admin/scheduler/[name]/run/+server.ts"},{path:k(s,"src/routes/api/admin/scheduler/[name]/toggle/+server.ts"),content:this.schedulerToggleServerTemplate(),label:"api/admin/scheduler/[name]/toggle/+server.ts"},{path:k(s,"src/routes/api/admin/logs/+server.ts"),content:this.logsServerTemplate(),label:"api/admin/logs/+server.ts"},{path:k(s,"src/routes/api/admin/logs/tail/+server.ts"),content:this.logsTailServerTemplate(),label:"api/admin/logs/tail/+server.ts"},{path:k(s,"src/routes/api/admin/stats/+server.ts"),content:this.statsServerTemplate(),label:"api/admin/stats/+server.ts"},{path:k(s,"src/routes/admin/dashboard/+page.server.ts"),content:this.dashboardPageServerTemplate(),label:"admin/dashboard/+page.server.ts"},{path:k(s,"src/routes/admin/dashboard/+page.svelte"),content:this.dashboardPageSvelteTemplate(),label:"admin/dashboard/+page.svelte"}],i=0,a=0;for(let o of n){let c=o.path.substring(0,o.path.lastIndexOf("/"));if(va(c,{recursive:!0}),ba(o.path)&&!r){this.warn(`${o.label} already exists (use --force to overwrite)`),a++;continue}ya(o.path,o.content),this.success(`Created ${o.label}`),i++}this.newLine(),i>0?this.info(`${i} file(s) created${a>0?`, ${a} 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';
1168
- import type { RequestHandler } from '@sveltejs/kit';
1169
-
1170
- /**
1171
- * GET /api/admin/health
1172
- * Returns system health status
1173
- */
1174
- export const GET: RequestHandler = async (event) => {
1175
- // TODO: Add admin middleware check
1176
-
1177
- const health = {
1178
- status: 'ok',
1179
- timestamp: new Date().toISOString(),
1180
- uptime: process.uptime(),
1181
- memory: process.memoryUsage(),
1182
- version: '0.1.0',
1183
- };
1184
-
1185
- return json(health);
1186
- };
1187
- `}queueServerTemplate(){return`import { json } from '@sveltejs/kit';
1188
- import type { RequestHandler } from '@sveltejs/kit';
1189
-
1190
- /**
1191
- * GET /api/admin/queue
1192
- * List jobs from the queue
1193
- *
1194
- * Query params:
1195
- * - status: 'completed' | 'failed' | 'delayed' | 'active' | 'waiting'
1196
- * - queue: queue name (default: 'default')
1197
- * - limit: number of jobs (default: 50)
1198
- * - offset: pagination offset (default: 0)
1199
- */
1200
- export const GET: RequestHandler = async (event) => {
1201
- // TODO: Add admin middleware check
1202
-
1203
- const { searchParams } = event.url;
1204
- const status = searchParams.get('status') || 'all';
1205
- const queueName = searchParams.get('queue') || 'default';
1206
- const limit = parseInt(searchParams.get('limit') || '50');
1207
- const offset = parseInt(searchParams.get('offset') || '0');
1208
-
1209
- try {
1210
- const { JobMonitor } = await import('svelar/queue/JobMonitor');
1211
-
1212
- const jobs = await JobMonitor.listJobs({
1213
- queue: queueName,
1214
- status: status === 'all' ? undefined : status as any,
1215
- limit,
1216
- offset,
1217
- });
1218
-
1219
- const counts = await JobMonitor.getCounts(queueName);
1220
-
1221
- return json({
1222
- jobs,
1223
- counts,
1224
- queueName,
1225
- });
1226
- } catch (error: any) {
1227
- return json(
1228
- {
1229
- error: error.message || 'Failed to fetch queue jobs',
1230
- },
1231
- { status: 500 }
1232
- );
1233
- }
1234
- };
1235
- `}queueRetryServerTemplate(){return`import { json } from '@sveltejs/kit';
1236
- import type { RequestHandler } from '@sveltejs/kit';
1237
-
1238
- /**
1239
- * POST /api/admin/queue/[id]/retry
1240
- * Retry a failed job
1241
- */
1242
- export const POST: RequestHandler = async (event) => {
1243
- // TODO: Add admin middleware check
1244
-
1245
- const { id } = event.params;
1246
-
1247
- try {
1248
- const { JobMonitor } = await import('svelar/queue/JobMonitor');
1249
- await JobMonitor.retryJob(id);
1250
-
1251
- return json({ success: true, message: 'Job queued for retry' });
1252
- } catch (error: any) {
1253
- return json(
1254
- {
1255
- error: error.message || 'Failed to retry job',
1256
- },
1257
- { status: 500 }
1258
- );
1259
- }
1260
- };
1261
- `}queueDeleteServerTemplate(){return`import { json } from '@sveltejs/kit';
1262
- import type { RequestHandler } from '@sveltejs/kit';
1263
-
1264
- /**
1265
- * DELETE /api/admin/queue/[id]
1266
- * Remove a job from the queue
1267
- */
1268
- export const DELETE: RequestHandler = async (event) => {
1269
- // TODO: Add admin middleware check
1270
-
1271
- const { id } = event.params;
1272
-
1273
- try {
1274
- const { JobMonitor } = await import('svelar/queue/JobMonitor');
1275
- await JobMonitor.deleteJob(id);
1276
-
1277
- return json({ success: true, message: 'Job removed' });
1278
- } catch (error: any) {
1279
- return json(
1280
- {
1281
- error: error.message || 'Failed to remove job',
1282
- },
1283
- { status: 500 }
1284
- );
1285
- }
1286
- };
1287
- `}schedulerServerTemplate(){return`import { json } from '@sveltejs/kit';
1288
- import type { RequestHandler } from '@sveltejs/kit';
1289
-
1290
- /**
1291
- * GET /api/admin/scheduler
1292
- * List all scheduled tasks
1293
- */
1294
- export const GET: RequestHandler = async (event) => {
1295
- // TODO: Add admin middleware check
1296
-
1297
- try {
1298
- const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1299
-
1300
- const tasks = await ScheduleMonitor.listTasks();
1301
- const health = await ScheduleMonitor.getHealth();
1302
-
1303
- return json({
1304
- tasks,
1305
- health,
1306
- });
1307
- } catch (error: any) {
1308
- return json(
1309
- {
1310
- error: error.message || 'Failed to fetch scheduled tasks',
1311
- },
1312
- { status: 500 }
1313
- );
1314
- }
1315
- };
1316
- `}schedulerRunServerTemplate(){return`import { json } from '@sveltejs/kit';
1317
- import type { RequestHandler } from '@sveltejs/kit';
1318
-
1319
- /**
1320
- * POST /api/admin/scheduler/[name]/run
1321
- * Manually trigger a scheduled task
1322
- */
1323
- export const POST: RequestHandler = async (event) => {
1324
- // TODO: Add admin middleware check
1325
-
1326
- const { name } = event.params;
1327
-
1328
- try {
1329
- const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1330
- await ScheduleMonitor.runTask(name);
1331
-
1332
- return json({ success: true, message: \`Task '\${name}' triggered\` });
1333
- } catch (error: any) {
1334
- return json(
1335
- {
1336
- error: error.message || 'Failed to run task',
1337
- },
1338
- { status: 500 }
1339
- );
1340
- }
1341
- };
1342
- `}schedulerToggleServerTemplate(){return`import { json } from '@sveltejs/kit';
1343
- import type { RequestHandler } from '@sveltejs/kit';
1344
-
1345
- /**
1346
- * POST /api/admin/scheduler/[name]/toggle
1347
- * Enable or disable a scheduled task
1348
- */
1349
- export const POST: RequestHandler = async (event) => {
1350
- // TODO: Add admin middleware check
1351
-
1352
- const { name } = event.params;
1353
- const body = await event.request.json();
1354
- const enabled = body.enabled ?? true;
1355
-
1356
- try {
1357
- const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1358
- if (enabled) {
1359
- ScheduleMonitor.enableTask(name);
1360
- } else {
1361
- ScheduleMonitor.disableTask(name);
1362
- }
1363
-
1364
- return json({ success: true, message: \`Task '\${name}' \${enabled ? 'enabled' : 'disabled'}\` });
1365
- } catch (error: any) {
1366
- return json(
1367
- {
1368
- error: error.message || 'Failed to toggle task',
1369
- },
1370
- { status: 500 }
1371
- );
1372
- }
1373
- };
1374
- `}logsServerTemplate(){return`import { json } from '@sveltejs/kit';
1375
- import type { RequestHandler } from '@sveltejs/kit';
1376
-
1377
- /**
1378
- * GET /api/admin/logs
1379
- * Retrieve logs with filtering
1380
- *
1381
- * Query params:
1382
- * - level: 'debug' | 'info' | 'warn' | 'error'
1383
- * - channel: log channel name
1384
- * - search: search term
1385
- * - limit: number of logs (default: 100)
1386
- * - offset: pagination offset (default: 0)
1387
- */
1388
- export const GET: RequestHandler = async (event) => {
1389
- // TODO: Add admin middleware check
1390
-
1391
- const { searchParams } = event.url;
1392
- const level = searchParams.get('level');
1393
- const channel = searchParams.get('channel');
1394
- const search = searchParams.get('search');
1395
- const limit = parseInt(searchParams.get('limit') || '100');
1396
- const offset = parseInt(searchParams.get('offset') || '0');
1397
-
1398
- try {
1399
- const { LogViewer } = await import('svelar/logging/LogViewer');
1400
-
1401
- const logs = LogViewer.query({
1402
- level: level as any,
1403
- channel: channel ?? undefined,
1404
- search: search ?? undefined,
1405
- limit,
1406
- offset,
1407
- });
1408
-
1409
- const stats = LogViewer.getStats();
1410
-
1411
- return json({
1412
- logs,
1413
- total: stats.totalEntries,
1414
- limit,
1415
- offset,
1416
- });
1417
- } catch (error: any) {
1418
- return json(
1419
- {
1420
- error: error.message || 'Failed to fetch logs',
1421
- },
1422
- { status: 500 }
1423
- );
1424
- }
1425
- };
1426
- `}logsTailServerTemplate(){return`import type { RequestHandler } from '@sveltejs/kit';
1427
-
1428
- /**
1429
- * GET /api/admin/logs/tail
1430
- * Server-Sent Events stream of live logs
1431
- *
1432
- * Returns a text/event-stream response with real-time log entries
1433
- */
1434
- export const GET: RequestHandler = async (event) => {
1435
- // TODO: Add admin middleware check
1436
-
1437
- const { LogViewer } = await import('svelar/logging/LogViewer');
1438
-
1439
- // Set up SSE headers
1440
- const headers = {
1441
- 'Content-Type': 'text/event-stream',
1442
- 'Cache-Control': 'no-cache',
1443
- Connection: 'keep-alive',
1444
- };
1445
-
1446
- // Create a readable stream using the tail() subscription
1447
- const stream = new ReadableStream({
1448
- start(controller) {
1449
- const encoder = new TextEncoder();
1450
- const unsubscribe = LogViewer.tail((entry) => {
1451
- try {
1452
- controller.enqueue(encoder.encode(\`data: \${JSON.stringify(entry)}
1453
-
1454
- \`));
1455
- } catch {
1456
- unsubscribe();
1457
- }
1458
- });
1459
-
1460
- // Clean up when the client disconnects
1461
- event.request.signal.addEventListener('abort', () => {
1462
- unsubscribe();
1463
- controller.close();
1464
- });
1465
- },
1466
- });
1467
-
1468
- return new Response(stream, { headers });
1469
- };
1470
- `}statsServerTemplate(){return`import { json } from '@sveltejs/kit';
1471
- import type { RequestHandler } from '@sveltejs/kit';
1472
-
1473
- /**
1474
- * GET /api/admin/stats
1475
- * Dashboard overview statistics
1476
- */
1477
- export const GET: RequestHandler = async (event) => {
1478
- // TODO: Add admin middleware check
1479
-
1480
- try {
1481
- const { JobMonitor } = await import('svelar/queue/JobMonitor');
1482
- const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1483
- const { LogViewer } = await import('svelar/logging/LogViewer');
1484
-
1485
- const [queueHealth, recentErrors] = await Promise.all([
1486
- JobMonitor.getHealth(),
1487
- Promise.resolve(LogViewer.getRecentErrors(10)),
1488
- ]);
1489
-
1490
- const schedulerHealth = await ScheduleMonitor.getHealth();
1491
- const logStats = LogViewer.getStats();
1492
-
1493
- return json({
1494
- queue: queueHealth,
1495
- scheduler: schedulerHealth,
1496
- logs: logStats,
1497
- recentErrors,
1498
- timestamp: new Date().toISOString(),
1499
- });
1500
- } catch (error: any) {
1501
- return json(
1502
- {
1503
- error: error.message || 'Failed to fetch stats',
1504
- },
1505
- { status: 500 }
1506
- );
1507
- }
1508
- };
1509
- `}dashboardPageServerTemplate(){return`import type { PageServerLoad } from './$types';
1510
-
1511
- export const load: PageServerLoad = async ({ fetch }) => {
1512
- try {
1513
- // Fetch initial dashboard data
1514
- const statsRes = await fetch('/api/admin/stats');
1515
- const stats = await statsRes.json();
1516
-
1517
- const healthRes = await fetch('/api/admin/health');
1518
- const health = await healthRes.json();
1519
-
1520
- return {
1521
- stats,
1522
- health,
1523
- };
1524
- } catch (error) {
1525
- console.error('Failed to load dashboard:', error);
1526
- return {
1527
- stats: null,
1528
- health: null,
1529
- error: 'Failed to load dashboard data',
1530
- };
1531
- }
1532
- };
1533
- `}dashboardPageSvelteTemplate(){return`<script lang="ts">
1534
- import type { PageData } from './$types';
1535
-
1536
- export let data: PageData;
1537
-
1538
- let selectedTab: 'overview' | 'queue' | 'scheduler' | 'logs' = 'overview';
1539
- let loading = false;
1540
-
1541
- async function refreshData() {
1542
- loading = true;
1543
- try {
1544
- const response = await fetch('/api/admin/stats');
1545
- const newStats = await response.json();
1546
- data.stats = newStats;
1547
- } catch (error) {
1548
- console.error('Failed to refresh:', error);
1549
- } finally {
1550
- loading = false;
1551
- }
1552
- }
1553
- </script>
1554
-
1555
- <div class="dashboard">
1556
- <header class="dashboard-header">
1557
- <h1>Admin Dashboard</h1>
1558
- <button on:click={refreshData} disabled={loading}>
1559
- {loading ? 'Refreshing...' : 'Refresh'}
1560
- </button>
1561
- </header>
1562
-
1563
- <nav class="tabs">
1564
- <button
1565
- class:active={selectedTab === 'overview'}
1566
- on:click={() => (selectedTab = 'overview')}
1567
- >
1568
- Overview
1569
- </button>
1570
- <button
1571
- class:active={selectedTab === 'queue'}
1572
- on:click={() => (selectedTab = 'queue')}
1573
- >
1574
- Queue
1575
- </button>
1576
- <button
1577
- class:active={selectedTab === 'scheduler'}
1578
- on:click={() => (selectedTab = 'scheduler')}
1579
- >
1580
- Scheduler
1581
- </button>
1582
- <button
1583
- class:active={selectedTab === 'logs'}
1584
- on:click={() => (selectedTab = 'logs')}
1585
- >
1586
- Logs
1587
- </button>
1588
- </nav>
1589
-
1590
- <main class="dashboard-content">
1591
- {#if selectedTab === 'overview'}
1592
- <section class="overview">
1593
- <h2>System Overview</h2>
1594
-
1595
- {#if data.health}
1596
- <div class="health-card">
1597
- <h3>System Health</h3>
1598
- <p>Status: <strong>{data.health.status}</strong></p>
1599
- <p>Uptime: {(data.health.uptime / 3600).toFixed(2)} hours</p>
1600
- <p>Memory: {(data.health.memory.heapUsed / 1024 / 1024).toFixed(2)} MB</p>
1601
- </div>
1602
- {/if}
1603
-
1604
- {#if data.stats}
1605
- <div class="stats-grid">
1606
- <div class="stat-card">
1607
- <h3>Queue Jobs</h3>
1608
- <p class="stat-number">{data.stats.queue?.total || 0}</p>
1609
- <small>Active: {data.stats.queue?.active || 0}</small>
1610
- </div>
1611
-
1612
- <div class="stat-card">
1613
- <h3>Scheduled Tasks</h3>
1614
- <p class="stat-number">{data.stats.scheduler?.total || 0}</p>
1615
- <small>Enabled: {data.stats.scheduler?.enabled || 0}</small>
1616
- </div>
1617
-
1618
- <div class="stat-card">
1619
- <h3>Recent Errors</h3>
1620
- <p class="stat-number">{data.stats.recentErrors?.length || 0}</p>
1621
- <small>Last 24 hours</small>
1622
- </div>
1623
- </div>
1624
- {/if}
1625
- </section>
1626
- {:else if selectedTab === 'queue'}
1627
- <section class="queue">
1628
- <h2>Job Queue</h2>
1629
- <p>Queue management interface coming soon...</p>
1630
- </section>
1631
- {:else if selectedTab === 'scheduler'}
1632
- <section class="scheduler">
1633
- <h2>Scheduled Tasks</h2>
1634
- <p>Task management interface coming soon...</p>
1635
- </section>
1636
- {:else if selectedTab === 'logs'}
1637
- <section class="logs">
1638
- <h2>Application Logs</h2>
1639
- <p>Log viewer coming soon...</p>
1640
- </section>
1641
- {/if}
1642
- </main>
1643
- </div>
1644
-
1645
- <style>
1646
- .dashboard {
1647
- padding: 2rem;
1648
- max-width: 1200px;
1649
- margin: 0 auto;
1650
- }
1651
-
1652
- .dashboard-header {
1653
- display: flex;
1654
- justify-content: space-between;
1655
- align-items: center;
1656
- margin-bottom: 2rem;
1657
- }
1658
-
1659
- .dashboard-header h1 {
1660
- margin: 0;
1661
- font-size: 2rem;
1662
- }
1663
-
1664
- .dashboard-header button {
1665
- padding: 0.5rem 1rem;
1666
- background: #0066cc;
1667
- color: white;
1668
- border: none;
1669
- border-radius: 4px;
1670
- cursor: pointer;
1671
- font-size: 1rem;
1672
- }
1673
-
1674
- .dashboard-header button:hover:not(:disabled) {
1675
- background: #0052a3;
1676
- }
1677
-
1678
- .dashboard-header button:disabled {
1679
- opacity: 0.6;
1680
- cursor: not-allowed;
1681
- }
1682
-
1683
- .tabs {
1684
- display: flex;
1685
- gap: 1rem;
1686
- margin-bottom: 2rem;
1687
- border-bottom: 1px solid #e0e0e0;
1688
- }
1689
-
1690
- .tabs button {
1691
- padding: 0.75rem 1.5rem;
1692
- background: none;
1693
- border: none;
1694
- border-bottom: 3px solid transparent;
1695
- cursor: pointer;
1696
- font-size: 1rem;
1697
- color: #666;
1698
- transition: all 0.3s ease;
1699
- }
1700
-
1701
- .tabs button:hover {
1702
- color: #0066cc;
1703
- }
1704
-
1705
- .tabs button.active {
1706
- color: #0066cc;
1707
- border-bottom-color: #0066cc;
1708
- }
1709
-
1710
- .dashboard-content {
1711
- animation: fadeIn 0.3s ease;
1712
- }
1713
-
1714
- @keyframes fadeIn {
1715
- from {
1716
- opacity: 0;
1717
- transform: translateY(10px);
1718
- }
1719
- to {
1720
- opacity: 1;
1721
- transform: translateY(0);
1722
- }
1723
- }
1724
-
1725
- .overview {
1726
- display: flex;
1727
- flex-direction: column;
1728
- gap: 2rem;
1729
- }
1730
-
1731
- .health-card {
1732
- padding: 1.5rem;
1733
- background: #f5f5f5;
1734
- border-radius: 8px;
1735
- border-left: 4px solid #00aa00;
1736
- }
1737
-
1738
- .health-card h3 {
1739
- margin-top: 0;
1740
- }
1741
-
1742
- .health-card p {
1743
- margin: 0.5rem 0;
1744
- }
1745
-
1746
- .stats-grid {
1747
- display: grid;
1748
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1749
- gap: 1.5rem;
1750
- }
1751
-
1752
- .stat-card {
1753
- padding: 1.5rem;
1754
- background: white;
1755
- border: 1px solid #e0e0e0;
1756
- border-radius: 8px;
1757
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1758
- }
1759
-
1760
- .stat-card h3 {
1761
- margin-top: 0;
1762
- font-size: 0.9rem;
1763
- color: #666;
1764
- text-transform: uppercase;
1765
- }
1766
-
1767
- .stat-number {
1768
- margin: 0.5rem 0;
1769
- font-size: 2rem;
1770
- font-weight: bold;
1771
- color: #0066cc;
1772
- }
1773
-
1774
- .stat-card small {
1775
- display: block;
1776
- color: #999;
1777
- font-size: 0.85rem;
1778
- }
1779
-
1780
- section h2 {
1781
- margin-top: 0;
1782
- }
1783
- </style>
1784
- `}};import{writeFileSync as Vr,mkdirSync as wa,existsSync as Qr}from"fs";import{join as ms}from"path";var dt=class extends h{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.warn(`No --module specified, using "${n}". Use --module=<name> to target a specific module.`);let i=ms(process.cwd(),"src","lib","modules",n);wa(i,{recursive:!0});let a=ms(i,`${r}.ts`);if(Qr(a)){this.warn(`Resource ${r} already exists.`);return}let o=t.model||this.inferModelName(r),c=this.generateResource(r,o);if(Vr(a,c),this.success(`Resource created: src/lib/modules/${n}/${r}.ts`),t.collection){let u=r.replace("Resource","CollectionResource"),d=ms(i,`${u}.ts`);if(!Qr(d)){let p=this.generateCollectionResource(u,r,o);Vr(d,p),this.success(`Collection resource created: src/lib/modules/${n}/${u}.ts`)}}}generateResource(e,t){let s=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
1170
+ `}};import{writeFileSync as Gr,mkdirSync as ya,existsSync as Yr}from"fs";import{join as hs}from"path";var dt=class extends g{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.warn(`No --module specified, using "${i}". Use --module=<name> to target a specific module.`);let n=hs(process.cwd(),"src","lib","modules",i);ya(n,{recursive:!0});let a=hs(n,`${r}.ts`);if(Yr(a)){this.warn(`Resource ${r} already exists.`);return}let l=t.model||this.inferModelName(r),c=this.generateResource(r,l);if(Gr(a,c),this.success(`Resource created: src/lib/modules/${i}/${r}.ts`),t.collection){let d=r.replace("Resource","CollectionResource"),p=hs(n,`${d}.ts`);if(!Yr(p)){let h=this.generateCollectionResource(d,r,l);Gr(p,h),this.success(`Collection resource created: src/lib/modules/${i}/${d}.ts`)}}}generateResource(e,t){let s=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
1785
1171
  import type { ${t} } from './${t}.js';
1786
1172
 
1787
1173
  // \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
@@ -1859,7 +1245,7 @@ export class ${e} {
1859
1245
  .toObject();
1860
1246
  }
1861
1247
  }
1862
- `}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as xa,mkdirSync as Ca,existsSync as Pa}from"fs";import{join as Gr}from"path";var ut=class extends h{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",i=t.module||s.toLowerCase(),a=Gr(process.cwd(),"src","lib","modules",i);Ca(a,{recursive:!0});let o=Gr(a,`${n}.ts`);if(Pa(o)){this.warn(`Schema already exists: src/lib/modules/${i}/${n}.ts`);return}let c=this.generateSchema(r);xa(o,c),this.success(`Schema created: src/lib/modules/${i}/${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`),this.info(` Frontend: import type { ${r}Data } from '$lib/modules/${i}/${n}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
1248
+ `}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as ba,mkdirSync as va,existsSync as wa}from"fs";import{join as Zr}from"path";var ut=class extends g{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",n=t.module||s.toLowerCase(),a=Zr(process.cwd(),"src","lib","modules",n);va(a,{recursive:!0});let l=Zr(a,`${i}.ts`);if(wa(l)){this.warn(`Schema already exists: src/lib/modules/${n}/${i}.ts`);return}let c=this.generateSchema(r);ba(l,c),this.success(`Schema created: src/lib/modules/${n}/${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`),this.info(` Frontend: import type { ${r}Data } from '$lib/modules/${n}/${i}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
1863
1249
 
1864
1250
  // \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
1865
1251
  //
@@ -1894,7 +1280,7 @@ export const update${e}Schema = create${e}Schema.partial();
1894
1280
  export type ${e}Data = z.infer<typeof ${t}Schema>;
1895
1281
  export type Create${e}Input = z.infer<typeof create${e}Schema>;
1896
1282
  export type Update${e}Input = z.infer<typeof update${e}Schema>;
1897
- `}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 Sa,mkdirSync as Ta,existsSync as Ra}from"fs";import{join as Yr}from"path";var mt=class extends h{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)),i=Yr(process.cwd(),"src","lib","modules",n);Ta(i,{recursive:!0});let a=Yr(i,`${s}.ts`);if(Ra(a)){this.warn(`Observer ${s} already exists at ${a}`);return}let o=`import { ModelObserver } from '@beeblock/svelar/orm';
1283
+ `}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 Ca,mkdirSync as xa,existsSync as Pa}from"fs";import{join as Xr}from"path";var mt=class extends g{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)),n=Xr(process.cwd(),"src","lib","modules",i);xa(n,{recursive:!0});let a=Xr(n,`${s}.ts`);if(Pa(a)){this.warn(`Observer ${s} already exists at ${a}`);return}let l=`import { ModelObserver } from '@beeblock/svelar/orm';
1898
1284
  import type { ${r} } from './${r}.js';
1899
1285
 
1900
1286
  export class ${s} extends ModelObserver {
@@ -1932,7 +1318,7 @@ export class ${s} extends ModelObserver {
1932
1318
  // async deleted(${r.toLowerCase()}: ${r}) {
1933
1319
  // }
1934
1320
  }
1935
- `;Sa(a,o),this.success(`Observer created: src/lib/modules/${n}/${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 Ea,mkdirSync as ka,existsSync as $a}from"fs";import{join as Xr}from"path";var pt=class extends h{name="make:event";description="Create a new event class";arguments=["name"];flags=[];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an event name (e.g. UserRegistered).");return}let r=Xr(process.cwd(),"src","lib","events");ka(r,{recursive:!0});let n=Xr(r,`${s}.ts`);if($a(n)){this.warn(`Event ${s} already exists at ${n}`);return}let i=`/**
1321
+ `;Ca(a,l),this.success(`Observer created: src/lib/modules/${i}/${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 Ra,mkdirSync as Sa,existsSync as Ta}from"fs";import{join as ei}from"path";var pt=class extends g{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.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=ei(process.cwd(),"src","lib","modules",r);Sa(i,{recursive:!0});let n=ei(i,`${s}.ts`);if(Ta(n)){this.warn(`Event ${s} already exists at ${n}`);return}let a=`/**
1936
1322
  * ${s} Event
1937
1323
  *
1938
1324
  * Dispatched when ... (describe when this event fires).
@@ -1950,30 +1336,30 @@ export class ${s} {
1950
1336
  // public readonly metadata?: Record<string, any>,
1951
1337
  ) {}
1952
1338
  }
1953
- `;Ea(n,i),this.success(`Event created: src/lib/events/${s}.ts`)}};import{writeFileSync as Aa,mkdirSync as Da,existsSync as Na}from"fs";import{join as Zr}from"path";var ht=class extends h{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"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a listener name (e.g. SendWelcomeEmail).");return}let r=Zr(process.cwd(),"src","lib","listeners");Da(r,{recursive:!0});let n=Zr(r,`${s}.ts`);if(Na(n)){this.warn(`Listener ${s} already exists at ${n}`);return}let i=t.event||"any",a=t.event?`import type { ${t.event} } from '../events/${t.event}.js';
1339
+ `;Ra(n,a),this.success(`Event created: src/lib/modules/${r}/${s}.ts`)}};import{writeFileSync as Ea,mkdirSync as ka,existsSync as $a}from"fs";import{join as ti}from"path";var ht=class extends g{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.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=ti(process.cwd(),"src","lib","modules",r);ka(i,{recursive:!0});let n=ti(i,`${s}.ts`);if($a(n)){this.warn(`Listener ${s} already exists at ${n}`);return}let a=t.event||"any",l=t.event?`import type { ${t.event} } from './${t.event}.js';
1954
1340
 
1955
- `:"",o=t.event||"any",c=`import { Listener } from '@beeblock/svelar/events';
1956
- ${a}export class ${s} extends Listener<${o}> {
1957
- async handle(event: ${o}): Promise<void> {
1341
+ `:"",c=t.event||"any",d=`import { Listener } from '@beeblock/svelar/events';
1342
+ ${l}export class ${s} extends Listener<${c}> {
1343
+ async handle(event: ${c}): Promise<void> {
1958
1344
  // Handle the event
1959
1345
  // e.g. await Mail.to(event.user.email).send(new WelcomeEmail());
1960
1346
  }
1961
1347
 
1962
1348
  // Optionally filter which events to handle:
1963
- // shouldHandle(event: ${o}): boolean {
1349
+ // shouldHandle(event: ${c}): boolean {
1964
1350
  // return true;
1965
1351
  // }
1966
1352
  }
1967
- `;Aa(n,c),this.success(`Listener created: src/lib/listeners/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as _a,mkdirSync as Ma,existsSync as Oa}from"fs";import{join as ei}from"path";var gt=class extends h{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),i=t.module||this.inferModuleName(r);t.resource?this.generateResourceRoutes(r,n,i):this.generateRoute(r,n,i,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 i=(r?r.split(",").map(a=>a.trim().toUpperCase()):["GET"]).map(a=>({method:a,handler:this.defaultHandler(a)}));this.generateRouteFile(e,t,s,i)}generateRouteFile(e,t,s,r){let n=ei(process.cwd(),"src","routes",...e.split("/"));Ma(n,{recursive:!0});let i=ei(n,"+server.ts");if(Oa(i)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let a=`$lib/modules/${s}/${t}.js`,o=r.map(u=>`export const ${u.method} = ctrl.handle('${u.handler}');`).join(`
1353
+ `;Ea(n,d),this.success(`Listener created: src/lib/modules/${r}/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as Aa,mkdirSync as Da,existsSync as La}from"fs";import{join as si}from"path";var gt=class extends g{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),n=t.module||this.inferModuleName(r);t.resource?this.generateResourceRoutes(r,i,n):this.generateRoute(r,i,n,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 n=(r?r.split(",").map(a=>a.trim().toUpperCase()):["GET"]).map(a=>({method:a,handler:this.defaultHandler(a)}));this.generateRouteFile(e,t,s,n)}generateRouteFile(e,t,s,r){let i=si(process.cwd(),"src","routes",...e.split("/"));Da(i,{recursive:!0});let n=si(i,"+server.ts");if(La(n)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let a=`$lib/modules/${s}/${t}.js`,l=r.map(d=>`export const ${d.method} = ctrl.handle('${d.handler}');`).join(`
1968
1354
  `),c=`import { ${t} } from '${a}';
1969
1355
 
1970
1356
  const ctrl = new ${t}();
1971
- ${o}
1972
- `;_a(i,c),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(i=>!i.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 ti,relative as ps,sep as hs}from"path";import{existsSync as ja,readdirSync as Ia,readFileSync as si,statSync as La}from"fs";var ft=class extends h{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=ti(process.cwd(),"src","routes");if(!ja(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)
1973
- `);let i=Math.max(6,...n.map(u=>u.method.length)),a=Math.max(4,...n.map(u=>u.path.length)),o=Math.max(7,...n.map(u=>u.handler.length)),c=` ${"METHOD".padEnd(i)} ${"PATH".padEnd(a)} ${"HANDLER".padEnd(o)} FILE`;this.log(`\x1B[2m${c}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(i)} ${"\u2500".repeat(a)} ${"\u2500".repeat(o)} ${"\u2500".repeat(20)}\x1B[0m`);for(let u of n){let p=`${this.getMethodColor(u.method)}${u.method.padEnd(i)}\x1B[0m`,f=u.path.padEnd(a),y=`\x1B[2m${u.handler.padEnd(o)}\x1B[0m`,S=`\x1B[2m${u.file}\x1B[0m`;this.log(` ${p} ${f} ${y} ${S}`)}this.log("")}scanRoutes(e,t){let s=[],r=Ia(e);for(let n of r){let i=ti(e,n);if(La(i).isDirectory()){s.push(...this.scanRoutes(i,t));continue}n==="+server.ts"||n==="+server.js"?s.push(...this.parseServerFile(i,t)):(n==="+page.server.ts"||n==="+page.server.js")&&s.push(...this.parsePageServerFile(i,t))}return s}parseServerFile(e,t){let s=[],r=si(e,"utf-8"),n=this.filePathToUrl(e,t),i=ps(process.cwd(),e).split(hs).join("/"),a=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,o;for(;(o=a.exec(r))!==null;){let c=o[1],u=this.extractHandler(r,c);s.push({method:c,path:n,handler:u,file:i})}return s}parsePageServerFile(e,t){let s=[],r=si(e,"utf-8"),n=this.filePathToUrl(e,t),i=ps(process.cwd(),e).split(hs).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:n,handler:"load()",file:i});let a=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(a){let o=a[1].split(",").map(c=>c.trim().split(":")[0].split("(")[0].trim()).filter(Boolean);for(let c of o)s.push({method:"POST",path:c==="default"?n:`${n}?/${c}`,handler:`actions.${c}()`,file:i})}return s}filePathToUrl(e,t){let s=ps(t,e).split(hs).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+)`),i=e.match(n);return i?`${i[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 qa}from"fs";import{join as ni}from"path";import{pathToFileURL as Ua}from"url";var yt=class extends h{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(c=>t[c]);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(()=>(ys(),ii)),n=new r,i=ni(process.cwd(),"src","lib","database","migrations"),a=await this.loadMigrations(i);if(t.status){let c=await n.status(a);this.table(["Migration","Status","Batch"],c.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 c=await n.rollback(a);if(c.length===0)this.info("Nothing to rollback.");else for(let u of c)this.success(`Rolled back: ${u}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let c=await n.reset(a);if(c.length===0)this.info("Nothing to reset.");else for(let u of c)this.success(`Rolled back: ${u}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let c=await n.refresh(a);for(let u of c.reset)this.success(`Rolled back: ${u}`);for(let u of c.migrated)this.success(`Migrated: ${u}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let c=await n.fresh(a);if(c.dropped.length>0)for(let u of c.dropped)this.success(`Dropped table: ${u}`);this.newLine(),this.info("Re-running all migrations...");for(let u of c.migrated)this.success(`Migrated: ${u}`);return}this.info("Running migrations...");let o=await n.run(a);if(o.length===0)this.info("Nothing to migrate.");else for(let c of o)this.success(`Migrated: ${c}`)}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=qa(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=ni(e,r);try{let i=await import(Ua(n).href),a=i.default??Object.values(i).find(o=>typeof o=="function"&&o.prototype&&typeof o.prototype.up=="function");a?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:n,migration:new a}):this.warn(`No migration class found in: ${r}`)}catch(i){let a;try{a=i instanceof Error?i.message:String(i)}catch{a=JSON.stringify(i)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${a}`)}}return s}};import{join as vs}from"path";import{pathToFileURL as Fa}from"url";import{existsSync as ai}from"fs";var vt=class extends h{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=vs(process.cwd(),"src","lib","database","seeders"),r=t.class?vs(s,`${t.class}.ts`):vs(s,"DatabaseSeeder.ts"),n=r;ai(n)||(n=n.replace(/\.ts$/,".js")),ai(n)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let i=await import(Fa(n).href),a=i.default??i.DatabaseSeeder??Object.values(i).find(c=>typeof c=="function"&&c.prototype&&typeof c.prototype.run=="function");(!a||typeof a!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new a().run(),this.success("Database seeded successfully.")}catch(i){let a=i instanceof Error?i.message:String(i);this.error(`Seeding failed: ${a}`),i?.stack&&console.error(i.stack),process.exit(1)}}};import{readdirSync as Ka}from"fs";import{join as ui}from"path";import{pathToFileURL as Wa}from"url";var xt=class extends h{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(()=>(di(),ci)),r=new s;r.persistToDatabase();let n=ui(process.cwd(),"src","lib","scheduler"),i=await this.loadTasks(n);if(i.length===0){this.warn("No scheduled tasks found in src/lib/scheduler/");return}for(let c of i)r.register(c),this.info(`Registered task: ${c.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let c=await r.run();if(c.length===0)this.info("No tasks were due.");else for(let u of c)u.success?this.success(`${u.task}: completed in ${u.duration}ms`):this.error(`${u.task}: failed \u2014 ${u.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let a=async()=>{let c=await r.run();for(let u of c){let d=new Date().toISOString().replace("T"," ").slice(0,19);u.success?this.success(`[${d}] ${u.task}: completed in ${u.duration}ms`):this.error(`[${d}] ${u.task}: failed \u2014 ${u.error}`)}};await a();let o=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(o/1e3)}s.`),await new Promise(c=>setTimeout(c,o)),await a(),setInterval(a,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=Ka(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let n=ui(e,r);try{let i=await import(Wa(n).href),a=i.default??Object.values(i).find(o=>typeof o=="function"&&o.prototype&&typeof o.prototype.handle=="function");if(a){let o=new a;o.schedule(),s.push(o)}}catch(i){this.error(`Failed to load task ${r}: ${i.message??i}`)}}return s}};var St=class extends h{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(()=>(G(),ke)),r=t.queue??"default",n=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,i=t["max-time"]?parseInt(t["max-time"]):void 0,a=t.sleep?parseInt(t.sleep):1e3;if(this.info(`Processing queue "${r}"...`),n&&this.info(`Will stop after ${n} jobs.`),i&&this.info(`Will stop after ${i} 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 o=Date.now(),c=0;for(;;){if(i&&(Date.now()-o)/1e3>=i){this.info(`Max time (${i}s) reached. Stopping.`);break}if(n&&c>=n){this.info(`Max jobs (${n}) reached. Stopping.`);break}let u=await s.work({queue:r,maxJobs:1,sleep:0});if(u>0){c+=u;let d=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${d}] Processed ${u} job(s) (total: ${c})`)}else await new Promise(d=>setTimeout(d,a))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${c}`)}};var Tt=class extends h{name="queue:failed";description="List all failed jobs";async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(G(),ke)),r=await s.failed();if(r.length===0){this.info("No failed jobs.");return}this.info(`Found ${r.length} failed job(s):
1974
- `);for(let n of r){let i=new Date(n.failedAt*1e3).toISOString().replace("T"," ").slice(0,19);this.log(` ID: ${n.id}`),this.log(` Job: ${n.jobClass}`),this.log(` Queue: ${n.queue}`),this.log(` Date: ${i}`),this.log(` Error: ${n.exception.split(`
1975
- `)[0]}`),this.log("")}}};var Rt=class extends h{name="queue:retry";description="Retry a failed job (or all failed jobs)";arguments=["id"];flags=[{name:"all",description:"Retry all failed jobs",type:"boolean",default:!1}];async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(G(),ke));if(t.all){let i=await s.retryAll();i===0?this.info("No failed jobs to retry."):this.success(`Retried ${i} job(s).`);return}let r=e[0];r||(this.error("Please provide a failed job ID, or use --all to retry all."),process.exit(1)),await s.retry(r)?this.success(`Job ${r} has been pushed back onto the queue.`):this.error(`Failed job with ID "${r}" not found.`)}};var Et=class extends h{name="queue:flush";description="Delete all failed job records";async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(G(),ke)),r=await s.flushFailed();r===0?this.info("No failed jobs to flush."):this.success(`Flushed ${r} failed job record(s).`)}};var es=class extends h{name="tinker";description="Start an interactive REPL with Svelar preloaded";flags=[];async handle(){this.info("Starting Svelar Tinker..."),this.log(`Type .exit to quit. All Svelar modules are available.
1976
- `);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(cn(),ln));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"),i=r(process.cwd(),"src","lib","models"),a=s(i).filter(o=>o.endsWith(".ts")||o.endsWith(".js"));for(let o of a)try{let c=await import(n(r(i,o)).href);for(let[u,d]of Object.entries(c))typeof d=="function"&&(t.context[u]=d)}catch{}a.length>0&&this.log(`Loaded models: ${a.map(o=>o.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var m=class{static packageJson(e,t="0.4.0"){return JSON.stringify({name:e,version:"0.0.1",private:!0,type:"module",scripts:{dev:"vite dev",build:"vite build",preview:"vite preview",migrate:"npx svelar migrate","migrate:rollback":"npx svelar migrate --rollback","migrate:refresh":"npx svelar migrate --refresh",seed:"npx svelar seed:run"},devDependencies:{"@sveltejs/adapter-auto":"^3.0.0","@sveltejs/kit":"^2.55.0","@sveltejs/vite-plugin-svelte":"^5.0.0","@tailwindcss/vite":"^4.2.2","lucide-svelte":"^0.468.0",svelte:"^5.0.0","svelte-check":"^4.0.0",tailwindcss:"^4.2.2",typescript:"^5.7.0",vite:"^6.0.0"},dependencies:{"better-sqlite3":"^11.0.0","drizzle-orm":"^0.38.0","@beeblock/svelar":`^${t}`,exceljs:"^4.4.0",pdfkit:"^0.18.0","sveltekit-superforms":"^2.22.0",zod:"^3.23.0"}},null,2)+`
1357
+ ${l}
1358
+ `;Aa(n,c),this.success(`Route created: src/routes/${e}/+server.ts`);for(let d of r)this.info(` ${d.method} /${e} \u2192 ${t}.${d.handler}()`)}inferControllerName(e){let t=e.replace(/^api\//,"").split("/").filter(n=>!n.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 ri,relative as gs,sep as fs}from"path";import{existsSync as Ma,readdirSync as Na,readFileSync as ii,statSync as Ia}from"fs";var ft=class extends g{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=ri(process.cwd(),"src","routes");if(!Ma(s)){this.error("No src/routes/ directory found.");return}let i=this.scanRoutes(s,s);if(t.api&&(i=i.filter(d=>d.path.startsWith("/api"))),t.method){let d=t.method.toUpperCase();i=i.filter(p=>p.method===d)}if(i.sort((d,p)=>d.path.localeCompare(p.path)||d.method.localeCompare(p.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)
1359
+ `);let n=Math.max(6,...i.map(d=>d.method.length)),a=Math.max(4,...i.map(d=>d.path.length)),l=Math.max(7,...i.map(d=>d.handler.length)),c=` ${"METHOD".padEnd(n)} ${"PATH".padEnd(a)} ${"HANDLER".padEnd(l)} FILE`;this.log(`\x1B[2m${c}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(n)} ${"\u2500".repeat(a)} ${"\u2500".repeat(l)} ${"\u2500".repeat(20)}\x1B[0m`);for(let d of i){let h=`${this.getMethodColor(d.method)}${d.method.padEnd(n)}\x1B[0m`,u=d.path.padEnd(a),v=`\x1B[2m${d.handler.padEnd(l)}\x1B[0m`,x=`\x1B[2m${d.file}\x1B[0m`;this.log(` ${h} ${u} ${v} ${x}`)}this.log("")}scanRoutes(e,t){let s=[],r=Na(e);for(let i of r){let n=ri(e,i);if(Ia(n).isDirectory()){s.push(...this.scanRoutes(n,t));continue}i==="+server.ts"||i==="+server.js"?s.push(...this.parseServerFile(n,t)):(i==="+page.server.ts"||i==="+page.server.js")&&s.push(...this.parsePageServerFile(n,t))}return s}parseServerFile(e,t){let s=[],r=ii(e,"utf-8"),i=this.filePathToUrl(e,t),n=gs(process.cwd(),e).split(fs).join("/"),a=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,l;for(;(l=a.exec(r))!==null;){let c=l[1],d=this.extractHandler(r,c);s.push({method:c,path:i,handler:d,file:n})}return s}parsePageServerFile(e,t){let s=[],r=ii(e,"utf-8"),i=this.filePathToUrl(e,t),n=gs(process.cwd(),e).split(fs).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:i,handler:"load()",file:n});let a=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(a){let l=a[1].split(",").map(c=>c.trim().split(":")[0].split("(")[0].trim()).filter(Boolean);for(let c of l)s.push({method:"POST",path:c==="default"?i:`${i}?/${c}`,handler:`actions.${c}()`,file:n})}return s}filePathToUrl(e,t){let s=gs(t,e).split(fs).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+)`),n=e.match(i);return n?`${n[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 _a}from"fs";import{join as oi}from"path";import{pathToFileURL as ja}from"url";var yt=class extends g{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(c=>t[c]);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(()=>(vs(),ai)),i=new r,n=oi(process.cwd(),"src","lib","database","migrations"),a=await this.loadMigrations(n);if(t.status){let c=await i.status(a);this.table(["Migration","Status","Batch"],c.map(d=>[d.name,d.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",d.batch?.toString()??"-"]));return}if(t.rollback){this.info("Rolling back last batch...");let c=await i.rollback(a);if(c.length===0)this.info("Nothing to rollback.");else for(let d of c)this.success(`Rolled back: ${d}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let c=await i.reset(a);if(c.length===0)this.info("Nothing to reset.");else for(let d of c)this.success(`Rolled back: ${d}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let c=await i.refresh(a);for(let d of c.reset)this.success(`Rolled back: ${d}`);for(let d of c.migrated)this.success(`Migrated: ${d}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let c=await i.fresh(a);if(c.dropped.length>0)for(let d of c.dropped)this.success(`Dropped table: ${d}`);this.newLine(),this.info("Re-running all migrations...");for(let d of c.migrated)this.success(`Migrated: ${d}`);return}this.info("Running migrations...");let l=await i.run(a);if(l.length===0)this.info("Nothing to migrate.");else for(let c of l)this.success(`Migrated: ${c}`)}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=_a(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=oi(e,r);try{let n=await import(ja(i).href),a=n.default??Object.values(n).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.up=="function");a?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:i,migration:new a}):this.warn(`No migration class found in: ${r}`)}catch(n){let a;try{a=n instanceof Error?n.message:String(n)}catch{a=JSON.stringify(n)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${a}`)}}return s}};import{join as ws}from"path";import{pathToFileURL as Oa}from"url";import{existsSync as li}from"fs";var bt=class extends g{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=ws(process.cwd(),"src","lib","database","seeders"),r=t.class?ws(s,`${t.class}.ts`):ws(s,"DatabaseSeeder.ts"),i=r;li(i)||(i=i.replace(/\.ts$/,".js")),li(i)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let n=await import(Oa(i).href),a=n.default??n.DatabaseSeeder??Object.values(n).find(c=>typeof c=="function"&&c.prototype&&typeof c.prototype.run=="function");(!a||typeof a!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new a().run(),this.success("Database seeded successfully.")}catch(n){let a=n instanceof Error?n.message:String(n);this.error(`Seeding failed: ${a}`),n?.stack&&console.error(n.stack),process.exit(1)}}};import{readdirSync as Ba}from"fs";import{join as pi}from"path";import{pathToFileURL as Ha}from"url";var Ct=class extends g{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(()=>(mi(),ui)),r=new s;r.persistToDatabase();let i=pi(process.cwd(),"src","lib","scheduler"),n=await this.loadTasks(i);if(n.length===0){this.warn("No scheduled tasks found in src/lib/scheduler/");return}for(let c of n)r.register(c),this.info(`Registered task: ${c.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let c=await r.run();if(c.length===0)this.info("No tasks were due.");else for(let d of c)d.success?this.success(`${d.task}: completed in ${d.duration}ms`):this.error(`${d.task}: failed \u2014 ${d.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let a=async()=>{let c=await r.run();for(let d of c){let p=new Date().toISOString().replace("T"," ").slice(0,19);d.success?this.success(`[${p}] ${d.task}: completed in ${d.duration}ms`):this.error(`[${p}] ${d.task}: failed \u2014 ${d.error}`)}};await a();let l=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(l/1e3)}s.`),await new Promise(c=>setTimeout(c,l)),await a(),setInterval(a,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=Ba(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let i=pi(e,r);try{let n=await import(Ha(i).href),a=n.default??Object.values(n).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.handle=="function");if(a){let l=new a;l.schedule(),s.push(l)}}catch(n){this.error(`Failed to load task ${r}: ${n.message??n}`)}}return s}};var Rt=class extends g{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(()=>(Q(),Te)),r=t.queue??"default",i=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,n=t["max-time"]?parseInt(t["max-time"]):void 0,a=t.sleep?parseInt(t.sleep):1e3;if(this.info(`Processing queue "${r}"...`),i&&this.info(`Will stop after ${i} jobs.`),n&&this.info(`Will stop after ${n} seconds.`),this.newLine(),t.once){let d=await s.work({queue:r,maxJobs:1,sleep:0});d===0?this.info("No jobs to process."):this.success(`Processed ${d} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let l=Date.now(),c=0;for(;;){if(n&&(Date.now()-l)/1e3>=n){this.info(`Max time (${n}s) reached. Stopping.`);break}if(i&&c>=i){this.info(`Max jobs (${i}) reached. Stopping.`);break}let d=await s.work({queue:r,maxJobs:1,sleep:0});if(d>0){c+=d;let p=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${p}] Processed ${d} job(s) (total: ${c})`)}else await new Promise(p=>setTimeout(p,a))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${c}`)}};var St=class extends g{name="queue:failed";description="List all failed jobs";async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(Q(),Te)),r=await s.failed();if(r.length===0){this.info("No failed jobs.");return}this.info(`Found ${r.length} failed job(s):
1360
+ `);for(let i of r){let n=new Date(i.failedAt*1e3).toISOString().replace("T"," ").slice(0,19);this.log(` ID: ${i.id}`),this.log(` Job: ${i.jobClass}`),this.log(` Queue: ${i.queue}`),this.log(` Date: ${n}`),this.log(` Error: ${i.exception.split(`
1361
+ `)[0]}`),this.log("")}}};var Tt=class extends g{name="queue:retry";description="Retry a failed job (or all failed jobs)";arguments=["id"];flags=[{name:"all",description:"Retry all failed jobs",type:"boolean",default:!1}];async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(Q(),Te));if(t.all){let n=await s.retryAll();n===0?this.info("No failed jobs to retry."):this.success(`Retried ${n} job(s).`);return}let r=e[0];r||(this.error("Please provide a failed job ID, or use --all to retry all."),process.exit(1)),await s.retry(r)?this.success(`Job ${r} has been pushed back onto the queue.`):this.error(`Failed job with ID "${r}" not found.`)}};var Et=class extends g{name="queue:flush";description="Delete all failed job records";async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(Q(),Te)),r=await s.flushFailed();r===0?this.info("No failed jobs to flush."):this.success(`Flushed ${r} failed job record(s).`)}};var es=class extends g{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.
1362
+ `);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(un(),dn));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"),n=r(process.cwd(),"src","lib","models"),a=s(n).filter(l=>l.endsWith(".ts")||l.endsWith(".js"));for(let l of a)try{let c=await import(i(r(n,l)).href);for(let[d,p]of Object.entries(c))typeof p=="function"&&(t.context[d]=p)}catch{}a.length>0&&this.log(`Loaded models: ${a.map(l=>l.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var m=class{static packageJson(e,t="0.4.0"){return JSON.stringify({name:e,version:"0.0.1",private:!0,type:"module",scripts:{dev:"vite dev",build:"vite build",preview:"vite preview",migrate:"npx svelar migrate","migrate:rollback":"npx svelar migrate --rollback","migrate:refresh":"npx svelar migrate --refresh",seed:"npx svelar seed:run"},devDependencies:{"@sveltejs/adapter-auto":"^3.0.0","@sveltejs/kit":"^2.55.0","@sveltejs/vite-plugin-svelte":"^5.0.0","@tailwindcss/vite":"^4.2.2","lucide-svelte":"^0.468.0",svelte:"^5.0.0","svelte-check":"^4.0.0",tailwindcss:"^4.2.2",typescript:"^5.7.0",vite:"^6.0.0"},dependencies:{"better-sqlite3":"^11.0.0","drizzle-orm":"^0.38.0","@beeblock/svelar":`^${t}`,exceljs:"^4.4.0",pdfkit:"^0.18.0","sveltekit-superforms":"^2.22.0",zod:"^3.23.0"}},null,2)+`
1977
1363
  `}static svelteConfig(){return`import adapter from '@sveltejs/adapter-auto';
1978
1364
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
1979
1365
 
@@ -2079,7 +1465,7 @@ export default defineConfig({
2079
1465
  <html lang="en">
2080
1466
  <head>
2081
1467
  <meta charset="utf-8" />
2082
- <link rel="icon" href="%sveltekit.assets%/favicon.png" />
1468
+ <link rel="icon" href="%sveltekit.assets%/favicon.svg" type="image/svg+xml" />
2083
1469
  <meta name="viewport" content="width=device-width, initial-scale=1" />
2084
1470
  %sveltekit.head%
2085
1471
  </head>
@@ -2087,7 +1473,78 @@ export default defineConfig({
2087
1473
  <div style="display: contents">%sveltekit.body%</div>
2088
1474
  </body>
2089
1475
  </html>
2090
- `}static appCss(){return`@import "tailwindcss";
1476
+ `}static faviconSvg(){return`<svg width="459" height="540" viewBox="0 0 459 540" fill="none" xmlns="http://www.w3.org/2000/svg">
1477
+ <path d="M458.11 4.54057L457.86 5.97056C457.832 6.12139 457.772 6.2639 457.683 6.38823C457.595 6.51256 457.482 6.61574 457.35 6.69057C439.037 17.0172 418.88 24.5506 396.88 29.2906C385.494 31.7506 377.45 33.4239 372.75 34.3106C365.117 27.0639 359.18 21.9206 354.94 18.8806C353.98 18.1939 350.274 16.0072 343.82 12.3206C338.96 9.54057 334.68 8.33056 329.39 6.06056C327.504 5.25389 324.92 4.31723 321.64 3.25056C319.114 2.4239 316.5 1.56388 313.8 0.670546C316.34 0.210546 318.73 -0.0127699 320.97 0.00056342C371.304 0.213897 414.804 0.250549 451.47 0.110549C453.464 0.103882 455.454 0.127223 457.44 0.180556C457.585 0.185536 457.722 0.245097 457.824 0.347182C457.926 0.449268 457.985 0.58629 457.99 0.730574L458.11 4.54057Z" fill="#FDC509"/>
1478
+ <path d="M313.8 0.670478C316.5 1.56381 319.114 2.42383 321.64 3.25049C324.92 4.31716 327.504 5.25383 329.39 6.06049C334.68 8.33049 338.96 9.5405 343.82 12.3205C350.274 16.0072 353.98 18.1938 354.94 18.8805C359.18 21.9205 365.117 27.0638 372.75 34.3105C375.577 38.4505 378.604 42.4238 381.83 46.2305C383.057 47.6772 385.537 51.5605 389.27 57.8805L396.06 70.0305C396.13 70.1583 396.239 70.2603 396.373 70.3215C396.506 70.3827 396.656 70.3999 396.8 70.3705C419.49 66.0905 437.64 59.9005 457.92 53.4905L457.96 75.2105C443.294 83.5838 428.11 90.7371 412.41 96.6705C409.424 94.7438 406.304 92.9505 403.05 91.2905C390.21 84.7305 377.88 77.4205 364.48 71.9505C353.92 67.2305 343.067 63.2405 331.92 59.9805C321.187 56.8338 313.174 54.6038 307.88 53.2905C306.767 53.0172 305.637 52.8372 304.49 52.7505C304.349 52.7391 304.208 52.7713 304.085 52.8427C303.962 52.9141 303.863 53.0214 303.8 53.1505L301.91 57.0805C302.157 55.1338 302.094 53.2505 301.72 51.4305C301.681 51.2523 301.606 51.0824 301.5 50.9305L301.17 50.4305L301.45 0.900489C301.452 0.832197 301.466 0.764839 301.494 0.702246C301.521 0.639654 301.561 0.583042 301.61 0.535681C301.659 0.488321 301.717 0.451129 301.781 0.426215C301.844 0.4013 301.912 0.389153 301.98 0.390479L313.8 0.670478Z" fill="#FD8005"/>
1479
+ <path d="M457.98 36.2305C435.55 45.7705 412.84 52.1705 389.27 57.8805C385.537 51.5605 383.057 47.6772 381.83 46.2305C378.604 42.4239 375.577 38.4505 372.75 34.3105C377.45 33.4238 385.494 31.7505 396.88 29.2905C418.88 24.5505 439.037 17.0172 457.35 6.69052C457.482 6.61569 457.596 6.51252 457.684 6.38818C457.772 6.26385 457.832 6.12134 457.86 5.97052L458.11 4.54053L457.98 36.2305Z" fill="#FCB10A"/>
1480
+ <path d="M457.98 36.2307L457.92 53.4907C437.64 59.9007 419.49 66.0907 396.8 70.3707C396.655 70.4001 396.505 70.3829 396.372 70.3217C396.239 70.2605 396.13 70.1585 396.06 70.0307L389.27 57.8807C412.84 52.1707 435.55 45.7707 457.98 36.2307Z" fill="#FB9708"/>
1481
+ <path d="M245.16 50.0405C244.92 57.0405 244.487 62.6005 243.86 66.7205C239.75 93.7505 224.43 100.88 198.77 98.8304L198.6 93.4504C198.595 93.309 198.535 93.1753 198.434 93.0781C198.333 92.9808 198.199 92.9278 198.06 92.9305L143.01 93.2104L142.48 92.8304L142.57 50.4504C142.57 50.3178 142.623 50.1907 142.716 50.0969C142.81 50.0031 142.937 49.9504 143.07 49.9504L245.16 50.0405Z" fill="#F43702"/>
1482
+ <path d="M285.14 50.2205C285.06 58.0205 285 65.8505 284.96 73.7105C284.87 89.1905 279.31 100.911 269.83 113.151L198.53 113.241L198.71 106.231L198.77 98.8305C224.43 100.881 239.75 93.7505 243.86 66.7205C244.487 62.6005 244.92 57.0405 245.16 50.0405L285.14 50.2205Z" fill="#D50E09"/>
1483
+ <path d="M301.17 50.4305L301.5 50.9305C301.606 51.0824 301.68 51.2522 301.72 51.4305C302.093 53.2505 302.157 55.1338 301.91 57.0804L301.65 113.18L269.83 113.15C279.31 100.91 284.87 89.1904 284.96 73.7104C285 65.8504 285.06 58.0205 285.14 50.2205L301.17 50.4305Z" fill="#B40C08"/>
1484
+ <path d="M364.48 71.9505C361.574 79.2638 358.63 86.5605 355.65 93.8405C352.85 100.651 349.58 107.721 345.81 113.221C339.24 122.761 332.19 130.931 325.76 139.971C325.732 140.01 325.716 140.056 325.713 140.105C325.71 140.153 325.721 140.201 325.744 140.244C325.766 140.286 325.801 140.322 325.843 140.346C325.884 140.37 325.932 140.382 325.98 140.381L345.5 140.481H302.13C301.998 140.481 301.871 140.427 301.777 140.331C301.683 140.236 301.63 140.106 301.63 139.971L301.65 113.181L301.91 57.0805L303.8 53.1505C303.863 53.0214 303.962 52.9141 304.085 52.8427C304.208 52.7713 304.349 52.7392 304.49 52.7505C305.637 52.8372 306.767 53.0172 307.88 53.2905C313.174 54.6039 321.187 56.8339 331.92 59.9805C343.067 63.2405 353.92 67.2305 364.48 71.9505Z" fill="#FD5303"/>
1485
+ <path d="M364.48 71.9504C377.88 77.4204 390.21 84.7305 403.05 91.2905C406.303 92.9505 409.423 94.7438 412.41 96.6704L427.03 106.28C416.937 116.06 408.863 127.244 402.81 139.83C402.787 139.879 402.776 139.932 402.778 139.986C402.781 140.039 402.797 140.091 402.824 140.137C402.852 140.183 402.891 140.221 402.938 140.248C402.984 140.274 403.036 140.289 403.09 140.29L411.43 140.49L345.5 140.48L325.98 140.38C325.932 140.382 325.884 140.37 325.842 140.346C325.8 140.321 325.766 140.286 325.743 140.243C325.72 140.201 325.71 140.153 325.713 140.105C325.716 140.056 325.732 140.01 325.76 139.97C332.19 130.93 339.24 122.76 345.81 113.22C349.58 107.72 352.85 100.65 355.65 93.8405C358.63 86.5605 361.573 79.2638 364.48 71.9504Z" fill="#F43702"/>
1486
+ <path d="M457.96 75.2107L457.89 106.061L439.69 116.351L427.03 106.281L412.41 96.6707C428.11 90.7374 443.293 83.584 457.96 75.2107Z" fill="#FD5303"/>
1487
+ <path d="M101.18 92.8306C109.79 103.171 119.01 112.481 131.45 118.091C137.69 120.904 145.07 122.914 153.59 124.121C168.63 126.247 183.49 125.277 198.17 121.211L197.98 150.451C180.494 157.277 162.604 158.677 144.31 154.651C132.564 152.064 121.264 148.154 110.41 142.921C95.6302 135.787 83.3169 125.654 73.4702 112.521C66.1835 102.794 61.4269 96.2639 59.2002 92.9306L101.18 92.8306Z" fill="#FD8005"/>
1488
+ <path d="M142.48 92.8306L143.01 93.2106C160.71 100.861 179.36 103.951 198.71 106.231L198.53 113.241L198.17 121.211C183.49 125.277 168.63 126.247 153.59 124.121C145.07 122.914 137.69 120.904 131.45 118.091C119.01 112.481 109.79 103.171 101.18 92.8306H142.48Z" fill="#FB9708"/>
1489
+ <path d="M198.77 98.8305L198.71 106.231C179.36 103.951 160.71 100.861 143.01 93.2105L198.06 92.9305C198.199 92.9279 198.333 92.9809 198.434 93.0782C198.535 93.1754 198.595 93.3091 198.6 93.4505L198.77 98.8305Z" fill="#FCB10A"/>
1490
+ <path d="M59.2001 92.9307C61.4268 96.264 66.1834 102.794 73.4701 112.521C83.3168 125.654 95.6301 135.787 110.41 142.921C121.263 148.154 132.563 152.064 144.31 154.651C162.603 158.677 180.493 157.277 197.98 150.451L197.87 163.351C197.869 163.393 197.859 163.434 197.842 163.472C197.825 163.511 197.8 163.545 197.769 163.574C197.739 163.603 197.703 163.625 197.663 163.64C197.624 163.655 197.582 163.662 197.54 163.661C182.733 162.981 168.72 163.031 155.5 163.811C149.45 164.171 143.05 165.731 135.95 167.761C132.61 168.721 129.377 169.571 126.25 170.311L87.4301 171.461C76.4701 163.114 66.0734 154.387 56.2401 145.281C43.0501 133.081 33.0101 120.891 24.3501 106.021C27.6601 103.611 31.0401 100.991 34.4801 99.1907C42.2134 95.164 50.4534 93.0773 59.2001 92.9307Z" fill="#FD5303"/>
1491
+ <path d="M457.89 106.061L457.98 132.371L457.03 134.881C456.985 135 456.908 135.104 456.807 135.183C456.707 135.262 456.587 135.312 456.46 135.327C456.334 135.342 456.205 135.323 456.089 135.271C455.972 135.218 455.873 135.135 455.8 135.031C451.107 128.424 445.737 122.197 439.69 116.351L457.89 106.061Z" fill="#F43702"/>
1492
+ <path d="M427.03 106.281L439.69 116.351C445.737 122.197 451.107 128.424 455.8 135.031C455.873 135.135 455.973 135.218 456.089 135.271C456.205 135.323 456.334 135.342 456.46 135.327C456.587 135.312 456.707 135.262 456.807 135.183C456.908 135.104 456.985 135 457.03 134.881L457.98 132.371L458.01 139.821C458.01 139.958 457.956 140.091 457.861 140.188C457.765 140.286 457.635 140.341 457.5 140.341L411.43 140.491L403.09 140.291C403.037 140.289 402.984 140.274 402.938 140.248C402.891 140.221 402.852 140.183 402.825 140.137C402.797 140.091 402.781 140.039 402.778 139.986C402.776 139.932 402.787 139.879 402.81 139.831C408.863 127.244 416.937 116.061 427.03 106.281Z" fill="#D50E09"/>
1493
+ <path d="M24.3502 106.021C33.0102 120.891 43.0502 133.081 56.2402 145.281C66.0735 154.387 76.4702 163.114 87.4302 171.461C77.8235 171.234 68.3669 170.331 59.0602 168.751C48.6302 166.991 39.2702 163.921 30.5902 159.701C23.3369 156.167 17.2169 150.381 12.2302 142.341C11.7502 141.561 11.2302 141.291 10.7602 140.801C10.6466 140.684 10.5586 140.543 10.5018 140.388C10.445 140.233 10.4206 140.067 10.4302 139.901C10.5369 138.074 10.2169 136.477 9.47021 135.111C10.2502 128.497 12.3136 122.384 15.6602 116.771C16.8736 114.731 19.7702 111.147 24.3502 106.021Z" fill="#F43702"/>
1494
+ <path d="M87.4302 171.461L126.25 170.311L116.23 175.061C116.024 175.014 115.79 175.041 115.53 175.141C111.924 176.514 107.84 178.194 103.28 180.181C101.614 180.901 97.5336 182.587 91.0403 185.241C85.1469 187.647 79.2969 190.444 73.4902 193.631L59.6302 202.291C46.6202 199.851 34.5802 196.481 23.8002 188.841C19.0136 185.454 14.1602 180.351 9.24023 173.531L9.47025 135.111C10.2169 136.477 10.5369 138.074 10.4302 139.901C10.4207 140.067 10.4451 140.234 10.5019 140.388C10.5587 140.543 10.6467 140.684 10.7603 140.801C11.2303 141.291 11.7503 141.561 12.2303 142.341C17.2169 150.381 23.3369 156.167 30.5902 159.701C39.2702 163.921 48.6302 166.991 59.0602 168.751C68.3669 170.331 77.8236 171.234 87.4302 171.461Z" fill="#D50E09"/>
1495
+ <path d="M59.6302 202.291C56.3902 204.857 54.4302 206.551 53.7502 207.371C47.9702 214.404 45.0069 222.55 44.8602 231.81C44.3269 242.817 46.4735 253.171 51.3002 262.871C53.0002 266.281 55.6102 269.08 57.9502 272.25C54.2636 272.244 50.5835 272.271 46.9102 272.331C44.1602 272.381 41.7102 271.36 39.0502 271.82C38.4829 271.919 37.9013 271.903 37.3402 271.771C33.1402 270.801 29.2902 270.131 25.8902 268.621C14.2102 263.447 8.56356 254.271 8.95023 241.091C9.04356 237.831 9.09021 236.157 9.09021 236.07C9.10354 215.304 9.15354 194.457 9.2402 173.531C14.1602 180.351 19.0135 185.454 23.8002 188.841C34.5802 196.481 46.6202 199.851 59.6302 202.291Z" fill="#B40C08"/>
1496
+ <path d="M116.23 175.061L115.53 183.811C115.519 183.956 115.538 184.103 115.586 184.241C115.634 184.379 115.709 184.506 115.808 184.613C115.907 184.72 116.026 184.805 116.159 184.863C116.292 184.921 116.435 184.951 116.58 184.951H165.55C165.746 184.951 165.935 185.029 166.074 185.167C166.212 185.306 166.29 185.494 166.29 185.691L166.16 210.281L165.8 213.171C165.793 213.229 165.773 213.285 165.741 213.334C165.71 213.384 165.667 213.425 165.617 213.456C165.567 213.487 165.511 213.506 165.453 213.512C165.394 213.518 165.335 213.511 165.28 213.491C155.98 210.277 146.384 206.774 136.49 202.981C124.35 198.321 113.16 195.421 101.01 195.021C94.3836 194.801 86.6902 194.947 77.9302 195.461C75.9302 195.041 74.4502 194.431 73.4902 193.631C79.2969 190.444 85.1469 187.647 91.0403 185.241C97.5336 182.587 101.614 180.901 103.28 180.181C107.84 178.194 111.924 176.514 115.53 175.141C115.79 175.041 116.024 175.014 116.23 175.061Z" fill="#FDC509"/>
1497
+ <path d="M166.16 210.281L166.47 230.241C165.83 234.054 165.697 237.537 166.07 240.691L165.34 243.031C164.927 243.151 164.34 242.864 163.58 242.171C163.408 242.011 163.216 241.877 163.01 241.771C155.49 237.941 149.23 233.451 141.81 229.171C133.07 224.137 118.614 215.701 98.4402 203.861C93.5002 200.961 86.6635 198.161 77.9302 195.461C86.6902 194.947 94.3835 194.801 101.01 195.021C113.16 195.421 124.35 198.321 136.49 202.981C146.384 206.774 155.98 210.277 165.28 213.491C165.335 213.511 165.394 213.518 165.453 213.512C165.511 213.506 165.567 213.487 165.617 213.456C165.667 213.425 165.71 213.384 165.741 213.334C165.773 213.285 165.793 213.229 165.8 213.171L166.16 210.281Z" fill="#FCB10A"/>
1498
+ <path d="M73.4903 193.631C74.4503 194.431 75.9303 195.041 77.9303 195.461C86.6637 198.161 93.5003 200.961 98.4403 203.861C118.614 215.701 133.07 224.137 141.81 229.171C149.23 233.451 155.49 237.941 163.01 241.771C163.216 241.877 163.408 242.011 163.58 242.171C164.34 242.864 164.927 243.151 165.34 243.031C165.694 251.404 165.71 259.897 165.39 268.511C165.384 268.564 165.44 269.107 165.56 270.141C165.627 270.794 165.514 271.534 165.22 272.361L142.01 272.251L144.1 272.071C144.137 272.069 144.173 272.055 144.201 272.031C144.229 272.006 144.247 271.973 144.253 271.936C144.259 271.9 144.252 271.862 144.233 271.83C144.214 271.798 144.185 271.773 144.15 271.761C106.3 255.641 78.1004 244.851 44.8604 231.811C45.007 222.551 47.9703 214.404 53.7503 207.371C54.4303 206.551 56.3903 204.857 59.6303 202.291L73.4903 193.631Z" fill="#E15E05"/>
1499
+ <path d="M238.59 230.27C220.64 240.02 200.94 245.97 180.9 249.64L166.07 240.69C165.697 237.537 165.83 234.054 166.47 230.24L238.59 230.27Z" fill="#B9D84B"/>
1500
+ <path d="M302.41 239.291C272.18 249.001 238 255.081 204.72 263.431C202.7 262.477 201.327 261.737 200.6 261.211C197.527 258.951 194.22 257.091 190.68 255.631C188.954 254.917 185.694 252.921 180.9 249.641C200.94 245.971 220.64 240.021 238.59 230.271L301.86 230.231C301.997 230.231 302.127 230.284 302.225 230.379C302.322 230.475 302.378 230.605 302.38 230.741L302.41 239.291Z" fill="#9EC744"/>
1501
+ <path d="M44.8604 231.811C78.1004 244.851 106.3 255.641 144.15 271.761C144.185 271.773 144.214 271.798 144.233 271.83C144.252 271.862 144.259 271.9 144.253 271.936C144.247 271.973 144.229 272.006 144.201 272.031C144.173 272.055 144.137 272.069 144.1 272.071L142.01 272.251H57.9504C55.6104 269.081 53.0003 266.281 51.3003 262.871C46.4737 253.171 44.327 242.817 44.8604 231.811Z" fill="#C14704"/>
1502
+ <path d="M302.41 239.291L302.33 251.051L302.25 253.781C302.247 253.936 302.207 254.089 302.135 254.228C302.062 254.366 301.958 254.487 301.83 254.581C292.05 261.574 282.387 266.63 272.84 269.75C260.967 273.637 249.087 277.521 237.2 281.401L228.57 276.81L204.72 263.431C238 255.081 272.18 249.001 302.41 239.291Z" fill="#6FB33D"/>
1503
+ <path d="M180.9 249.641C185.694 252.921 188.954 254.917 190.68 255.631C194.22 257.091 197.527 258.951 200.6 261.211C201.327 261.737 202.7 262.477 204.72 263.431L228.57 276.811C226.057 277.431 223.957 277.617 222.27 277.371C205.924 274.964 189.507 273.217 173.02 272.131C170.607 271.971 168.18 272.087 165.74 272.481C165.567 272.441 165.394 272.401 165.22 272.361C165.514 271.534 165.627 270.794 165.56 270.141C165.44 269.107 165.384 268.564 165.39 268.511C165.71 259.897 165.694 251.404 165.34 243.031L166.07 240.691L180.9 249.641Z" fill="#3E8832"/>
1504
+ <path d="M302.66 278.091C302.48 278.151 302.344 278.164 302.25 278.13L285.72 278.351C285.587 278.353 285.46 278.408 285.366 278.503C285.273 278.599 285.22 278.727 285.22 278.861L285.1 293.051L284.92 288.971C284.918 288.926 284.903 288.883 284.876 288.847C284.849 288.812 284.812 288.785 284.77 288.771C284.728 288.757 284.682 288.756 284.639 288.769C284.597 288.781 284.558 288.806 284.53 288.841C281.124 292.854 277.267 296.434 272.96 299.581L268.9 297.491L251.87 288.951L237.2 281.401C249.087 277.521 260.967 273.637 272.84 269.75C282.387 266.63 292.05 261.574 301.83 254.581C301.958 254.487 302.062 254.366 302.135 254.228C302.207 254.089 302.247 253.936 302.25 253.781L302.33 251.051L302.66 278.091Z" fill="#51A746"/>
1505
+ <path d="M228.57 276.811L237.2 281.401L251.87 288.951C232.51 295.641 215.41 298.621 195.07 298.041C185.317 297.767 175.547 297.291 165.76 296.611L165.74 272.481C168.18 272.087 170.607 271.971 173.02 272.131C189.507 273.217 205.924 274.964 222.27 277.371C223.957 277.617 226.057 277.431 228.57 276.811Z" fill="#138B74"/>
1506
+ <path d="M302.25 278.131C302.544 291.404 303.787 304.594 305.98 317.701C298.66 314.654 291.737 310.877 285.21 306.371C285.097 306.017 285.044 305.657 285.05 305.291L285.1 293.051L285.22 278.861C285.22 278.727 285.273 278.599 285.366 278.503C285.46 278.408 285.587 278.353 285.72 278.351L302.25 278.131Z" fill="#B9D84B"/>
1507
+ <path d="M302.66 278.091C302.874 278.351 303.144 278.481 303.47 278.481C317.484 278.447 331.454 278.404 345.38 278.351C348.97 297.861 351.16 316.261 348.91 335.831L342.23 333.291L310.19 319.551L305.98 317.701C303.787 304.594 302.544 291.404 302.25 278.131C302.344 278.164 302.48 278.151 302.66 278.091Z" fill="#91D95B"/>
1508
+ <path d="M372.67 278.341C373.284 282.667 373.994 286.927 374.8 291.121C377.407 304.647 379.504 318.251 381.09 331.931C381.72 337.391 382.64 342.631 383.48 348.001L371.93 344.501L348.91 335.831C351.16 316.261 348.97 297.861 345.38 278.351L372.67 278.341Z" fill="#66C96E"/>
1509
+ <path d="M430.47 278.361L427.18 278.791C427.051 278.81 426.935 278.878 426.853 278.98C426.772 279.082 426.731 279.21 426.74 279.341C428.15 299.531 428.81 317.271 426.52 336.871C414.11 343.311 400.12 348.051 386.32 348.451L383.48 348.001C382.64 342.631 381.72 337.391 381.09 331.931C379.504 318.251 377.407 304.647 374.8 291.121C373.994 286.927 373.284 282.667 372.67 278.341L430.47 278.361Z" fill="#47B874"/>
1510
+ <path d="M430.47 278.361C441.23 279.521 449.1 284.811 454.08 294.231C455.233 296.417 456.033 298.797 456.48 301.371C456.947 304.037 457.137 306.544 457.05 308.891C455.017 310.737 453.367 313.231 452.1 316.371C445.513 325.524 436.987 332.357 426.52 336.871C428.81 317.271 428.15 299.531 426.74 279.341C426.731 279.21 426.771 279.082 426.853 278.98C426.934 278.878 427.051 278.81 427.18 278.791L430.47 278.361Z" fill="#24A37C"/>
1511
+ <path d="M285.1 293.051L285.05 305.291L277.95 302.321L272.96 299.581C277.267 296.434 281.124 292.854 284.53 288.841C284.559 288.806 284.597 288.781 284.64 288.769C284.682 288.756 284.728 288.757 284.77 288.771C284.812 288.785 284.85 288.812 284.876 288.848C284.903 288.883 284.919 288.926 284.92 288.971L285.1 293.051Z" fill="#0D6F68"/>
1512
+ <path d="M251.87 288.95L268.9 297.49C253.35 305.63 237.98 311.24 220.33 312.18C202.82 313.12 184.85 311.62 166.59 308.53C166.449 308.507 166.319 308.441 166.215 308.341C166.112 308.241 166.04 308.112 166.01 307.97L165.78 306.87L165.76 296.61C175.547 297.29 185.317 297.767 195.07 298.04C215.41 298.62 232.51 295.64 251.87 288.95Z" fill="#0D6F68"/>
1513
+ <path d="M272.96 299.58L277.95 302.32C268.63 306.787 261.46 309.924 256.44 311.73C227.42 322.17 196.72 323.04 166.65 316.01C166.518 315.98 166.396 315.916 166.295 315.825C166.194 315.734 166.116 315.619 166.07 315.49L165.78 314.62V306.87L166.01 307.97C166.04 308.112 166.112 308.241 166.215 308.341C166.319 308.441 166.449 308.507 166.59 308.53C184.85 311.62 202.82 313.12 220.33 312.18C237.98 311.24 253.35 305.63 268.9 297.49L272.96 299.58Z" fill="#0D6562"/>
1514
+ <path d="M277.95 302.321L285.05 305.291C285.044 305.657 285.097 306.017 285.21 306.371L285.27 307.241C269.14 315.921 252.85 323.121 234.8 326.681C220.014 329.601 203.45 330.587 185.11 329.641C179.944 329.374 173.514 328.444 165.82 326.851L165.78 314.621L166.07 315.491C166.116 315.619 166.194 315.734 166.295 315.825C166.396 315.916 166.518 315.98 166.65 316.011C196.72 323.041 227.42 322.171 256.44 311.731C261.46 309.924 268.63 306.787 277.95 302.321Z" fill="#085A66"/>
1515
+ <path d="M305.98 317.701L310.19 319.551C309.737 324.204 308.924 328.754 307.75 333.201C305.83 340.501 301.32 341.541 294.93 343.601C292.27 343.781 288.65 343.171 286.15 344.211L285.41 343.611L285.31 320.761L285.27 307.241L285.21 306.371C291.737 310.877 298.66 314.654 305.98 317.701Z" fill="#9EC744"/>
1516
+ <path d="M285.27 307.24L285.31 320.76C281.043 325.08 277.617 327.94 275.03 329.34C261.29 336.774 246.91 340.33 231.89 340.01C216.963 339.69 202.047 339.897 187.14 340.63C179.947 340.99 172.83 340.497 165.79 339.15L165.82 326.85C173.513 328.444 179.943 329.374 185.11 329.64C203.45 330.587 220.013 329.6 234.8 326.68C252.85 323.12 269.14 315.92 285.27 307.24Z" fill="#094A57"/>
1517
+ <path d="M457.05 308.891L457.08 315.981C454.687 326.534 451.457 335.394 447.39 342.561C442.57 351.047 435.72 360.154 426.84 369.881C412.08 386.061 393 397.051 370.56 395.381C370.494 395.375 370.428 395.383 370.365 395.404C370.302 395.425 370.244 395.458 370.195 395.502C370.145 395.546 370.105 395.6 370.077 395.66C370.049 395.72 370.033 395.784 370.03 395.851L369.86 401.381L369.74 395.891L369.79 388.331C383.264 382.377 392.687 377.934 398.06 375.001C421.5 362.221 440.09 340.221 452.1 316.371C453.367 313.231 455.017 310.737 457.05 308.891Z" fill="#085A66"/>
1518
+ <path d="M457.08 315.981L457.1 359.001C452.1 370.534 446.394 380.167 439.98 387.901C431.42 398.221 419.82 406.934 405.18 414.041C393.86 419.531 382.06 423.941 370.53 428.991C370.396 429.049 370.28 429.141 370.194 429.259C370.108 429.377 370.055 429.516 370.04 429.661L369.82 431.881L369.86 401.381L370.03 395.851C370.033 395.785 370.049 395.72 370.077 395.66C370.105 395.6 370.145 395.546 370.195 395.502C370.244 395.459 370.302 395.425 370.365 395.404C370.428 395.383 370.494 395.375 370.56 395.381C393 397.051 412.08 386.061 426.84 369.881C435.72 360.154 442.57 351.047 447.39 342.561C451.457 335.394 454.687 326.534 457.08 315.981Z" fill="#094A57"/>
1519
+ <path d="M452.1 316.371C440.09 340.221 421.5 362.221 398.06 375.001C392.687 377.934 383.263 382.377 369.79 388.331L369.93 367.821C375.957 365.554 381.573 362.491 386.78 358.631C388.84 357.101 391.75 353.811 389.66 351.181C388.66 349.927 387.547 349.017 386.32 348.451C400.12 348.051 414.11 343.311 426.52 336.871C436.987 332.357 445.513 325.524 452.1 316.371Z" fill="#0D6F68"/>
1520
+ <path d="M285.31 320.76L285.41 343.611L166.07 343.741C166.007 343.741 165.944 343.728 165.885 343.702C165.827 343.677 165.774 343.64 165.73 343.593C165.686 343.546 165.652 343.491 165.63 343.43C165.608 343.37 165.597 343.305 165.6 343.241L165.79 339.151C172.83 340.497 179.947 340.99 187.14 340.63C202.047 339.897 216.963 339.69 231.89 340.01C246.91 340.33 261.29 336.774 275.03 329.341C277.617 327.941 281.043 325.08 285.31 320.76Z" fill="#083747"/>
1521
+ <path d="M342.23 333.291C340 335.641 335.26 340.99 337 344.75L321.43 344.471L304.91 343.931L294.93 343.601C301.32 341.541 305.83 340.5 307.75 333.201C308.924 328.754 309.737 324.204 310.19 319.551L342.23 333.291Z" fill="#6FB33D"/>
1522
+ <path d="M342.23 333.291L348.91 335.831L371.93 344.5C370.41 346.647 369.684 349.344 369.75 352.591C369.917 350.444 369.777 348.624 369.33 347.13C369.191 346.662 368.907 346.251 368.519 345.954C368.131 345.658 367.659 345.492 367.17 345.481L347.72 345.06L337 344.75C335.26 340.99 340 335.641 342.23 333.291Z" fill="#3E8832"/>
1523
+ <path d="M294.93 343.601L304.91 343.931C302.457 350.071 299.12 357.417 294.9 365.971C289.174 377.584 281.674 387.301 272.4 395.121C277.16 389.174 280.854 383.334 283.48 377.601C285.42 373.361 286.01 368.651 286.05 363.471C286.104 357.051 286.137 350.631 286.15 344.211C288.65 343.171 292.27 343.781 294.93 343.601Z" fill="#B9D84B"/>
1524
+ <path d="M321.43 344.471C313.997 363.151 303.497 379.941 289.93 394.841C287.484 396.181 284.937 397.387 282.29 398.461C279.364 399.654 276.79 400.791 274.57 401.871C269.61 404.291 264.47 406.334 259.15 408.001L272.4 395.121C281.674 387.301 289.174 377.584 294.9 365.971C299.12 357.417 302.457 350.071 304.91 343.931L321.43 344.471Z" fill="#91D95B"/>
1525
+ <path d="M337 344.75L347.72 345.06L334 371.7L324.16 376.85L289.93 394.84C303.497 379.94 313.997 363.15 321.43 344.47L337 344.75Z" fill="#66C96E"/>
1526
+ <path d="M371.93 344.5L383.48 348L386.32 348.451C387.547 349.017 388.66 349.927 389.66 351.181C391.75 353.811 388.84 357.1 386.78 358.63C381.573 362.49 375.957 365.554 369.93 367.82L369.58 364.841L369.35 354.601L369.75 352.591C369.683 349.344 370.41 346.647 371.93 344.5Z" fill="#195239"/>
1527
+ <path d="M369.75 352.591L369.35 354.601L334 371.701L347.72 345.061L367.17 345.481C367.659 345.492 368.131 345.658 368.519 345.954C368.907 346.251 369.191 346.663 369.33 347.131C369.777 348.624 369.917 350.444 369.75 352.591Z" fill="#47B874"/>
1528
+ <path d="M369.35 354.601L369.58 364.841C359.094 374.247 348.404 383.401 337.51 392.301C318.67 407.681 300.67 422.741 287.46 443.421L240.63 443.391C263.26 429.261 279.93 415.741 302.14 397.141C308.934 391.447 316.274 384.684 324.16 376.851L334 371.701L369.35 354.601Z" fill="#209D93"/>
1529
+ <path d="M457.1 359V416.901C457.1 417.226 457.063 417.555 456.99 417.88C455.13 425.927 450.527 431.751 443.18 435.351C435.42 439.151 426.23 441.351 415.61 441.951C415.317 441.97 415.027 442.011 414.74 442.07C412.42 442.604 409.077 442.891 404.71 442.931C393.25 443.031 381.707 443.017 370.08 442.891L369.82 431.88L370.04 429.661C370.055 429.515 370.108 429.377 370.194 429.259C370.28 429.141 370.396 429.049 370.53 428.991C382.06 423.941 393.86 419.531 405.18 414.041C419.82 406.934 431.42 398.221 439.98 387.901C446.394 380.167 452.1 370.534 457.1 359Z" fill="#083747"/>
1530
+ <path d="M369.93 367.821L369.79 388.331L369.74 395.891C362.754 400.677 355.957 405.714 349.35 411.001C337.85 420.207 328.034 431.024 319.9 443.451L298.19 443.461L287.46 443.421C300.67 422.741 318.67 407.681 337.51 392.301C348.404 383.401 359.094 374.247 369.58 364.841L369.93 367.821Z" fill="#188495"/>
1531
+ <path d="M324.16 376.851C316.273 384.684 308.933 391.447 302.14 397.141C279.93 415.741 263.26 429.261 240.63 443.391L187.51 442.911C180.423 443.284 173.767 443.127 167.54 442.441L154.62 441.441C156.88 441.001 159.203 440.824 161.59 440.911C162.566 440.944 163.544 440.85 164.5 440.631C167.073 440.024 172.077 439.091 179.51 437.831C182.517 437.317 187.687 436.261 195.02 434.661C200.367 433.487 205.457 432.094 210.29 430.481C227.47 424.734 243.757 417.241 259.15 408.001C264.47 406.334 269.61 404.291 274.57 401.871C276.79 400.791 279.363 399.654 282.29 398.461C284.937 397.387 287.483 396.181 289.93 394.841L324.16 376.851Z" fill="#2FB991"/>
1532
+ <path d="M20.5104 391.171L25.8704 430.441C25.7838 430.347 25.6271 430.304 25.4004 430.311C18.4538 425.744 11.8504 420.674 5.59043 415.101L0.29044 403.041L0.0904283 391.721C0.0891266 391.655 0.101039 391.59 0.125462 391.529C0.149885 391.467 0.186333 391.412 0.232762 391.364C0.279192 391.317 0.334695 391.279 0.396062 391.253C0.457429 391.226 0.523466 391.212 0.590428 391.211L20.5104 391.171Z" fill="#6FB33D"/>
1533
+ <path d="M74.4302 391.171L76.5403 391.361C76.6938 391.376 76.8398 391.432 76.9617 391.524C77.0836 391.616 77.1766 391.74 77.2303 391.881C80.7103 401.091 83.6202 409.861 84.5302 419.481C84.7902 422.154 84.8236 426.561 84.6302 432.701C84.4502 438.467 84.3136 444.244 84.2202 450.031C71.6202 448.331 59.0802 444.701 47.1302 440.511C43.8102 439.351 40.2169 437.774 36.3503 435.781C32.8836 434.001 29.3902 432.221 25.8702 430.441L20.5103 391.171H74.4302Z" fill="#9EC744"/>
1534
+ <path d="M149.67 442.011L149.33 450.461C140.184 451.747 131.95 452.417 124.63 452.471C121.95 452.491 115.47 452.351 105.19 452.051C98.1569 451.891 91.1669 451.217 84.2202 450.031C84.3135 444.244 84.4502 438.467 84.6302 432.701C84.8235 426.561 84.7902 422.154 84.5302 419.481C83.6202 409.861 80.7102 401.091 77.2302 391.881C77.1765 391.74 77.0835 391.616 76.9616 391.524C76.8397 391.432 76.6938 391.376 76.5402 391.361L74.4302 391.171L149.56 391.181C149.605 391.181 149.649 391.199 149.68 391.23C149.712 391.262 149.73 391.306 149.73 391.351L149.67 442.011Z" fill="#B9D84B"/>
1535
+ <path d="M369.74 395.891L369.86 401.381L369.82 431.881L370.08 442.891L369.69 443.511L323.42 443.521L319.9 443.451C328.034 431.024 337.85 420.207 349.35 411.001C355.957 405.714 362.754 400.677 369.74 395.891Z" fill="#177492"/>
1536
+ <path d="M5.59 415.101C5.55 423.001 8.00666 430.054 12.96 436.26C16.3333 440.48 19.79 443.724 23.33 445.991C27.5433 448.684 33.2733 451.75 40.52 455.19C57.9867 462.264 76.0333 467.511 94.66 470.931C96.5467 471.277 98.3433 471.53 100.05 471.69C103.037 472.144 105.937 472.551 108.75 472.911C114.997 473.711 121.237 474.551 127.47 475.431C131.443 475.991 138.787 476.564 149.5 477.151L149.63 492.621L149.39 495.56C149.375 495.701 149.31 495.831 149.206 495.925C149.103 496.019 148.969 496.071 148.83 496.07C139.777 496.11 131.51 495.864 124.03 495.331C109.397 494.284 94.55 491.387 79.49 486.641C63.8 481.701 32.04 470.251 0 460.361L0.290009 403.041L5.59 415.101Z" fill="#0D6F68"/>
1537
+ <path d="M25.4003 430.311C30.3603 441.151 33.0803 447.691 40.5203 455.191C33.2737 451.751 27.5436 448.684 23.3303 445.991C19.7903 443.724 16.3337 440.481 12.9603 436.261C8.00699 430.054 5.55032 423.001 5.59032 415.101C11.8503 420.674 18.4537 425.744 25.4003 430.311Z" fill="#3E8832"/>
1538
+ <path d="M25.8704 430.44C29.3904 432.22 32.8837 434.001 36.3504 435.781C40.2171 437.774 43.8104 439.35 47.1304 440.51C59.0804 444.7 71.6204 448.331 84.2204 450.031C91.1671 451.217 98.1571 451.891 105.19 452.051C104.737 458.857 103.024 465.404 100.05 471.69C98.3437 471.53 96.5471 471.277 94.6604 470.931C76.0337 467.511 57.9871 462.264 40.5204 455.19C33.0804 447.69 30.3604 441.15 25.4004 430.31C25.6271 430.304 25.7837 430.347 25.8704 430.44Z" fill="#51A746"/>
1539
+ <path d="M154.62 441.441L167.54 442.441C177.66 451.221 188.667 458.281 200.56 463.621C233.093 478.207 265.06 476.837 296.46 459.511C307.28 453.537 316.267 448.207 323.42 443.521L369.69 443.511C369.717 450.857 369.717 458.064 369.69 465.131C369.663 470.631 369.233 474.557 368.4 476.911C364.79 487.061 355.34 493.051 344.99 495.841C341.423 496.801 336.823 497.584 331.19 498.191C327.55 498.584 322.893 498.784 317.22 498.791C246.393 498.924 196.977 498.977 168.97 498.951C161.323 498.944 154.94 499.034 149.82 499.221L149.63 492.621L149.5 477.151L149.33 450.461L149.67 442.011L154.62 441.441Z" fill="#083747"/>
1540
+ <path d="M187.51 442.911C217.33 458.331 248.91 466.001 280.06 448.931C285.333 446.037 288.407 444.351 289.28 443.871C289.55 443.726 289.848 443.647 290.15 443.641L298.19 443.461L319.9 443.451L323.42 443.521C316.267 448.207 307.28 453.537 296.46 459.511C265.06 476.837 233.093 478.207 200.56 463.621C188.667 458.281 177.66 451.221 167.54 442.441C173.767 443.127 180.423 443.284 187.51 442.911Z" fill="#094A57"/>
1541
+ <path d="M240.63 443.391L287.46 443.421L298.19 443.461L290.15 443.641C289.848 443.647 289.55 443.726 289.28 443.871C288.407 444.351 285.334 446.037 280.06 448.931C248.91 466.001 217.33 458.331 187.51 442.911L240.63 443.391Z" fill="#085A66"/>
1542
+ <path d="M149.33 450.461L149.5 477.151C138.787 476.564 131.444 475.991 127.47 475.431C121.237 474.551 114.997 473.711 108.75 472.911C105.937 472.551 103.037 472.144 100.05 471.691C103.024 465.404 104.737 458.857 105.19 452.051C115.47 452.351 121.95 452.491 124.63 452.471C131.95 452.417 140.184 451.747 149.33 450.461Z" fill="#47B874"/>
1543
+ <path d="M149.63 492.621L149.82 499.221L149.69 502.791C124.58 513.291 98.88 509.941 73.68 502.541C61.2333 498.887 48.9233 494.951 36.75 490.731C24.49 486.477 12.2433 482.097 0.0100098 477.591L0 460.361C32.04 470.251 63.8 481.701 79.49 486.641C94.55 491.387 109.397 494.284 124.03 495.331C131.51 495.864 139.777 496.111 148.83 496.071C148.969 496.071 149.103 496.019 149.206 495.925C149.31 495.831 149.375 495.701 149.39 495.561L149.63 492.621Z" fill="#0D6562"/>
1544
+ <path d="M149.69 502.791L149.72 510.591L148.37 522.611C148.356 522.743 148.298 522.867 148.206 522.963C148.114 523.059 147.992 523.121 147.86 523.141C124.52 526.731 101.33 528.021 78.1802 522.711C62.8802 519.204 46.2036 514.057 28.1502 507.271C19.3636 503.964 9.98359 499.657 0.0102539 494.351V477.591C12.2436 482.097 24.4902 486.477 36.7502 490.731C48.9236 494.951 61.2336 498.887 73.6802 502.541C98.8802 509.941 124.58 513.291 149.69 502.791Z" fill="#094A57"/>
1545
+ <path d="M149.72 510.591L149.83 538.721C149.83 538.851 149.78 538.975 149.69 539.067C149.6 539.159 149.478 539.211 149.35 539.211H0.270233C0.230451 539.211 0.192315 539.195 0.164185 539.167C0.136054 539.138 0.120239 539.1 0.120239 539.061L0.0102539 494.351C9.98359 499.657 19.3636 503.964 28.1502 507.271C46.2036 514.057 62.8802 519.204 78.1802 522.711C101.33 528.021 124.52 526.731 147.86 523.141C147.992 523.121 148.114 523.059 148.206 522.963C148.298 522.867 148.356 522.743 148.37 522.611L149.72 510.591Z" fill="#083747"/>
1546
+ </svg>`}static appCss(){return`@import "tailwindcss";
1547
+ @source "../node_modules/@beeblock/svelar/src/ui";
2091
1548
 
2092
1549
  @theme {
2093
1550
  --color-brand: #ff3e00;
@@ -2117,9 +1574,9 @@ import { PDF } from '@beeblock/svelar/pdf';
2117
1574
  import { configureDashboard } from '@beeblock/svelar/dashboard';
2118
1575
  import { Broadcast } from '@beeblock/svelar/broadcasting';
2119
1576
  import { Notifier } from '@beeblock/svelar/notifications';
2120
- import { User } from './lib/models/User.js';
1577
+ import { User } from './lib/modules/auth/User.js';
2121
1578
  import { EventServiceProvider } from './lib/shared/providers/EventServiceProvider.js';
2122
- import './lib/auth/gates.js';
1579
+ import './lib/modules/auth/gates.js';
2123
1580
 
2124
1581
  // \u2500\u2500 Database (SQLite) \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
2125
1582
  Connection.configure({
@@ -2239,14 +1696,14 @@ export { Connection, Hash, Broadcast };
2239
1696
 
2240
1697
  import { createSvelarApp } from '@beeblock/svelar/hooks';
2241
1698
  import { DatabaseSessionStore } from '@beeblock/svelar/session';
1699
+ import { env } from '$env/dynamic/private';
2242
1700
 
2243
1701
  // Import app.ts to trigger database + hashing + auth configuration
2244
1702
  import { auth } from './app.js';
2245
1703
 
2246
1704
  export const { handle, handleError } = createSvelarApp({
2247
1705
  auth,
2248
- // WARNING: Set APP_KEY to a random 32+ char string in production
2249
- secret: process.env.APP_KEY || 'change-me-in-production',
1706
+ secret: env.APP_KEY,
2250
1707
  sessionStore: new DatabaseSessionStore(),
2251
1708
  csrfExcludePaths: ['/api/webhooks', '/api/internal/'],
2252
1709
  });
@@ -2290,11 +1747,17 @@ DB_PATH=database.db
2290
1747
  # RESEND_API_KEY=re_your-resend-api-key
2291
1748
 
2292
1749
  # Redis (optional \u2014 needed for BullMQ queue and Redis cache/session)
2293
- # REDIS_URL=redis://localhost:6379
1750
+ # REDIS_HOST=localhost
1751
+ # REDIS_PORT=6379
1752
+ # REDIS_PASSWORD=
2294
1753
 
2295
1754
  # Queue driver (sync = immediate, redis = background via BullMQ)
2296
1755
  # QUEUE_DRIVER=sync
2297
1756
 
1757
+ # Meilisearch (optional \u2014 full-text search engine)
1758
+ # MEILISEARCH_HOST=http://localhost:7700
1759
+ # MEILISEARCH_KEY=
1760
+
2298
1761
  # PDF (default driver is pdfkit \u2014 no config needed)
2299
1762
  # Switch to Gotenberg for pixel-perfect HTML rendering:
2300
1763
  # PDF_DRIVER=gotenberg
@@ -2359,7 +1822,7 @@ export class User extends HasRoles(Model) {
2359
1822
  // Enable audit logging for User model (tracks create/update/delete)
2360
1823
  auditable(User);
2361
1824
 
2362
- import { Post } from './Post.js';
1825
+ import { Post } from '$lib/modules/posts/Post.js';
2363
1826
  `}static postModel(){return`import { Model } from '@beeblock/svelar/orm';
2364
1827
  import { auditable } from '@beeblock/svelar/audit';
2365
1828
 
@@ -2391,9 +1854,9 @@ export class Post extends Model {
2391
1854
  // Enable audit logging for Post model (tracks create/update/delete)
2392
1855
  auditable(Post);
2393
1856
 
2394
- import { User } from './User.js';
1857
+ import { User } from '$lib/modules/auth/User.js';
2395
1858
  `}static userRepository(){return`import { Repository } from '@beeblock/svelar/repositories';
2396
- import { User } from '../models/User.js';
1859
+ import { User } from './User.js';
2397
1860
 
2398
1861
  export class UserRepository extends Repository<User> {
2399
1862
  model() {
@@ -2409,7 +1872,7 @@ export class UserRepository extends Repository<User> {
2409
1872
  }
2410
1873
  }
2411
1874
  `}static postRepository(){return`import { Repository } from '@beeblock/svelar/repositories';
2412
- import { Post } from '../models/Post.js';
1875
+ import { Post } from './Post.js';
2413
1876
 
2414
1877
  export class PostRepository extends Repository<Post> {
2415
1878
  model() {
@@ -2437,8 +1900,8 @@ export class PostRepository extends Repository<Post> {
2437
1900
  `}static authService(){return`import { Service } from '@beeblock/svelar/services';
2438
1901
  import { Hash } from '@beeblock/svelar/hashing';
2439
1902
  import { Event } from '@beeblock/svelar/events';
2440
- import { UserRepository } from '../repositories/UserRepository.js';
2441
- import { UserRegistered } from '../events/UserRegistered.js';
1903
+ import { UserRepository } from './UserRepository.js';
1904
+ import { UserRegistered } from './UserRegistered.js';
2442
1905
 
2443
1906
  const userRepo = new UserRepository();
2444
1907
 
@@ -2505,8 +1968,8 @@ export class AuthService extends Service {
2505
1968
  `}static postService(){return`import { CrudService } from '@beeblock/svelar/services';
2506
1969
  import { Repository } from '@beeblock/svelar/repositories';
2507
1970
  import { Broadcast } from '@beeblock/svelar/broadcasting';
2508
- import { PostRepository } from '../repositories/PostRepository.js';
2509
- import type { Post } from '../models/Post.js';
1971
+ import { PostRepository } from './PostRepository.js';
1972
+ import type { Post } from './Post.js';
2510
1973
 
2511
1974
  const postRepo = new PostRepository();
2512
1975
 
@@ -2544,11 +2007,15 @@ export class PostService extends CrudService<Post> {
2544
2007
  }
2545
2008
  }
2546
2009
  `}static authController(){return`import { Controller } from '@beeblock/svelar/routing';
2547
- import { RegisterRequest } from '../dtos/RegisterRequest.js';
2548
- import { LoginRequest } from '../dtos/LoginRequest.js';
2549
- import { RegisterUserAction } from '../actions/RegisterUserAction.js';
2550
- import { AuthService } from '../services/AuthService.js';
2551
- import { UserResource } from '../resources/UserResource.js';
2010
+ import { RegisterRequest } from './RegisterRequest.js';
2011
+ import { LoginRequest } from './LoginRequest.js';
2012
+ import { ForgotPasswordRequest } from './ForgotPasswordRequest.js';
2013
+ import { ResetPasswordRequest } from './ResetPasswordRequest.js';
2014
+ import { OtpSendRequest } from './OtpSendRequest.js';
2015
+ import { OtpVerifyRequest } from './OtpVerifyRequest.js';
2016
+ import { RegisterUserAction } from './RegisterUserAction.js';
2017
+ import { AuthService } from './AuthService.js';
2018
+ import { UserResource } from './UserResource.js';
2552
2019
 
2553
2020
  const registerAction = new RegisterUserAction();
2554
2021
  const authService = new AuthService();
@@ -2612,21 +2079,15 @@ export class AuthController extends Controller {
2612
2079
 
2613
2080
  /** POST /api/auth/forgot-password */
2614
2081
  async forgotPassword(event: any) {
2615
- const { email } = await event.request.json();
2616
- if (!email) return this.json({ message: 'Email is required' }, 422);
2617
-
2618
- const result = await authService.forgotPassword(email, event.locals.auth);
2082
+ const data = await ForgotPasswordRequest.validate(event);
2083
+ const result = await authService.forgotPassword(data.email, event.locals.auth);
2619
2084
  return this.json(result.data);
2620
2085
  }
2621
2086
 
2622
2087
  /** POST /api/auth/reset-password */
2623
2088
  async resetPassword(event: any) {
2624
- const { token, email, password } = await event.request.json();
2625
- if (!token || !email || !password) {
2626
- return this.json({ message: 'Token, email, and password are required' }, 422);
2627
- }
2628
-
2629
- const result = await authService.resetPassword(token, email, password, event.locals.auth);
2089
+ const data = await ResetPasswordRequest.validate(event);
2090
+ const result = await authService.resetPassword(data.token, data.email, data.password, event.locals.auth);
2630
2091
  if (!result.success) {
2631
2092
  return this.json({ message: result.error }, 400);
2632
2093
  }
@@ -2635,19 +2096,15 @@ export class AuthController extends Controller {
2635
2096
 
2636
2097
  /** POST /api/auth/otp/send */
2637
2098
  async sendOtp(event: any) {
2638
- const { email } = await event.request.json();
2639
- if (!email) return this.json({ message: 'Email is required' }, 422);
2640
-
2641
- const result = await authService.sendOtp(email, event.locals.auth);
2099
+ const data = await OtpSendRequest.validate(event);
2100
+ const result = await authService.sendOtp(data.email, event.locals.auth);
2642
2101
  return this.json(result.data);
2643
2102
  }
2644
2103
 
2645
2104
  /** POST /api/auth/otp/verify */
2646
2105
  async verifyOtp(event: any) {
2647
- const { email, code } = await event.request.json();
2648
- if (!email || !code) return this.json({ message: 'Email and code are required' }, 422);
2649
-
2650
- const result = await authService.verifyOtp(email, code, event.locals.auth, event.locals.session);
2106
+ const data = await OtpVerifyRequest.validate(event);
2107
+ const result = await authService.verifyOtp(data.email, data.code, event.locals.auth, event.locals.session);
2651
2108
  if (!result.success) {
2652
2109
  return this.json({ message: result.error }, 401);
2653
2110
  }
@@ -2673,11 +2130,11 @@ export class AuthController extends Controller {
2673
2130
  }
2674
2131
  }
2675
2132
  `}static postController(){return`import { Controller } from '@beeblock/svelar/routing';
2676
- import { CreatePostRequest } from '../dtos/CreatePostRequest.js';
2677
- import { UpdatePostRequest } from '../dtos/UpdatePostRequest.js';
2678
- import { PostService } from '../services/PostService.js';
2679
- import { CreatePostAction } from '../actions/CreatePostAction.js';
2680
- import { PostResource } from '../resources/PostResource.js';
2133
+ import { CreatePostRequest } from './CreatePostRequest.js';
2134
+ import { UpdatePostRequest } from './UpdatePostRequest.js';
2135
+ import { PostService } from './PostService.js';
2136
+ import { CreatePostAction } from './CreatePostAction.js';
2137
+ import { PostResource } from './PostResource.js';
2681
2138
 
2682
2139
  const postService = new PostService();
2683
2140
  const createPostAction = new CreatePostAction();
@@ -2748,20 +2205,20 @@ export class PostController extends Controller {
2748
2205
  }
2749
2206
  `}static adminController(){return`import { Controller } from '@beeblock/svelar/routing';
2750
2207
  import { Gate } from '@beeblock/svelar/auth';
2751
- import { AdminService } from '../services/AdminService.js';
2752
- import { UserResource } from '../resources/UserResource.js';
2753
- import { RoleResource } from '../resources/RoleResource.js';
2754
- import { PermissionResource } from '../resources/PermissionResource.js';
2755
- import { UpdateUserRoleRequest } from '../dtos/UpdateUserRoleRequest.js';
2756
- import { DeleteUserRequest } from '../dtos/DeleteUserRequest.js';
2757
- import { CreateRoleRequest } from '../dtos/CreateRoleRequest.js';
2758
- import { DeleteRoleRequest } from '../dtos/DeleteRoleRequest.js';
2759
- import { CreatePermissionRequest } from '../dtos/CreatePermissionRequest.js';
2760
- import { DeletePermissionRequest } from '../dtos/DeletePermissionRequest.js';
2761
- import { RolePermissionRequest } from '../dtos/RolePermissionRequest.js';
2762
- import { UserRoleRequest } from '../dtos/UserRoleRequest.js';
2763
- import { UserPermissionRequest } from '../dtos/UserPermissionRequest.js';
2764
- import { ExportDataRequest } from '../dtos/ExportDataRequest.js';
2208
+ import { AdminService } from './AdminService.js';
2209
+ import { UserResource } from '$lib/modules/auth/UserResource.js';
2210
+ import { RoleResource } from './RoleResource.js';
2211
+ import { PermissionResource } from './PermissionResource.js';
2212
+ import { UpdateUserRoleRequest } from './UpdateUserRoleRequest.js';
2213
+ import { DeleteUserRequest } from './DeleteUserRequest.js';
2214
+ import { CreateRoleRequest } from './CreateRoleRequest.js';
2215
+ import { DeleteRoleRequest } from './DeleteRoleRequest.js';
2216
+ import { CreatePermissionRequest } from './CreatePermissionRequest.js';
2217
+ import { DeletePermissionRequest } from './DeletePermissionRequest.js';
2218
+ import { RolePermissionRequest } from './RolePermissionRequest.js';
2219
+ import { UserRoleRequest } from './UserRoleRequest.js';
2220
+ import { UserPermissionRequest } from './UserPermissionRequest.js';
2221
+ import { ExportDataRequest } from './ExportDataRequest.js';
2765
2222
 
2766
2223
  const adminService = new AdminService();
2767
2224
 
@@ -2920,24 +2377,56 @@ export class AdminController extends Controller {
2920
2377
  return this.json(result.data);
2921
2378
  }
2922
2379
  }
2923
- `}static registerRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2924
- import { registerSchema } from '../schemas/auth.js';
2380
+ `}static registerRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2381
+ import { registerSchema } from './schemas.js';
2382
+
2383
+ export class RegisterRequest extends FormRequest {
2384
+ rules() {
2385
+ return registerSchema;
2386
+ }
2387
+ }
2388
+ `}static loginRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2389
+ import { loginSchema } from './schemas.js';
2390
+
2391
+ export class LoginRequest extends FormRequest {
2392
+ rules() {
2393
+ return loginSchema;
2394
+ }
2395
+ }
2396
+ `}static forgotPasswordRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2397
+ import { forgotPasswordSchema } from './schemas.js';
2398
+
2399
+ export class ForgotPasswordRequest extends FormRequest {
2400
+ rules() {
2401
+ return forgotPasswordSchema;
2402
+ }
2403
+ }
2404
+ `}static resetPasswordRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2405
+ import { resetPasswordSchema } from './schemas.js';
2406
+
2407
+ export class ResetPasswordRequest extends FormRequest {
2408
+ rules() {
2409
+ return resetPasswordSchema;
2410
+ }
2411
+ }
2412
+ `}static otpSendRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2413
+ import { otpRequestSchema } from './schemas.js';
2925
2414
 
2926
- export class RegisterRequest extends FormRequest {
2415
+ export class OtpSendRequest extends FormRequest {
2927
2416
  rules() {
2928
- return registerSchema;
2417
+ return otpRequestSchema;
2929
2418
  }
2930
2419
  }
2931
- `}static loginRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2932
- import { loginSchema } from '../schemas/auth.js';
2420
+ `}static otpVerifyRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2421
+ import { otpVerifySchema } from './schemas.js';
2933
2422
 
2934
- export class LoginRequest extends FormRequest {
2423
+ export class OtpVerifyRequest extends FormRequest {
2935
2424
  rules() {
2936
- return loginSchema;
2425
+ return otpVerifySchema;
2937
2426
  }
2938
2427
  }
2939
2428
  `}static createPostRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2940
- import { createPostSchema } from '../schemas/post.js';
2429
+ import { createPostSchema } from './schemas.js';
2941
2430
 
2942
2431
  export class CreatePostRequest extends FormRequest {
2943
2432
  rules() {
@@ -2959,7 +2448,7 @@ export class CreatePostRequest extends FormRequest {
2959
2448
  }
2960
2449
  }
2961
2450
  `}static updatePostRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
2962
- import { updatePostSchema } from '../schemas/post.js';
2451
+ import { updatePostSchema } from './schemas.js';
2963
2452
 
2964
2453
  export class UpdatePostRequest extends FormRequest {
2965
2454
  rules() {
@@ -2971,8 +2460,8 @@ export class UpdatePostRequest extends FormRequest {
2971
2460
  }
2972
2461
  }
2973
2462
  `}static registerUserAction(){return`import { Action } from '@beeblock/svelar/actions';
2974
- import { AuthService } from '../services/AuthService.js';
2975
- import type { User } from '../models/User.js';
2463
+ import { AuthService } from './AuthService.js';
2464
+ import type { User } from './User.js';
2976
2465
 
2977
2466
  interface RegisterInput {
2978
2467
  name: string;
@@ -2994,8 +2483,8 @@ export class RegisterUserAction extends Action<RegisterInput, ServiceResult<User
2994
2483
  }
2995
2484
  }
2996
2485
  `}static createPostAction(){return`import { Action } from '@beeblock/svelar/actions';
2997
- import { PostService } from '../services/PostService.js';
2998
- import type { Post } from '../models/Post.js';
2486
+ import { PostService } from './PostService.js';
2487
+ import type { Post } from './Post.js';
2999
2488
 
3000
2489
  interface CreatePostInput {
3001
2490
  userId: number;
@@ -3023,31 +2512,33 @@ export class CreatePostAction extends Action<CreatePostInput, Post> {
3023
2512
  }
3024
2513
  }
3025
2514
  `}static userResource(){return`import { Resource } from '@beeblock/svelar/routing';
2515
+ import type { UserResponse } from './schemas.js';
3026
2516
 
3027
2517
  export class UserResource extends Resource {
3028
- toJSON() {
2518
+ toJSON(): UserResponse {
3029
2519
  return {
3030
2520
  id: this.data.id,
3031
2521
  name: this.data.name,
3032
2522
  email: this.data.email,
3033
2523
  role: this.data.role ?? 'user',
3034
- created_at: this.data.created_at,
2524
+ created_at: this.data.created_at ?? null,
3035
2525
  };
3036
2526
  }
3037
2527
  }
3038
2528
  `}static postResource(){return`import { Resource } from '@beeblock/svelar/routing';
2529
+ import type { PostResponse } from './schemas.js';
3039
2530
 
3040
2531
  export class PostResource extends Resource {
3041
- toJSON() {
2532
+ toJSON(): PostResponse {
3042
2533
  return {
3043
2534
  id: this.data.id,
3044
2535
  title: this.data.title,
3045
2536
  slug: this.data.slug,
3046
2537
  body: this.data.body,
3047
- published: this.data.published,
2538
+ published: !!this.data.published,
3048
2539
  user_id: this.data.user_id,
3049
- created_at: this.data.created_at,
3050
- updated_at: this.data.updated_at,
2540
+ created_at: this.data.created_at ?? null,
2541
+ updated_at: this.data.updated_at ?? null,
3051
2542
  };
3052
2543
  }
3053
2544
  }
@@ -3102,8 +2593,40 @@ export const userPermissionSchema = z.object({
3102
2593
  export const exportDataSchema = z.object({
3103
2594
  format: z.enum(['csv', 'json']).default('csv'),
3104
2595
  });
2596
+
2597
+ // \u2500\u2500 Inferred Types \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
2598
+
2599
+ export type UpdateUserRoleInput = z.infer<typeof updateUserRoleSchema>;
2600
+ export type DeleteUserInput = z.infer<typeof deleteUserSchema>;
2601
+ export type CreateRoleInput = z.infer<typeof createRoleSchema>;
2602
+ export type DeleteRoleInput = z.infer<typeof deleteRoleSchema>;
2603
+ export type CreatePermissionInput = z.infer<typeof createPermissionSchema>;
2604
+ export type DeletePermissionInput = z.infer<typeof deletePermissionSchema>;
2605
+ export type RolePermissionInput = z.infer<typeof rolePermissionSchema>;
2606
+ export type UserRoleInput = z.infer<typeof userRoleSchema>;
2607
+ export type UserPermissionInput = z.infer<typeof userPermissionSchema>;
2608
+ export type ExportDataInput = z.infer<typeof exportDataSchema>;
2609
+
2610
+ // \u2500\u2500 Response Schemas \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
2611
+
2612
+ export const roleResponseSchema = z.object({
2613
+ id: z.number(),
2614
+ name: z.string(),
2615
+ guard: z.string(),
2616
+ description: z.string().nullable(),
2617
+ });
2618
+
2619
+ export const permissionResponseSchema = z.object({
2620
+ id: z.number(),
2621
+ name: z.string(),
2622
+ guard: z.string(),
2623
+ description: z.string().nullable(),
2624
+ });
2625
+
2626
+ export type RoleResponse = z.infer<typeof roleResponseSchema>;
2627
+ export type PermissionResponse = z.infer<typeof permissionResponseSchema>;
3105
2628
  `}static updateUserRoleRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3106
- import { updateUserRoleSchema } from '../schemas/admin.js';
2629
+ import { updateUserRoleSchema } from './schemas.js';
3107
2630
 
3108
2631
  export class UpdateUserRoleRequest extends FormRequest {
3109
2632
  rules() {
@@ -3115,7 +2638,7 @@ export class UpdateUserRoleRequest extends FormRequest {
3115
2638
  }
3116
2639
  }
3117
2640
  `}static deleteUserRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3118
- import { deleteUserSchema } from '../schemas/admin.js';
2641
+ import { deleteUserSchema } from './schemas.js';
3119
2642
 
3120
2643
  export class DeleteUserRequest extends FormRequest {
3121
2644
  rules() {
@@ -3127,7 +2650,7 @@ export class DeleteUserRequest extends FormRequest {
3127
2650
  }
3128
2651
  }
3129
2652
  `}static createRoleRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3130
- import { createRoleSchema } from '../schemas/admin.js';
2653
+ import { createRoleSchema } from './schemas.js';
3131
2654
 
3132
2655
  export class CreateRoleRequest extends FormRequest {
3133
2656
  rules() {
@@ -3139,7 +2662,7 @@ export class CreateRoleRequest extends FormRequest {
3139
2662
  }
3140
2663
  }
3141
2664
  `}static deleteRoleRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3142
- import { deleteRoleSchema } from '../schemas/admin.js';
2665
+ import { deleteRoleSchema } from './schemas.js';
3143
2666
 
3144
2667
  export class DeleteRoleRequest extends FormRequest {
3145
2668
  rules() {
@@ -3151,7 +2674,7 @@ export class DeleteRoleRequest extends FormRequest {
3151
2674
  }
3152
2675
  }
3153
2676
  `}static createPermissionRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3154
- import { createPermissionSchema } from '../schemas/admin.js';
2677
+ import { createPermissionSchema } from './schemas.js';
3155
2678
 
3156
2679
  export class CreatePermissionRequest extends FormRequest {
3157
2680
  rules() {
@@ -3163,7 +2686,7 @@ export class CreatePermissionRequest extends FormRequest {
3163
2686
  }
3164
2687
  }
3165
2688
  `}static deletePermissionRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3166
- import { deletePermissionSchema } from '../schemas/admin.js';
2689
+ import { deletePermissionSchema } from './schemas.js';
3167
2690
 
3168
2691
  export class DeletePermissionRequest extends FormRequest {
3169
2692
  rules() {
@@ -3175,7 +2698,7 @@ export class DeletePermissionRequest extends FormRequest {
3175
2698
  }
3176
2699
  }
3177
2700
  `}static rolePermissionRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3178
- import { rolePermissionSchema } from '../schemas/admin.js';
2701
+ import { rolePermissionSchema } from './schemas.js';
3179
2702
 
3180
2703
  export class RolePermissionRequest extends FormRequest {
3181
2704
  rules() {
@@ -3187,7 +2710,7 @@ export class RolePermissionRequest extends FormRequest {
3187
2710
  }
3188
2711
  }
3189
2712
  `}static userRoleRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3190
- import { userRoleSchema } from '../schemas/admin.js';
2713
+ import { userRoleSchema } from './schemas.js';
3191
2714
 
3192
2715
  export class UserRoleRequest extends FormRequest {
3193
2716
  rules() {
@@ -3199,7 +2722,7 @@ export class UserRoleRequest extends FormRequest {
3199
2722
  }
3200
2723
  }
3201
2724
  `}static userPermissionRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3202
- import { userPermissionSchema } from '../schemas/admin.js';
2725
+ import { userPermissionSchema } from './schemas.js';
3203
2726
 
3204
2727
  export class UserPermissionRequest extends FormRequest {
3205
2728
  rules() {
@@ -3211,7 +2734,7 @@ export class UserPermissionRequest extends FormRequest {
3211
2734
  }
3212
2735
  }
3213
2736
  `}static exportDataRequest(){return`import { FormRequest } from '@beeblock/svelar/forms';
3214
- import { exportDataSchema } from '../schemas/admin.js';
2737
+ import { exportDataSchema } from './schemas.js';
3215
2738
 
3216
2739
  export class ExportDataRequest extends FormRequest {
3217
2740
  rules() {
@@ -3223,9 +2746,10 @@ export class ExportDataRequest extends FormRequest {
3223
2746
  }
3224
2747
  }
3225
2748
  `}static roleResource(){return`import { Resource } from '@beeblock/svelar/routing';
2749
+ import type { RoleResponse } from './schemas.js';
3226
2750
 
3227
2751
  export class RoleResource extends Resource {
3228
- toJSON() {
2752
+ toJSON(): RoleResponse {
3229
2753
  return {
3230
2754
  id: this.data.id,
3231
2755
  name: this.data.name,
@@ -3235,9 +2759,10 @@ export class RoleResource extends Resource {
3235
2759
  }
3236
2760
  }
3237
2761
  `}static permissionResource(){return`import { Resource } from '@beeblock/svelar/routing';
2762
+ import type { PermissionResponse } from './schemas.js';
3238
2763
 
3239
2764
  export class PermissionResource extends Resource {
3240
- toJSON() {
2765
+ toJSON(): PermissionResponse {
3241
2766
  return {
3242
2767
  id: this.data.id,
3243
2768
  name: this.data.name,
@@ -3249,10 +2774,10 @@ export class PermissionResource extends Resource {
3249
2774
  `}static adminService(){return`import { Service } from '@beeblock/svelar/services';
3250
2775
  import { Permissions } from '@beeblock/svelar/permissions';
3251
2776
  import { Queue } from '@beeblock/svelar/queue';
3252
- import { UserRepository } from '../repositories/UserRepository.js';
3253
- import { Post } from '../models/Post.js';
3254
- import { User } from '../models/User.js';
3255
- import { ExportDataJob } from '../shared/jobs/ExportDataJob.js';
2777
+ import { UserRepository } from '$lib/modules/auth/UserRepository.js';
2778
+ import { Post } from '$lib/modules/posts/Post.js';
2779
+ import { User } from '$lib/modules/auth/User.js';
2780
+ import { ExportDataJob } from '$lib/shared/jobs/ExportDataJob.js';
3256
2781
 
3257
2782
  const userRepo = new UserRepository();
3258
2783
 
@@ -3382,6 +2907,8 @@ Gate.define('manage-users', (user) => user?.role === 'admin');
3382
2907
  Gate.defineSuperUser((user) => user?.role === 'admin');
3383
2908
  `}static authSchema(){return`import { z } from 'zod';
3384
2909
 
2910
+ // \u2500\u2500 Input Schemas (DTOs + UI validation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2911
+
3385
2912
  export const loginSchema = z.object({
3386
2913
  email: z.string().email('Please enter a valid email address'),
3387
2914
  password: z.string().min(1, 'Password is required'),
@@ -3419,8 +2946,31 @@ export const otpVerifySchema = z.object({
3419
2946
  email: z.string().email(),
3420
2947
  code: z.string().length(6, 'Code must be 6 digits'),
3421
2948
  });
2949
+
2950
+ // \u2500\u2500 Inferred Types \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
2951
+
2952
+ export type LoginInput = z.infer<typeof loginSchema>;
2953
+ export type RegisterInput = z.infer<typeof registerSchema>;
2954
+ export type ForgotPasswordInput = z.infer<typeof forgotPasswordSchema>;
2955
+ export type ResetPasswordInput = z.infer<typeof resetPasswordSchema>;
2956
+ export type OtpRequestInput = z.infer<typeof otpRequestSchema>;
2957
+ export type OtpVerifyInput = z.infer<typeof otpVerifySchema>;
2958
+
2959
+ // \u2500\u2500 Response Schemas (Resources + API contracts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2960
+
2961
+ export const userResponseSchema = z.object({
2962
+ id: z.number(),
2963
+ name: z.string(),
2964
+ email: z.string().email(),
2965
+ role: z.string(),
2966
+ created_at: z.string().nullable(),
2967
+ });
2968
+
2969
+ export type UserResponse = z.infer<typeof userResponseSchema>;
3422
2970
  `}static postSchema(){return`import { z } from 'zod';
3423
2971
 
2972
+ // \u2500\u2500 Input Schemas \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
2973
+
3424
2974
  export const createPostSchema = z.object({
3425
2975
  title: z.string().min(3, 'Title must be at least 3 characters').max(255),
3426
2976
  slug: z.string().regex(/^[a-z0-9-]+$/, 'Slug must be lowercase alphanumeric with dashes').optional(),
@@ -3434,6 +2984,26 @@ export const updatePostSchema = z.object({
3434
2984
  body: z.string().min(10).optional(),
3435
2985
  published: z.boolean().optional(),
3436
2986
  });
2987
+
2988
+ // \u2500\u2500 Inferred Types \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
2989
+
2990
+ export type CreatePostInput = z.infer<typeof createPostSchema>;
2991
+ export type UpdatePostInput = z.infer<typeof updatePostSchema>;
2992
+
2993
+ // \u2500\u2500 Response Schema (Resources + API contracts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2994
+
2995
+ export const postResponseSchema = z.object({
2996
+ id: z.number(),
2997
+ title: z.string(),
2998
+ slug: z.string(),
2999
+ body: z.string(),
3000
+ published: z.boolean(),
3001
+ user_id: z.number(),
3002
+ created_at: z.string().nullable(),
3003
+ updated_at: z.string().nullable(),
3004
+ });
3005
+
3006
+ export type PostResponse = z.infer<typeof postResponseSchema>;
3437
3007
  `}static createUsersTable(){return`import { Migration } from '@beeblock/svelar/database';
3438
3008
 
3439
3009
  export default class CreateUsersTable extends Migration {
@@ -3606,8 +3176,8 @@ export default class CreateFailedJobsTable extends Migration {
3606
3176
  `}static databaseSeeder(){return`import { Seeder } from '@beeblock/svelar/database';
3607
3177
  import { Hash } from '@beeblock/svelar/hashing';
3608
3178
  import { Permissions } from '@beeblock/svelar/permissions';
3609
- import { User } from '../../models/User.js';
3610
- import { Post } from '../../models/Post.js';
3179
+ import { User } from '$lib/modules/auth/User.js';
3180
+ import { Post } from '$lib/modules/posts/Post.js';
3611
3181
 
3612
3182
  export class DatabaseSeeder extends Seeder {
3613
3183
  async run(): Promise<void> {
@@ -3698,8 +3268,8 @@ export class DatabaseSeeder extends Seeder {
3698
3268
  import { fail, redirect } from '@sveltejs/kit';
3699
3269
  import { superValidate, message } from 'sveltekit-superforms';
3700
3270
  import { zod } from 'sveltekit-superforms/adapters';
3701
- import { loginSchema } from '$lib/schemas/auth';
3702
- import { AuthService } from '$lib/services/AuthService';
3271
+ import { loginSchema } from '$lib/modules/auth/schemas';
3272
+ import { AuthService } from '$lib/modules/auth/AuthService';
3703
3273
  import { authConfig } from '../../app.js';
3704
3274
 
3705
3275
  const authService = new AuthService();
@@ -3828,8 +3398,8 @@ export const actions: Actions = {
3828
3398
  import { fail, redirect } from '@sveltejs/kit';
3829
3399
  import { superValidate, message, setError } from 'sveltekit-superforms';
3830
3400
  import { zod } from 'sveltekit-superforms/adapters';
3831
- import { registerSchema } from '$lib/schemas/auth';
3832
- import { AuthService } from '$lib/services/AuthService';
3401
+ import { registerSchema } from '$lib/modules/auth/schemas';
3402
+ import { AuthService } from '$lib/modules/auth/AuthService';
3833
3403
  import { auth, authConfig } from '../../app.js';
3834
3404
 
3835
3405
  const authService = new AuthService();
@@ -3994,7 +3564,7 @@ export const actions: Actions = {
3994
3564
  import { fail } from '@sveltejs/kit';
3995
3565
  import { superValidate, message } from 'sveltekit-superforms';
3996
3566
  import { zod } from 'sveltekit-superforms/adapters';
3997
- import { forgotPasswordSchema } from '$lib/schemas/auth';
3567
+ import { forgotPasswordSchema } from '$lib/modules/auth/schemas';
3998
3568
  import { auth } from '../../app.js';
3999
3569
 
4000
3570
  export const load: PageServerLoad = async () => {
@@ -4082,7 +3652,7 @@ export const actions: Actions = {
4082
3652
  import { fail, redirect } from '@sveltejs/kit';
4083
3653
  import { superValidate, message } from 'sveltekit-superforms';
4084
3654
  import { zod } from 'sveltekit-superforms/adapters';
4085
- import { resetPasswordSchema } from '$lib/schemas/auth';
3655
+ import { resetPasswordSchema } from '$lib/modules/auth/schemas';
4086
3656
  import { auth } from '../../app.js';
4087
3657
 
4088
3658
  export const load: PageServerLoad = async ({ url }) => {
@@ -4188,7 +3758,7 @@ export const actions: Actions = {
4188
3758
  import { fail, redirect } from '@sveltejs/kit';
4189
3759
  import { superValidate, message } from 'sveltekit-superforms';
4190
3760
  import { zod } from 'sveltekit-superforms/adapters';
4191
- import { otpRequestSchema, otpVerifySchema } from '$lib/schemas/auth';
3761
+ import { otpRequestSchema, otpVerifySchema } from '$lib/modules/auth/schemas';
4192
3762
  import { auth, authConfig } from '../../app.js';
4193
3763
 
4194
3764
  export const load: PageServerLoad = async ({ locals }) => {
@@ -4410,6 +3980,66 @@ export const load: PageServerLoad = async ({ url }) => {
4410
3980
  `}static dashboardLayoutServer(){return`import { guardAuth } from '@beeblock/svelar/auth';
4411
3981
 
4412
3982
  export const load = guardAuth();
3983
+ `}static dashboardLayoutSvelte(){return`<script lang="ts">
3984
+ import { page } from '$app/stores';
3985
+ import type { Snippet } from 'svelte';
3986
+ import { Icon } from '@beeblock/svelar/ui';
3987
+ import LayoutDashboard from 'lucide-svelte/icons/layout-dashboard';
3988
+ import KeyRound from 'lucide-svelte/icons/key-round';
3989
+ import Users from 'lucide-svelte/icons/users';
3990
+ import Settings from 'lucide-svelte/icons/settings';
3991
+
3992
+ interface Props {
3993
+ data: any;
3994
+ children: Snippet;
3995
+ }
3996
+
3997
+ let { data, children }: Props = $props();
3998
+
3999
+ const navItems = [
4000
+ { href: '/dashboard', label: 'Overview', exact: true, icon: LayoutDashboard },
4001
+ { href: '/dashboard/api-keys', label: 'API Keys', exact: false, icon: KeyRound },
4002
+ { href: '/dashboard/team', label: 'Team', exact: false, icon: Users },
4003
+ ];
4004
+
4005
+ function isActive(href: string, exact: boolean, pathname: string): boolean {
4006
+ return exact ? pathname === href : pathname.startsWith(href);
4007
+ }
4008
+ </script>
4009
+
4010
+ <div class="flex min-h-[calc(100vh-130px)]">
4011
+ <aside class="w-64 border-r border-gray-200 bg-gray-50 hidden md:block">
4012
+ <nav class="p-4 space-y-1">
4013
+ {#each navItems as item}
4014
+ {@const active = isActive(item.href, item.exact, $page.url.pathname)}
4015
+ <a
4016
+ href={item.href}
4017
+ class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors {active ? 'bg-brand/10 text-brand' : 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'}"
4018
+ >
4019
+ <Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-gray-400'} />
4020
+ {item.label}
4021
+ </a>
4022
+ {/each}
4023
+ </nav>
4024
+
4025
+ {#if data.user?.role === 'admin'}
4026
+ <div class="border-t border-gray-200 mx-4 my-2"></div>
4027
+ <div class="p-4 pt-0">
4028
+ <a
4029
+ href="/admin"
4030
+ class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors"
4031
+ >
4032
+ <Icon icon={Settings} size={20} class="text-gray-400" />
4033
+ Admin Panel
4034
+ </a>
4035
+ </div>
4036
+ {/if}
4037
+ </aside>
4038
+
4039
+ <div class="flex-1 p-6 md:p-8">
4040
+ {@render children()}
4041
+ </div>
4042
+ </div>
4413
4043
  `}static dashboardPageServer(){return`import type { PageServerLoad } from './$types';
4414
4044
  import { ApiKeys } from '@beeblock/svelar/api-keys';
4415
4045
  import { Teams } from '@beeblock/svelar/teams';
@@ -4982,15 +4612,91 @@ export const actions: Actions = {
4982
4612
  `}static adminLayoutServer(){return`import { guardAuth } from '@beeblock/svelar/auth';
4983
4613
 
4984
4614
  export const load = guardAuth('/dashboard', { role: 'admin' });
4615
+ `}static adminLayoutSvelte(){return`<script lang="ts">
4616
+ import { page } from '$app/stores';
4617
+ import type { Snippet } from 'svelte';
4618
+ import { Icon } from '@beeblock/svelar/ui';
4619
+ import LayoutDashboard from 'lucide-svelte/icons/layout-dashboard';
4620
+ import Users from 'lucide-svelte/icons/users';
4621
+ import ShieldCheck from 'lucide-svelte/icons/shield-check';
4622
+ import Lock from 'lucide-svelte/icons/lock';
4623
+ import ListTodo from 'lucide-svelte/icons/list-todo';
4624
+ import Clock from 'lucide-svelte/icons/clock';
4625
+ import FileText from 'lucide-svelte/icons/file-text';
4626
+ import ArrowLeft from 'lucide-svelte/icons/arrow-left';
4627
+
4628
+ interface Props {
4629
+ data: any;
4630
+ children: Snippet;
4631
+ }
4632
+
4633
+ let { data, children }: Props = $props();
4634
+
4635
+ const navItems = [
4636
+ { tab: 'overview', label: 'Overview', icon: LayoutDashboard },
4637
+ { tab: 'users', label: 'Users', icon: Users },
4638
+ { tab: 'roles', label: 'Roles', icon: ShieldCheck },
4639
+ { tab: 'permissions', label: 'Permissions', icon: Lock },
4640
+ { tab: 'queue', label: 'Queue', icon: ListTodo },
4641
+ { tab: 'scheduler', label: 'Scheduler', icon: Clock },
4642
+ { tab: 'logs', label: 'Logs', icon: FileText },
4643
+ ];
4644
+
4645
+ function isActive(tab: string, currentUrl: URL): boolean {
4646
+ const activeTab = currentUrl.searchParams.get('tab') ?? 'overview';
4647
+ return activeTab === tab;
4648
+ }
4649
+ </script>
4650
+
4651
+ <div class="flex min-h-[calc(100vh-130px)]">
4652
+ <aside class="w-64 border-r border-gray-200 bg-gray-50 hidden md:block">
4653
+ <div class="p-4 border-b border-gray-200">
4654
+ <p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Administration</p>
4655
+ </div>
4656
+ <nav class="p-4 space-y-1">
4657
+ {#each navItems as item}
4658
+ {@const active = isActive(item.tab, $page.url)}
4659
+ <a
4660
+ href="/admin?tab={item.tab}"
4661
+ class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors {active ? 'bg-brand/10 text-brand' : 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'}"
4662
+ >
4663
+ <Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-gray-400'} />
4664
+ {item.label}
4665
+ </a>
4666
+ {/each}
4667
+ </nav>
4668
+
4669
+ <div class="border-t border-gray-200 mx-4 my-2"></div>
4670
+ <div class="p-4 pt-0">
4671
+ <a
4672
+ href="/dashboard"
4673
+ class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900 transition-colors"
4674
+ >
4675
+ <Icon icon={ArrowLeft} size={20} class="text-gray-400" />
4676
+ Back to Dashboard
4677
+ </a>
4678
+ </div>
4679
+ </aside>
4680
+
4681
+ <div class="flex-1 p-6 md:p-8">
4682
+ {@render children()}
4683
+ </div>
4684
+ </div>
4985
4685
  `}static adminPageServer(){return`import type { ServerLoadEvent } from '@sveltejs/kit';
4986
- import { User } from '$lib/models/User.js';
4987
- import { Post } from '$lib/models/Post.js';
4686
+ import { User } from '$lib/modules/auth/User.js';
4687
+ import { Post } from '$lib/modules/posts/Post.js';
4688
+ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
4689
+ import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
4690
+ import { LogViewer } from '@beeblock/svelar/logging/LogViewer';
4988
4691
  import { Permissions } from '@beeblock/svelar/permissions';
4989
4692
 
4990
4693
  export async function load(event: ServerLoadEvent) {
4991
4694
  const user = event.locals.user;
4992
4695
 
4696
+ // Fetch all users
4993
4697
  const users = await User.query().get();
4698
+
4699
+ // Fetch stats
4994
4700
  const userCount = users.length;
4995
4701
  const postCount = await Post.count();
4996
4702
 
@@ -4999,15 +4705,66 @@ export async function load(event: ServerLoadEvent) {
4999
4705
  user: users.filter((u: any) => u.role === 'user').length,
5000
4706
  };
5001
4707
 
4708
+ // Queue stats from JobMonitor
4709
+ let queueCounts = { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0, total: 0 };
4710
+ try {
4711
+ queueCounts = await JobMonitor.getCounts('default');
4712
+ } catch { /* sync/memory driver \u2014 no counts available */ }
4713
+
4714
+ // Scheduler tasks from ScheduleMonitor
4715
+ let scheduledTasks: any[] = [];
4716
+ try {
4717
+ scheduledTasks = await ScheduleMonitor.listTasks();
4718
+ } catch { /* scheduler not configured */ }
4719
+
4720
+ // Recent logs from LogViewer
4721
+ let recentLogs: any[] = [];
4722
+ let logStats = { totalEntries: 0, byLevel: {} as Record<string, number>, byChannel: {} };
4723
+ try {
4724
+ recentLogs = LogViewer.query({ limit: 50 });
4725
+ logStats = LogViewer.getStats();
4726
+ } catch { /* no logs yet */ }
4727
+
4728
+ // System health
4729
+ const memUsage = process.memoryUsage();
4730
+ const health = {
4731
+ status: 'ok',
4732
+ uptime: process.uptime(),
4733
+ memoryUsedMB: Math.round(memUsage.heapUsed / 1024 / 1024),
4734
+ memoryTotalMB: Math.round(memUsage.heapTotal / 1024 / 1024),
4735
+ memoryPercent: Math.round((memUsage.heapUsed / memUsage.heapTotal) * 100),
4736
+ };
4737
+
4738
+ // Roles & Permissions
5002
4739
  let roles: any[] = [];
5003
4740
  let permissions: any[] = [];
4741
+ let rolePermissionsMap: Record<number, number[]> = {};
4742
+ let userRolesMap: Record<number, any[]> = {};
4743
+ let userDirectPermsMap: Record<number, any[]> = {};
5004
4744
  try {
5005
4745
  roles = await Permissions.allRoles();
5006
4746
  permissions = await Permissions.allPermissions();
5007
- } catch {}
4747
+
4748
+ // Load permissions for each role
4749
+ for (const role of roles) {
4750
+ const rolePerms = await Permissions.getRolePermissions(role.id);
4751
+ rolePermissionsMap[role.id] = rolePerms.map((p: any) => p.id);
4752
+ }
4753
+
4754
+ // Load roles and direct permissions for each user
4755
+ for (const u of users) {
4756
+ userRolesMap[u.id] = await Permissions.getModelRoles('User', u.id);
4757
+ userDirectPermsMap[u.id] = await Permissions.getModelDirectPermissions('User', u.id);
4758
+ }
4759
+ } catch { /* permissions tables may not exist yet */ }
5008
4760
 
5009
4761
  return {
5010
- user: { id: user.id, name: user.name, email: user.email, role: user.role },
4762
+ user: {
4763
+ id: user.id,
4764
+ name: user.name,
4765
+ email: user.email,
4766
+ role: user.role,
4767
+ },
5011
4768
  users: users.map((u: any) => ({
5012
4769
  id: u.id,
5013
4770
  name: u.name,
@@ -5015,163 +4772,1009 @@ export async function load(event: ServerLoadEvent) {
5015
4772
  role: u.role,
5016
4773
  created_at: u.created_at,
5017
4774
  })),
5018
- stats: { userCount, postCount, roleDistribution },
5019
- roles: roles.map((r: any) => ({ id: r.id, name: r.name, guard: r.guard, description: r.description })),
5020
- permissions: permissions.map((p: any) => ({ id: p.id, name: p.name, guard: p.guard, description: p.description })),
4775
+ stats: {
4776
+ userCount,
4777
+ postCount,
4778
+ roleDistribution,
4779
+ },
4780
+ queueCounts,
4781
+ scheduledTasks: scheduledTasks.map((t: any) => ({
4782
+ name: t.name,
4783
+ expression: t.expression,
4784
+ humanReadable: t.humanReadable,
4785
+ enabled: t.enabled,
4786
+ isRunning: t.isRunning,
4787
+ lastRun: t.lastRun?.toISOString() ?? null,
4788
+ lastStatus: t.lastStatus ?? null,
4789
+ nextRun: t.nextRun?.toISOString() ?? null,
4790
+ })),
4791
+ recentLogs: recentLogs.map((l: any) => ({
4792
+ timestamp: l.timestamp,
4793
+ level: l.level,
4794
+ channel: l.channel,
4795
+ message: l.message,
4796
+ })),
4797
+ logStats,
4798
+ health,
4799
+ roles: roles.map((r: any) => ({
4800
+ id: r.id,
4801
+ name: r.name,
4802
+ guard: r.guard,
4803
+ description: r.description,
4804
+ created_at: r.created_at,
4805
+ })),
4806
+ permissions: permissions.map((p: any) => ({
4807
+ id: p.id,
4808
+ name: p.name,
4809
+ guard: p.guard,
4810
+ description: p.description,
4811
+ created_at: p.created_at,
4812
+ })),
4813
+ rolePermissionsMap,
4814
+ userRolesMap: Object.fromEntries(
4815
+ Object.entries(userRolesMap).map(([uid, roles]) => [
4816
+ uid,
4817
+ roles.map((r: any) => ({ id: r.id, name: r.name })),
4818
+ ]),
4819
+ ),
4820
+ userDirectPermsMap: Object.fromEntries(
4821
+ Object.entries(userDirectPermsMap).map(([uid, perms]) => [
4822
+ uid,
4823
+ perms.map((p: any) => ({ id: p.id, name: p.name })),
4824
+ ]),
4825
+ ),
5021
4826
  };
5022
4827
  }
5023
4828
  `}static adminPageSvelte(){return`<script lang="ts">
5024
- import { Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent } from '@beeblock/svelar/ui';
4829
+ import { page } from '$app/stores';
4830
+ import { Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, Alert, Input, Label } from '@beeblock/svelar/ui';
5025
4831
 
5026
4832
  let { data } = $props();
5027
4833
  let users = $state(data.users);
4834
+ let message = $state('');
4835
+ let messageType = $state<'success' | 'error'>('success');
5028
4836
 
5029
- async function updateRole(userId: number, role: string) {
5030
- const res = await fetch('/api/admin/users', {
5031
- method: 'PUT',
5032
- headers: { 'Content-Type': 'application/json' },
5033
- body: JSON.stringify({ userId, role }),
5034
- });
5035
- if (res.ok) {
5036
- users = users.map((u: any) => u.id === userId ? { ...u, role } : u);
4837
+ // Real data from server
4838
+ let queueCounts = $state(data.queueCounts);
4839
+ let scheduledTasks = $state(data.scheduledTasks);
4840
+ let recentLogs = $state(data.recentLogs);
4841
+ let logStats = $state(data.logStats);
4842
+ let health = $state(data.health);
4843
+
4844
+ // Roles & Permissions
4845
+ let roles = $state(data.roles ?? []);
4846
+ let permissions = $state(data.permissions ?? []);
4847
+ let rolePermissionsMap = $state<Record<number, number[]>>(data.rolePermissionsMap ?? {});
4848
+ let userRolesMap = $state<Record<number, { id: number; name: string }[]>>(data.userRolesMap ?? {});
4849
+ let userDirectPermsMap = $state<Record<number, { id: number; name: string }[]>>(data.userDirectPermsMap ?? {});
4850
+
4851
+ // Form state
4852
+ let newRoleName = $state('');
4853
+ let newRoleDesc = $state('');
4854
+ let newPermName = $state('');
4855
+ let newPermDesc = $state('');
4856
+ let showRoleForm = $state(false);
4857
+ let showPermForm = $state(false);
4858
+
4859
+ let logFilter = $state<'all' | 'info' | 'warn' | 'error'>('all');
4860
+
4861
+ const activeTab = $derived($page.url.searchParams.get('tab') ?? 'overview');
4862
+
4863
+ const filteredLogs = $derived(
4864
+ logFilter === 'all' ? recentLogs : recentLogs.filter((log: any) => log.level === logFilter)
4865
+ );
4866
+
4867
+ function flash(msg: string, type: 'success' | 'error' = 'success') {
4868
+ message = msg;
4869
+ messageType = type;
4870
+ }
4871
+
4872
+ async function refreshDashboard() {
4873
+ try {
4874
+ const res = await fetch('/api/admin/stats');
4875
+ if (res.ok) {
4876
+ const stats = await res.json();
4877
+ if (stats.queue) {
4878
+ queueCounts = stats.queue.queues?.default ?? queueCounts;
4879
+ }
4880
+ }
4881
+ } catch { /* ignore refresh errors */ }
4882
+ }
4883
+
4884
+ async function updateUserRole(userId: number, newRole: string) {
4885
+ try {
4886
+ const res = await fetch('/api/admin/users', {
4887
+ method: 'PUT',
4888
+ headers: { 'Content-Type': 'application/json' },
4889
+ body: JSON.stringify({ userId, role: newRole }),
4890
+ });
4891
+
4892
+ if (res.ok) {
4893
+ flash('User role updated successfully!');
4894
+ await refreshUsers();
4895
+ } else {
4896
+ const error = await res.json();
4897
+ flash(error.message || 'Failed to update user role', 'error');
4898
+ }
4899
+ } catch {
4900
+ flash('Network error', 'error');
5037
4901
  }
5038
4902
  }
5039
4903
 
5040
- async function deleteUser(userId: number) {
5041
- if (!confirm('Are you sure you want to delete this user?')) return;
5042
- const res = await fetch('/api/admin/users', {
5043
- method: 'DELETE',
5044
- headers: { 'Content-Type': 'application/json' },
5045
- body: JSON.stringify({ userId }),
5046
- });
4904
+ async function deleteUser(userId: number, userName: string) {
4905
+ if (!confirm(\`Are you sure you want to delete \${userName}? This cannot be undone.\`)) {
4906
+ return;
4907
+ }
4908
+
4909
+ try {
4910
+ const res = await fetch('/api/admin/users', {
4911
+ method: 'DELETE',
4912
+ headers: { 'Content-Type': 'application/json' },
4913
+ body: JSON.stringify({ userId }),
4914
+ });
4915
+
4916
+ if (res.ok) {
4917
+ flash('User deleted successfully!');
4918
+ await refreshUsers();
4919
+ } else {
4920
+ const error = await res.json();
4921
+ flash(error.message || 'Failed to delete user', 'error');
4922
+ }
4923
+ } catch {
4924
+ flash('Network error', 'error');
4925
+ }
4926
+ }
4927
+
4928
+ async function refreshUsers() {
4929
+ const res = await fetch('/api/admin/users');
5047
4930
  if (res.ok) {
5048
- users = users.filter((u: any) => u.id !== userId);
4931
+ const data = await res.json();
4932
+ users = data;
4933
+ }
4934
+ }
4935
+
4936
+ async function retryJob(jobId: string) {
4937
+ try {
4938
+ const res = await fetch(\`/api/admin/queue/\${jobId}/retry\`, { method: 'POST' });
4939
+ if (res.ok) {
4940
+ flash('Job queued for retry');
4941
+ await refreshQueue();
4942
+ }
4943
+ } catch {
4944
+ flash('Failed to retry job', 'error');
4945
+ }
4946
+ }
4947
+
4948
+ async function refreshQueue() {
4949
+ try {
4950
+ const res = await fetch('/api/admin/queue');
4951
+ if (res.ok) {
4952
+ const data = await res.json();
4953
+ queueCounts = data.counts;
4954
+ }
4955
+ } catch { /* ignore */ }
4956
+ }
4957
+
4958
+ async function runTask(taskName: string) {
4959
+ try {
4960
+ const res = await fetch(\`/api/admin/scheduler/\${taskName}/run\`, { method: 'POST' });
4961
+ if (res.ok) {
4962
+ flash(\`Task '\${taskName}' triggered\`);
4963
+ } else {
4964
+ const err = await res.json();
4965
+ flash(err.error || 'Failed to run task', 'error');
4966
+ }
4967
+ } catch {
4968
+ flash('Failed to run task', 'error');
4969
+ }
4970
+ }
4971
+
4972
+ async function toggleTask(taskName: string, enabled: boolean) {
4973
+ try {
4974
+ const res = await fetch(\`/api/admin/scheduler/\${taskName}/toggle\`, {
4975
+ method: 'POST',
4976
+ headers: { 'Content-Type': 'application/json' },
4977
+ body: JSON.stringify({ enabled }),
4978
+ });
4979
+ if (res.ok) {
4980
+ scheduledTasks = scheduledTasks.map((t: any) =>
4981
+ t.name === taskName ? { ...t, enabled } : t
4982
+ );
4983
+ flash(\`Task '\${taskName}' \${enabled ? 'enabled' : 'disabled'}\`);
4984
+ }
4985
+ } catch {
4986
+ flash('Failed to toggle task', 'error');
4987
+ }
4988
+ }
4989
+
4990
+ // -- Roles CRUD --
4991
+
4992
+ async function createRole() {
4993
+ if (!newRoleName.trim()) return;
4994
+ try {
4995
+ const res = await fetch('/api/admin/roles', {
4996
+ method: 'POST',
4997
+ headers: { 'Content-Type': 'application/json' },
4998
+ body: JSON.stringify({ name: newRoleName.trim(), description: newRoleDesc.trim() || undefined }),
4999
+ });
5000
+ if (res.ok) {
5001
+ const role = await res.json();
5002
+ roles = [...roles, role];
5003
+ rolePermissionsMap[role.id] = [];
5004
+ newRoleName = '';
5005
+ newRoleDesc = '';
5006
+ showRoleForm = false;
5007
+ flash('Role created');
5008
+ } else {
5009
+ const err = await res.json();
5010
+ flash(err.message || 'Failed to create role', 'error');
5011
+ }
5012
+ } catch {
5013
+ flash('Network error', 'error');
5014
+ }
5015
+ }
5016
+
5017
+ async function deleteRole(name: string) {
5018
+ if (!confirm(\`Delete role "\${name}"? This will remove it from all users.\`)) return;
5019
+ try {
5020
+ const res = await fetch('/api/admin/roles', {
5021
+ method: 'DELETE',
5022
+ headers: { 'Content-Type': 'application/json' },
5023
+ body: JSON.stringify({ name }),
5024
+ });
5025
+ if (res.ok) {
5026
+ const deleted = roles.find((r: any) => r.name === name);
5027
+ roles = roles.filter((r: any) => r.name !== name);
5028
+ if (deleted) delete rolePermissionsMap[deleted.id];
5029
+ for (const uid of Object.keys(userRolesMap)) {
5030
+ userRolesMap[uid as any] = userRolesMap[uid as any].filter((r: any) => r.name !== name);
5031
+ }
5032
+ flash('Role deleted');
5033
+ } else {
5034
+ const err = await res.json();
5035
+ flash(err.message || 'Failed to delete role', 'error');
5036
+ }
5037
+ } catch {
5038
+ flash('Network error', 'error');
5039
+ }
5040
+ }
5041
+
5042
+ // -- Permissions CRUD --
5043
+
5044
+ async function createPermission() {
5045
+ if (!newPermName.trim()) return;
5046
+ try {
5047
+ const res = await fetch('/api/admin/permissions', {
5048
+ method: 'POST',
5049
+ headers: { 'Content-Type': 'application/json' },
5050
+ body: JSON.stringify({ name: newPermName.trim(), description: newPermDesc.trim() || undefined }),
5051
+ });
5052
+ if (res.ok) {
5053
+ const perm = await res.json();
5054
+ permissions = [...permissions, perm];
5055
+ newPermName = '';
5056
+ newPermDesc = '';
5057
+ showPermForm = false;
5058
+ flash('Permission created');
5059
+ } else {
5060
+ const err = await res.json();
5061
+ flash(err.message || 'Failed to create permission', 'error');
5062
+ }
5063
+ } catch {
5064
+ flash('Network error', 'error');
5065
+ }
5066
+ }
5067
+
5068
+ async function deletePermission(name: string) {
5069
+ if (!confirm(\`Delete permission "\${name}"? This will revoke it from all roles and users.\`)) return;
5070
+ try {
5071
+ const res = await fetch('/api/admin/permissions', {
5072
+ method: 'DELETE',
5073
+ headers: { 'Content-Type': 'application/json' },
5074
+ body: JSON.stringify({ name }),
5075
+ });
5076
+ if (res.ok) {
5077
+ const deleted = permissions.find((p: any) => p.name === name);
5078
+ permissions = permissions.filter((p: any) => p.name !== name);
5079
+ if (deleted) {
5080
+ for (const rid of Object.keys(rolePermissionsMap)) {
5081
+ rolePermissionsMap[rid as any] = rolePermissionsMap[rid as any].filter((pid: number) => pid !== deleted.id);
5082
+ }
5083
+ }
5084
+ flash('Permission deleted');
5085
+ } else {
5086
+ const err = await res.json();
5087
+ flash(err.message || 'Failed to delete permission', 'error');
5088
+ }
5089
+ } catch {
5090
+ flash('Network error', 'error');
5091
+ }
5092
+ }
5093
+
5094
+ // -- Role <-> Permission --
5095
+
5096
+ async function toggleRolePermission(roleId: number, permissionId: number) {
5097
+ const current = rolePermissionsMap[roleId] ?? [];
5098
+ const has = current.includes(permissionId);
5099
+
5100
+ try {
5101
+ const res = await fetch('/api/admin/role-permissions', {
5102
+ method: has ? 'DELETE' : 'POST',
5103
+ headers: { 'Content-Type': 'application/json' },
5104
+ body: JSON.stringify({ roleId, permissionId }),
5105
+ });
5106
+ if (res.ok) {
5107
+ if (has) {
5108
+ rolePermissionsMap[roleId] = current.filter((id: number) => id !== permissionId);
5109
+ } else {
5110
+ rolePermissionsMap[roleId] = [...current, permissionId];
5111
+ }
5112
+ rolePermissionsMap = { ...rolePermissionsMap };
5113
+ } else {
5114
+ const err = await res.json();
5115
+ flash(err.message || 'Failed to update', 'error');
5116
+ }
5117
+ } catch {
5118
+ flash('Network error', 'error');
5119
+ }
5120
+ }
5121
+
5122
+ // -- User <-> Role --
5123
+
5124
+ async function assignRoleToUser(userId: number, roleId: number) {
5125
+ try {
5126
+ const res = await fetch('/api/admin/user-roles', {
5127
+ method: 'POST',
5128
+ headers: { 'Content-Type': 'application/json' },
5129
+ body: JSON.stringify({ userId, roleId }),
5130
+ });
5131
+ if (res.ok) {
5132
+ const role = roles.find((r: any) => r.id === roleId);
5133
+ if (role) {
5134
+ const current = userRolesMap[userId] ?? [];
5135
+ if (!current.some((r: any) => r.id === roleId)) {
5136
+ userRolesMap[userId] = [...current, { id: role.id, name: role.name }];
5137
+ userRolesMap = { ...userRolesMap };
5138
+ }
5139
+ }
5140
+ flash('Role assigned');
5141
+ } else {
5142
+ const err = await res.json();
5143
+ flash(err.message || 'Failed to assign role', 'error');
5144
+ }
5145
+ } catch {
5146
+ flash('Network error', 'error');
5147
+ }
5148
+ }
5149
+
5150
+ async function removeRoleFromUser(userId: number, roleId: number) {
5151
+ try {
5152
+ const res = await fetch('/api/admin/user-roles', {
5153
+ method: 'DELETE',
5154
+ headers: { 'Content-Type': 'application/json' },
5155
+ body: JSON.stringify({ userId, roleId }),
5156
+ });
5157
+ if (res.ok) {
5158
+ userRolesMap[userId] = (userRolesMap[userId] ?? []).filter((r: any) => r.id !== roleId);
5159
+ userRolesMap = { ...userRolesMap };
5160
+ flash('Role removed');
5161
+ } else {
5162
+ const err = await res.json();
5163
+ flash(err.message || 'Failed to remove role', 'error');
5164
+ }
5165
+ } catch {
5166
+ flash('Network error', 'error');
5167
+ }
5168
+ }
5169
+
5170
+ // -- User <-> Direct Permission --
5171
+
5172
+ async function grantPermToUser(userId: number, permissionId: number) {
5173
+ try {
5174
+ const res = await fetch('/api/admin/user-permissions', {
5175
+ method: 'POST',
5176
+ headers: { 'Content-Type': 'application/json' },
5177
+ body: JSON.stringify({ userId, permissionId }),
5178
+ });
5179
+ if (res.ok) {
5180
+ const perm = permissions.find((p: any) => p.id === permissionId);
5181
+ if (perm) {
5182
+ const current = userDirectPermsMap[userId] ?? [];
5183
+ if (!current.some((p: any) => p.id === permissionId)) {
5184
+ userDirectPermsMap[userId] = [...current, { id: perm.id, name: perm.name }];
5185
+ userDirectPermsMap = { ...userDirectPermsMap };
5186
+ }
5187
+ }
5188
+ flash('Permission granted');
5189
+ } else {
5190
+ const err = await res.json();
5191
+ flash(err.message || 'Failed to grant permission', 'error');
5192
+ }
5193
+ } catch {
5194
+ flash('Network error', 'error');
5195
+ }
5196
+ }
5197
+
5198
+ async function revokePermFromUser(userId: number, permissionId: number) {
5199
+ try {
5200
+ const res = await fetch('/api/admin/user-permissions', {
5201
+ method: 'DELETE',
5202
+ headers: { 'Content-Type': 'application/json' },
5203
+ body: JSON.stringify({ userId, permissionId }),
5204
+ });
5205
+ if (res.ok) {
5206
+ userDirectPermsMap[userId] = (userDirectPermsMap[userId] ?? []).filter((p: any) => p.id !== permissionId);
5207
+ userDirectPermsMap = { ...userDirectPermsMap };
5208
+ flash('Permission revoked');
5209
+ } else {
5210
+ const err = await res.json();
5211
+ flash(err.message || 'Failed to revoke permission', 'error');
5212
+ }
5213
+ } catch {
5214
+ flash('Network error', 'error');
5049
5215
  }
5050
5216
  }
5217
+
5218
+ function formatDate(date: string | null): string {
5219
+ if (!date) return 'Never';
5220
+ try {
5221
+ return new Date(date).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' });
5222
+ } catch {
5223
+ return date;
5224
+ }
5225
+ }
5226
+
5227
+ function formatUptime(seconds: number): string {
5228
+ const h = Math.floor(seconds / 3600);
5229
+ const m = Math.floor((seconds % 3600) / 60);
5230
+ return h > 0 ? \`\${h}h \${m}m\` : \`\${m}m\`;
5231
+ }
5232
+
5233
+ function getLogBadgeVariant(level: string): 'default' | 'secondary' | 'destructive' {
5234
+ return level === 'error' || level === 'fatal' ? 'destructive' : level === 'warn' ? 'secondary' : 'default';
5235
+ }
5051
5236
  </script>
5052
5237
 
5053
5238
  <svelte:head>
5054
- <title>Admin Panel</title>
5239
+ <title>Admin Dashboard</title>
5055
5240
  </svelte:head>
5056
5241
 
5057
5242
  <div class="space-y-8">
5058
- <div>
5059
- <h1 class="text-3xl font-bold text-gray-900 mb-2">Admin Panel</h1>
5060
- <p class="text-gray-600">Manage users, roles, and permissions</p>
5243
+ <div class="flex justify-between items-center">
5244
+ <div>
5245
+ <h1 class="text-3xl font-bold text-gray-900">Admin Dashboard</h1>
5246
+ <p class="text-gray-600 mt-1">System health, queue monitoring, and task management</p>
5247
+ </div>
5248
+ <Button variant="outline" onclick={refreshDashboard}>Refresh</Button>
5061
5249
  </div>
5062
5250
 
5063
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
5064
- <Card>
5065
- <CardContent class="pt-6">
5066
- <p class="text-sm text-gray-600">Total Users</p>
5067
- <p class="text-3xl font-bold text-brand mt-2">{data.stats.userCount}</p>
5068
- <p class="text-xs text-gray-500 mt-1">{data.stats.roleDistribution.admin} admin, {data.stats.roleDistribution.user} user</p>
5069
- </CardContent>
5070
- </Card>
5251
+ {#if message}
5252
+ <Alert variant={messageType === 'error' ? 'destructive' : 'success'}>
5253
+ <span class="text-sm">{message}</span>
5254
+ </Alert>
5255
+ {/if}
5256
+
5257
+ <!-- Overview -->
5258
+ {#if activeTab === 'overview'}
5259
+ <div class="space-y-6">
5260
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
5261
+ <Card>
5262
+ <CardContent class="pt-6">
5263
+ <div>
5264
+ <p class="text-sm text-gray-600">Total Users</p>
5265
+ <p class="text-3xl font-bold text-[var(--color-brand)] mt-2">{data.stats.userCount}</p>
5266
+ </div>
5267
+ </CardContent>
5268
+ </Card>
5269
+
5270
+ <Card>
5271
+ <CardContent class="pt-6">
5272
+ <div>
5273
+ <p class="text-sm text-gray-600">Total Posts</p>
5274
+ <p class="text-3xl font-bold text-[var(--color-brand)] mt-2">{data.stats.postCount}</p>
5275
+ </div>
5276
+ </CardContent>
5277
+ </Card>
5278
+
5279
+ <Card>
5280
+ <CardContent class="pt-6">
5281
+ <div>
5282
+ <p class="text-sm text-gray-600">Queue Pending</p>
5283
+ <p class="text-3xl font-bold text-yellow-600 mt-2">{queueCounts.waiting}</p>
5284
+ </div>
5285
+ </CardContent>
5286
+ </Card>
5287
+
5288
+ <Card>
5289
+ <CardContent class="pt-6">
5290
+ <div>
5291
+ <p class="text-sm text-gray-600">Failed Jobs</p>
5292
+ <p class="text-3xl font-bold text-red-600 mt-2">{queueCounts.failed}</p>
5293
+ </div>
5294
+ </CardContent>
5295
+ </Card>
5296
+ </div>
5297
+
5298
+ <Card>
5299
+ <CardHeader>
5300
+ <CardTitle>System Health</CardTitle>
5301
+ </CardHeader>
5302
+ <CardContent class="space-y-4">
5303
+ <div class="flex justify-between text-sm">
5304
+ <span>Status</span>
5305
+ <Badge variant="default">{health.status}</Badge>
5306
+ </div>
5307
+ <div class="flex justify-between text-sm">
5308
+ <span>Uptime</span>
5309
+ <span class="font-medium">{formatUptime(health.uptime)}</span>
5310
+ </div>
5311
+ <div class="space-y-2">
5312
+ <div class="flex justify-between text-sm">
5313
+ <span>Memory Usage</span>
5314
+ <Badge variant={health.memoryPercent > 90 ? 'destructive' : health.memoryPercent > 70 ? 'secondary' : 'default'}>
5315
+ {health.memoryUsedMB} MB / {health.memoryTotalMB} MB ({health.memoryPercent}%)
5316
+ </Badge>
5317
+ </div>
5318
+ <div class="h-2 bg-gray-200 rounded-full overflow-hidden">
5319
+ <div
5320
+ class="h-full transition-all"
5321
+ class:bg-green-500={health.memoryPercent <= 70}
5322
+ class:bg-yellow-500={health.memoryPercent > 70 && health.memoryPercent <= 90}
5323
+ class:bg-red-500={health.memoryPercent > 90}
5324
+ style="width: {health.memoryPercent}%"
5325
+ ></div>
5326
+ </div>
5327
+ </div>
5328
+ <div class="flex justify-between text-sm">
5329
+ <span>Queue Throughput</span>
5330
+ <span class="font-medium">{queueCounts.total} total jobs</span>
5331
+ </div>
5332
+ <div class="flex justify-between text-sm">
5333
+ <span>Log Entries</span>
5334
+ <span class="font-medium">{logStats.totalEntries} entries ({logStats.byLevel?.error ?? 0} errors)</span>
5335
+ </div>
5336
+ </CardContent>
5337
+ </Card>
5338
+ </div>
5339
+ {/if}
5340
+
5341
+ <!-- Users -->
5342
+ {#if activeTab === 'users'}
5071
5343
  <Card>
5072
- <CardContent class="pt-6">
5073
- <p class="text-sm text-gray-600">Total Posts</p>
5074
- <p class="text-3xl font-bold text-brand mt-2">{data.stats.postCount}</p>
5075
- </CardContent>
5076
- </Card>
5077
- <Card>
5078
- <CardContent class="pt-6">
5079
- <p class="text-sm text-gray-600">Roles</p>
5080
- <p class="text-3xl font-bold text-brand mt-2">{data.roles.length}</p>
5081
- <p class="text-xs text-gray-500 mt-1">{data.permissions.length} permissions</p>
5344
+ <CardHeader>
5345
+ <CardTitle>User Management</CardTitle>
5346
+ <CardDescription>Manage user roles and permissions ({data.stats.userCount} users)</CardDescription>
5347
+ </CardHeader>
5348
+ <CardContent>
5349
+ <div class="overflow-x-auto">
5350
+ <table class="w-full text-sm">
5351
+ <thead>
5352
+ <tr class="border-b border-gray-200">
5353
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Name</th>
5354
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Email</th>
5355
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Column Role</th>
5356
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Assigned Roles</th>
5357
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Direct Permissions</th>
5358
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Actions</th>
5359
+ </tr>
5360
+ </thead>
5361
+ <tbody>
5362
+ {#each users as user (user.id)}
5363
+ <tr class="border-b border-gray-100 hover:bg-gray-50">
5364
+ <td class="py-3 px-4 font-medium text-gray-900">{user.name}</td>
5365
+ <td class="py-3 px-4 text-gray-600">{user.email}</td>
5366
+ <td class="py-3 px-4">
5367
+ <Badge variant={user.role === 'admin' ? 'default' : 'secondary'}>
5368
+ {user.role}
5369
+ </Badge>
5370
+ </td>
5371
+ <td class="py-3 px-4">
5372
+ <div class="flex flex-wrap gap-1">
5373
+ {#each (userRolesMap[user.id] ?? []) as role (role.id)}
5374
+ <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs bg-blue-100 text-blue-800">
5375
+ {role.name}
5376
+ <button
5377
+ type="button"
5378
+ class="hover:text-red-600 font-bold"
5379
+ onclick={() => removeRoleFromUser(user.id, role.id)}
5380
+ >&times;</button>
5381
+ </span>
5382
+ {/each}
5383
+ {#if roles.length > 0}
5384
+ <select
5385
+ class="text-xs border border-gray-200 rounded px-1 py-0.5"
5386
+ onchange={(e) => {
5387
+ const val = Number((e.target as HTMLSelectElement).value);
5388
+ if (val) { assignRoleToUser(user.id, val); (e.target as HTMLSelectElement).value = ''; }
5389
+ }}
5390
+ >
5391
+ <option value="">+ role</option>
5392
+ {#each roles.filter((r) => !(userRolesMap[user.id] ?? []).some((ur) => ur.id === r.id)) as role (role.id)}
5393
+ <option value={role.id}>{role.name}</option>
5394
+ {/each}
5395
+ </select>
5396
+ {/if}
5397
+ </div>
5398
+ </td>
5399
+ <td class="py-3 px-4">
5400
+ <div class="flex flex-wrap gap-1">
5401
+ {#each (userDirectPermsMap[user.id] ?? []) as perm (perm.id)}
5402
+ <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs bg-purple-100 text-purple-800">
5403
+ {perm.name}
5404
+ <button
5405
+ type="button"
5406
+ class="hover:text-red-600 font-bold"
5407
+ onclick={() => revokePermFromUser(user.id, perm.id)}
5408
+ >&times;</button>
5409
+ </span>
5410
+ {/each}
5411
+ {#if permissions.length > 0}
5412
+ <select
5413
+ class="text-xs border border-gray-200 rounded px-1 py-0.5"
5414
+ onchange={(e) => {
5415
+ const val = Number((e.target as HTMLSelectElement).value);
5416
+ if (val) { grantPermToUser(user.id, val); (e.target as HTMLSelectElement).value = ''; }
5417
+ }}
5418
+ >
5419
+ <option value="">+ perm</option>
5420
+ {#each permissions.filter((p) => !(userDirectPermsMap[user.id] ?? []).some((up) => up.id === p.id)) as perm (perm.id)}
5421
+ <option value={perm.id}>{perm.name}</option>
5422
+ {/each}
5423
+ </select>
5424
+ {/if}
5425
+ </div>
5426
+ </td>
5427
+ <td class="py-3 px-4">
5428
+ <div class="flex gap-2">
5429
+ {#if user.role === 'user'}
5430
+ <Button size="sm" variant="outline" onclick={() => updateUserRole(user.id, 'admin')}>
5431
+ Make Admin
5432
+ </Button>
5433
+ {:else if data.stats.roleDistribution.admin > 1}
5434
+ <Button size="sm" variant="outline" onclick={() => updateUserRole(user.id, 'user')}>
5435
+ Demote
5436
+ </Button>
5437
+ {/if}
5438
+ {#if user.id !== data.user.id}
5439
+ <Button size="sm" variant="destructive" onclick={() => deleteUser(user.id, user.name)}>
5440
+ Delete
5441
+ </Button>
5442
+ {/if}
5443
+ </div>
5444
+ </td>
5445
+ </tr>
5446
+ {/each}
5447
+ </tbody>
5448
+ </table>
5449
+ </div>
5082
5450
  </CardContent>
5083
5451
  </Card>
5084
- </div>
5452
+ {/if}
5085
5453
 
5086
- <Card>
5087
- <CardHeader>
5088
- <CardTitle>Users</CardTitle>
5089
- <CardDescription>{users.length} registered users</CardDescription>
5090
- </CardHeader>
5091
- <CardContent>
5092
- <div class="overflow-x-auto">
5093
- <table class="w-full text-sm">
5094
- <thead>
5095
- <tr class="border-b border-gray-200">
5096
- <th class="text-left py-3 px-2 font-medium text-gray-600">ID</th>
5097
- <th class="text-left py-3 px-2 font-medium text-gray-600">Name</th>
5098
- <th class="text-left py-3 px-2 font-medium text-gray-600">Email</th>
5099
- <th class="text-left py-3 px-2 font-medium text-gray-600">Role</th>
5100
- <th class="text-right py-3 px-2 font-medium text-gray-600">Actions</th>
5101
- </tr>
5102
- </thead>
5103
- <tbody>
5104
- {#each users as u (u.id)}
5105
- <tr class="border-b border-gray-100 hover:bg-gray-50">
5106
- <td class="py-3 px-2">{u.id}</td>
5107
- <td class="py-3 px-2 font-medium">{u.name}</td>
5108
- <td class="py-3 px-2 text-gray-600">{u.email}</td>
5109
- <td class="py-3 px-2">
5110
- <select
5111
- class="px-2 py-1 border border-gray-300 rounded text-sm"
5112
- value={u.role}
5113
- onchange={(e) => updateRole(u.id, e.currentTarget.value)}
5114
- >
5115
- <option value="user">User</option>
5116
- <option value="admin">Admin</option>
5117
- </select>
5118
- </td>
5119
- <td class="py-3 px-2 text-right">
5120
- {#if u.id !== data.user.id}
5121
- <Button size="sm" variant="destructive" onclick={() => deleteUser(u.id)}>Delete</Button>
5122
- {/if}
5123
- </td>
5124
- </tr>
5125
- {/each}
5126
- </tbody>
5127
- </table>
5454
+ <!-- Roles -->
5455
+ {#if activeTab === 'roles'}
5456
+ <div class="space-y-6">
5457
+ <Card>
5458
+ <CardHeader>
5459
+ <div class="flex justify-between items-start">
5460
+ <div>
5461
+ <CardTitle>Roles</CardTitle>
5462
+ <CardDescription>{roles.length} roles defined</CardDescription>
5463
+ </div>
5464
+ <Button size="sm" onclick={() => (showRoleForm = !showRoleForm)}>
5465
+ {showRoleForm ? 'Cancel' : 'Create Role'}
5466
+ </Button>
5467
+ </div>
5468
+ </CardHeader>
5469
+ {#if showRoleForm}
5470
+ <CardContent>
5471
+ <form
5472
+ class="flex flex-wrap gap-3 items-end border-b border-gray-100 pb-4 mb-4"
5473
+ onsubmit={(e) => { e.preventDefault(); createRole(); }}
5474
+ >
5475
+ <div class="flex-1 min-w-[200px]">
5476
+ <Label for="role-name">Name</Label>
5477
+ <Input id="role-name" bind:value={newRoleName} placeholder="e.g. editor" />
5478
+ </div>
5479
+ <div class="flex-1 min-w-[200px]">
5480
+ <Label for="role-desc">Description (optional)</Label>
5481
+ <Input id="role-desc" bind:value={newRoleDesc} placeholder="Can edit content" />
5482
+ </div>
5483
+ <Button type="submit" size="sm">Create</Button>
5484
+ </form>
5485
+ </CardContent>
5486
+ {/if}
5487
+ <CardContent>
5488
+ {#if roles.length > 0}
5489
+ <div class="space-y-4">
5490
+ {#each roles as role (role.id)}
5491
+ <div class="border border-gray-200 rounded-lg p-4">
5492
+ <div class="flex items-center justify-between mb-3">
5493
+ <div>
5494
+ <span class="font-medium text-gray-900">{role.name}</span>
5495
+ <Badge variant="secondary" class="ml-2">{role.guard}</Badge>
5496
+ {#if role.description}
5497
+ <p class="text-xs text-gray-500 mt-1">{role.description}</p>
5498
+ {/if}
5499
+ </div>
5500
+ <Button size="sm" variant="destructive" onclick={() => deleteRole(role.name)}>Delete</Button>
5501
+ </div>
5502
+ <div>
5503
+ <p class="text-xs font-semibold text-gray-500 uppercase mb-2">Permissions</p>
5504
+ <div class="flex flex-wrap gap-2">
5505
+ {#each permissions as perm (perm.id)}
5506
+ {@const has = (rolePermissionsMap[role.id] ?? []).includes(perm.id)}
5507
+ <button
5508
+ type="button"
5509
+ class="px-2 py-1 rounded text-xs border transition-colors {has
5510
+ ? 'bg-[var(--color-brand)] text-white border-[var(--color-brand)]'
5511
+ : 'bg-white text-gray-600 border-gray-200 hover:border-gray-400'}"
5512
+ onclick={() => toggleRolePermission(role.id, perm.id)}
5513
+ >
5514
+ {perm.name}
5515
+ </button>
5516
+ {/each}
5517
+ {#if permissions.length === 0}
5518
+ <span class="text-xs text-gray-400">No permissions defined yet</span>
5519
+ {/if}
5520
+ </div>
5521
+ </div>
5522
+ </div>
5523
+ {/each}
5524
+ </div>
5525
+ {:else}
5526
+ <p class="text-sm text-gray-500 py-4 text-center">
5527
+ No roles defined. Create one to start assigning permissions.
5528
+ </p>
5529
+ {/if}
5530
+ </CardContent>
5531
+ </Card>
5532
+ </div>
5533
+ {/if}
5534
+
5535
+ <!-- Permissions -->
5536
+ {#if activeTab === 'permissions'}
5537
+ <div class="space-y-6">
5538
+ <Card>
5539
+ <CardHeader>
5540
+ <div class="flex justify-between items-start">
5541
+ <div>
5542
+ <CardTitle>Permissions</CardTitle>
5543
+ <CardDescription>{permissions.length} permissions defined</CardDescription>
5544
+ </div>
5545
+ <Button size="sm" onclick={() => (showPermForm = !showPermForm)}>
5546
+ {showPermForm ? 'Cancel' : 'Create Permission'}
5547
+ </Button>
5548
+ </div>
5549
+ </CardHeader>
5550
+ {#if showPermForm}
5551
+ <CardContent>
5552
+ <form
5553
+ class="flex flex-wrap gap-3 items-end border-b border-gray-100 pb-4 mb-4"
5554
+ onsubmit={(e) => { e.preventDefault(); createPermission(); }}
5555
+ >
5556
+ <div class="flex-1 min-w-[200px]">
5557
+ <Label for="perm-name">Name</Label>
5558
+ <Input id="perm-name" bind:value={newPermName} placeholder="e.g. manage-users" />
5559
+ </div>
5560
+ <div class="flex-1 min-w-[200px]">
5561
+ <Label for="perm-desc">Description (optional)</Label>
5562
+ <Input id="perm-desc" bind:value={newPermDesc} placeholder="Can manage user accounts" />
5563
+ </div>
5564
+ <Button type="submit" size="sm">Create</Button>
5565
+ </form>
5566
+ </CardContent>
5567
+ {/if}
5568
+ <CardContent>
5569
+ {#if permissions.length > 0}
5570
+ <div class="overflow-x-auto">
5571
+ <table class="w-full text-sm">
5572
+ <thead>
5573
+ <tr class="border-b border-gray-200">
5574
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Name</th>
5575
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Guard</th>
5576
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Description</th>
5577
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Used by Roles</th>
5578
+ <th class="text-left py-3 px-4 font-semibold text-gray-900">Actions</th>
5579
+ </tr>
5580
+ </thead>
5581
+ <tbody>
5582
+ {#each permissions as perm (perm.id)}
5583
+ {@const usedBy = roles.filter((r) => (rolePermissionsMap[r.id] ?? []).includes(perm.id))}
5584
+ <tr class="border-b border-gray-100 hover:bg-gray-50">
5585
+ <td class="py-3 px-4 font-medium text-gray-900">{perm.name}</td>
5586
+ <td class="py-3 px-4">
5587
+ <Badge variant="secondary">{perm.guard}</Badge>
5588
+ </td>
5589
+ <td class="py-3 px-4 text-gray-600">{perm.description || '---'}</td>
5590
+ <td class="py-3 px-4">
5591
+ <div class="flex flex-wrap gap-1">
5592
+ {#each usedBy as role (role.id)}
5593
+ <Badge variant="outline">{role.name}</Badge>
5594
+ {/each}
5595
+ {#if usedBy.length === 0}
5596
+ <span class="text-xs text-gray-400">None</span>
5597
+ {/if}
5598
+ </div>
5599
+ </td>
5600
+ <td class="py-3 px-4">
5601
+ <Button size="sm" variant="destructive" onclick={() => deletePermission(perm.name)}>Delete</Button>
5602
+ </td>
5603
+ </tr>
5604
+ {/each}
5605
+ </tbody>
5606
+ </table>
5607
+ </div>
5608
+ {:else}
5609
+ <p class="text-sm text-gray-500 py-4 text-center">
5610
+ No permissions defined. Create one to start building your authorization system.
5611
+ </p>
5612
+ {/if}
5613
+ </CardContent>
5614
+ </Card>
5615
+ </div>
5616
+ {/if}
5617
+
5618
+ <!-- Queue -->
5619
+ {#if activeTab === 'queue'}
5620
+ <div class="space-y-6">
5621
+ <div class="grid grid-cols-1 md:grid-cols-5 gap-4">
5622
+ <Card>
5623
+ <CardContent class="pt-6">
5624
+ <div>
5625
+ <p class="text-sm text-gray-600">Waiting</p>
5626
+ <p class="text-3xl font-bold text-yellow-600 mt-2">{queueCounts.waiting}</p>
5627
+ </div>
5628
+ </CardContent>
5629
+ </Card>
5630
+ <Card>
5631
+ <CardContent class="pt-6">
5632
+ <div>
5633
+ <p class="text-sm text-gray-600">Active</p>
5634
+ <p class="text-3xl font-bold text-blue-600 mt-2">{queueCounts.active}</p>
5635
+ </div>
5636
+ </CardContent>
5637
+ </Card>
5638
+ <Card>
5639
+ <CardContent class="pt-6">
5640
+ <div>
5641
+ <p class="text-sm text-gray-600">Failed</p>
5642
+ <p class="text-3xl font-bold text-red-600 mt-2">{queueCounts.failed}</p>
5643
+ </div>
5644
+ </CardContent>
5645
+ </Card>
5646
+ <Card>
5647
+ <CardContent class="pt-6">
5648
+ <div>
5649
+ <p class="text-sm text-gray-600">Completed</p>
5650
+ <p class="text-3xl font-bold text-green-600 mt-2">{queueCounts.completed}</p>
5651
+ </div>
5652
+ </CardContent>
5653
+ </Card>
5654
+ <Card>
5655
+ <CardContent class="pt-6">
5656
+ <div>
5657
+ <p class="text-sm text-gray-600">Delayed</p>
5658
+ <p class="text-3xl font-bold text-gray-600 mt-2">{queueCounts.delayed}</p>
5659
+ </div>
5660
+ </CardContent>
5661
+ </Card>
5128
5662
  </div>
5129
- </CardContent>
5130
- </Card>
5663
+ <Card>
5664
+ <CardHeader>
5665
+ <CardTitle>Queue Actions</CardTitle>
5666
+ <CardDescription>Manage job queue</CardDescription>
5667
+ </CardHeader>
5668
+ <CardContent class="flex gap-3">
5669
+ <Button variant="outline" onclick={refreshQueue}>Refresh Counts</Button>
5670
+ </CardContent>
5671
+ </Card>
5672
+ </div>
5673
+ {/if}
5131
5674
 
5132
- {#if data.roles.length > 0}
5675
+ <!-- Scheduler -->
5676
+ {#if activeTab === 'scheduler'}
5133
5677
  <Card>
5134
5678
  <CardHeader>
5135
- <CardTitle>Roles</CardTitle>
5679
+ <CardTitle>Scheduled Tasks</CardTitle>
5680
+ <CardDescription>
5681
+ {scheduledTasks.length > 0
5682
+ ? \`\${scheduledTasks.length} registered tasks\`
5683
+ : 'No tasks registered. Configure your scheduler to see tasks here.'}
5684
+ </CardDescription>
5136
5685
  </CardHeader>
5137
5686
  <CardContent>
5138
- <div class="flex flex-wrap gap-2">
5139
- {#each data.roles as role}
5140
- <div class="flex items-center gap-2 p-3 border border-gray-200 rounded-lg">
5141
- <Badge variant="default">{role.name}</Badge>
5142
- {#if role.description}
5143
- <span class="text-sm text-gray-600">{role.description}</span>
5144
- {/if}
5145
- </div>
5146
- {/each}
5147
- </div>
5687
+ {#if scheduledTasks.length > 0}
5688
+ <div class="space-y-3">
5689
+ {#each scheduledTasks as task (task.name)}
5690
+ <div class="flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:bg-gray-50">
5691
+ <div class="flex-1">
5692
+ <p class="font-medium text-gray-900">{task.name}</p>
5693
+ <p class="text-sm text-gray-600">Schedule: {task.humanReadable}</p>
5694
+ <p class="text-xs text-gray-500 mt-1">Last run: {formatDate(task.lastRun)}</p>
5695
+ <p class="text-xs text-gray-500">Next run: {formatDate(task.nextRun)}</p>
5696
+ </div>
5697
+ <div class="flex items-center gap-3">
5698
+ {#if task.lastStatus}
5699
+ <Badge variant={task.lastStatus === 'success' ? 'default' : 'destructive'}>
5700
+ {task.lastStatus}
5701
+ </Badge>
5702
+ {/if}
5703
+ <Badge variant={task.enabled ? 'default' : 'secondary'}>
5704
+ {task.enabled ? 'enabled' : 'disabled'}
5705
+ </Badge>
5706
+ <Button size="sm" variant="outline" onclick={() => runTask(task.name)}>Run Now</Button>
5707
+ <Button size="sm" variant="outline" onclick={() => toggleTask(task.name, !task.enabled)}>
5708
+ {task.enabled ? 'Disable' : 'Enable'}
5709
+ </Button>
5710
+ </div>
5711
+ </div>
5712
+ {/each}
5713
+ </div>
5714
+ {:else}
5715
+ <p class="text-sm text-gray-500 py-4 text-center">
5716
+ No scheduled tasks found. Configure the Scheduler in your app.ts to register tasks.
5717
+ </p>
5718
+ {/if}
5148
5719
  </CardContent>
5149
5720
  </Card>
5150
5721
  {/if}
5151
5722
 
5152
- {#if data.permissions.length > 0}
5723
+ <!-- Logs -->
5724
+ {#if activeTab === 'logs'}
5153
5725
  <Card>
5154
5726
  <CardHeader>
5155
- <CardTitle>Permissions</CardTitle>
5727
+ <CardTitle>Application Logs</CardTitle>
5728
+ <CardDescription>
5729
+ {logStats.totalEntries} total entries
5730
+ {#if logStats.byLevel?.error}
5731
+ ({logStats.byLevel.error} errors)
5732
+ {/if}
5733
+ </CardDescription>
5156
5734
  </CardHeader>
5157
5735
  <CardContent>
5158
- <div class="flex flex-wrap gap-2">
5159
- {#each data.permissions as perm}
5160
- <Badge variant="secondary">{perm.name}</Badge>
5161
- {/each}
5736
+ <div class="flex gap-2 mb-4">
5737
+ <Button size="sm" variant={logFilter === 'all' ? 'default' : 'outline'} onclick={() => (logFilter = 'all')}>
5738
+ All ({logStats.totalEntries})
5739
+ </Button>
5740
+ <Button size="sm" variant={logFilter === 'info' ? 'default' : 'outline'} onclick={() => (logFilter = 'info')}>
5741
+ Info ({logStats.byLevel?.info ?? 0})
5742
+ </Button>
5743
+ <Button size="sm" variant={logFilter === 'warn' ? 'default' : 'outline'} onclick={() => (logFilter = 'warn')}>
5744
+ Warning ({logStats.byLevel?.warn ?? 0})
5745
+ </Button>
5746
+ <Button size="sm" variant={logFilter === 'error' ? 'default' : 'outline'} onclick={() => (logFilter = 'error')}>
5747
+ Error ({logStats.byLevel?.error ?? 0})
5748
+ </Button>
5162
5749
  </div>
5750
+
5751
+ {#if filteredLogs.length > 0}
5752
+ <div class="space-y-2 max-h-96 overflow-y-auto">
5753
+ {#each filteredLogs as log, i (i)}
5754
+ <div class="flex items-start gap-3 p-3 border border-gray-200 rounded bg-gray-50 text-sm">
5755
+ <Badge variant={getLogBadgeVariant(log.level)} class="mt-0.5">
5756
+ {log.level.toUpperCase()}
5757
+ </Badge>
5758
+ <div class="flex-1">
5759
+ <p class="text-gray-900">{log.message}</p>
5760
+ <p class="text-xs text-gray-500 mt-1">
5761
+ {formatDate(log.timestamp)}
5762
+ {#if log.channel && log.channel !== 'default'}
5763
+ <span class="ml-2 text-gray-400">[{log.channel}]</span>
5764
+ {/if}
5765
+ </p>
5766
+ </div>
5767
+ </div>
5768
+ {/each}
5769
+ </div>
5770
+ {:else}
5771
+ <p class="text-sm text-gray-500 py-4 text-center">
5772
+ No log entries found. Logs appear here as your application runs.
5773
+ </p>
5774
+ {/if}
5163
5775
  </CardContent>
5164
5776
  </Card>
5165
5777
  {/if}
5166
-
5167
- <Card>
5168
- <CardContent class="pt-6">
5169
- <p class="text-sm text-gray-600">
5170
- Need full monitoring with queue, scheduler, and log views?
5171
- Run <code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm">npx svelar make:dashboard</code> to generate the complete admin dashboard.
5172
- </p>
5173
- </CardContent>
5174
- </Card>
5175
5778
  </div>
5176
5779
  `}static apiHealth(){return`import type { RequestHandler } from '@sveltejs/kit';
5177
5780
  import { json } from '@sveltejs/kit';
@@ -5184,7 +5787,7 @@ export const GET: RequestHandler = async () => {
5184
5787
  });
5185
5788
  };
5186
5789
  `}static apiAuthRegister(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5187
- import { AuthController } from '$lib/controllers/AuthController.js';
5790
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5188
5791
 
5189
5792
  const throttle = new ThrottleMiddleware({ maxAttempts: 5, decayMinutes: 2 });
5190
5793
  const ctrl = new AuthController();
@@ -5195,7 +5798,7 @@ export async function POST(event: any) {
5195
5798
  return ctrl.handle('register')(event);
5196
5799
  }
5197
5800
  `}static apiAuthLogin(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5198
- import { AuthController } from '$lib/controllers/AuthController.js';
5801
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5199
5802
 
5200
5803
  const throttle = new ThrottleMiddleware({ maxAttempts: 5, decayMinutes: 1 });
5201
5804
  const ctrl = new AuthController();
@@ -5205,16 +5808,16 @@ export async function POST(event: any) {
5205
5808
  if (blocked) return blocked;
5206
5809
  return ctrl.handle('login')(event);
5207
5810
  }
5208
- `}static apiAuthLogout(){return`import { AuthController } from '$lib/controllers/AuthController.js';
5811
+ `}static apiAuthLogout(){return`import { AuthController } from '$lib/modules/auth/AuthController.js';
5209
5812
 
5210
5813
  const ctrl = new AuthController();
5211
5814
  export const POST = ctrl.handle('logout');
5212
- `}static apiAuthMe(){return`import { AuthController } from '$lib/controllers/AuthController.js';
5815
+ `}static apiAuthMe(){return`import { AuthController } from '$lib/modules/auth/AuthController.js';
5213
5816
 
5214
5817
  const ctrl = new AuthController();
5215
5818
  export const GET = ctrl.handle('me');
5216
5819
  `}static apiAuthForgotPassword(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5217
- import { AuthController } from '$lib/controllers/AuthController.js';
5820
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5218
5821
 
5219
5822
  const throttle = new ThrottleMiddleware({ maxAttempts: 3, decayMinutes: 5 });
5220
5823
  const ctrl = new AuthController();
@@ -5225,7 +5828,7 @@ export async function POST(event: any) {
5225
5828
  return ctrl.handle('forgotPassword')(event);
5226
5829
  }
5227
5830
  `}static apiAuthResetPassword(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5228
- import { AuthController } from '$lib/controllers/AuthController.js';
5831
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5229
5832
 
5230
5833
  const throttle = new ThrottleMiddleware({ maxAttempts: 5, decayMinutes: 5 });
5231
5834
  const ctrl = new AuthController();
@@ -5236,7 +5839,7 @@ export async function POST(event: any) {
5236
5839
  return ctrl.handle('resetPassword')(event);
5237
5840
  }
5238
5841
  `}static apiAuthOtpSend(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5239
- import { AuthController } from '$lib/controllers/AuthController.js';
5842
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5240
5843
 
5241
5844
  const throttle = new ThrottleMiddleware({ maxAttempts: 3, decayMinutes: 2 });
5242
5845
  const ctrl = new AuthController();
@@ -5247,7 +5850,7 @@ export async function POST(event: any) {
5247
5850
  return ctrl.handle('sendOtp')(event);
5248
5851
  }
5249
5852
  `}static apiAuthOtpVerify(){return`import { ThrottleMiddleware } from '@beeblock/svelar/middleware';
5250
- import { AuthController } from '$lib/controllers/AuthController.js';
5853
+ import { AuthController } from '$lib/modules/auth/AuthController.js';
5251
5854
 
5252
5855
  const throttle = new ThrottleMiddleware({ maxAttempts: 5, decayMinutes: 5 });
5253
5856
  const ctrl = new AuthController();
@@ -5257,22 +5860,22 @@ export async function POST(event: any) {
5257
5860
  if (blocked) return blocked;
5258
5861
  return ctrl.handle('verifyOtp')(event);
5259
5862
  }
5260
- `}static apiAuthVerifyEmail(){return`import { AuthController } from '$lib/controllers/AuthController.js';
5863
+ `}static apiAuthVerifyEmail(){return`import { AuthController } from '$lib/modules/auth/AuthController.js';
5261
5864
 
5262
5865
  const ctrl = new AuthController();
5263
5866
  export const GET = ctrl.handle('verifyEmail');
5264
- `}static apiPosts(){return`import { PostController } from '$lib/controllers/PostController.js';
5867
+ `}static apiPosts(){return`import { PostController } from '$lib/modules/posts/PostController.js';
5265
5868
 
5266
5869
  const ctrl = new PostController();
5267
5870
  export const GET = ctrl.handle('index');
5268
5871
  export const POST = ctrl.handle('store');
5269
- `}static apiPostsSingle(){return`import { PostController } from '$lib/controllers/PostController.js';
5872
+ `}static apiPostsSingle(){return`import { PostController } from '$lib/modules/posts/PostController.js';
5270
5873
 
5271
5874
  const ctrl = new PostController();
5272
5875
  export const GET = ctrl.handle('show');
5273
5876
  export const PUT = ctrl.handle('update');
5274
5877
  export const DELETE = ctrl.handle('destroy');
5275
- `}static apiPostsMine(){return`import { PostController } from '$lib/controllers/PostController.js';
5878
+ `}static apiPostsMine(){return`import { PostController } from '$lib/modules/posts/PostController.js';
5276
5879
 
5277
5880
  const ctrl = new PostController();
5278
5881
  export const GET = ctrl.handle('mine');
@@ -5333,41 +5936,203 @@ export const POST: RequestHandler = async (event) => {
5333
5936
  return json({ message: err.message || 'Failed to broadcast' }, { status: 500 });
5334
5937
  }
5335
5938
  };
5336
- `}static apiAdminUsers(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5939
+ `}static apiAdminUsers(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5337
5940
 
5338
5941
  const ctrl = new AdminController();
5339
5942
  export const GET = ctrl.handle('listUsers');
5340
5943
  export const PUT = ctrl.handle('updateUserRole');
5341
5944
  export const DELETE = ctrl.handle('deleteUser');
5342
- `}static apiAdminRoles(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5945
+ `}static apiAdminRoles(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5343
5946
 
5344
5947
  const ctrl = new AdminController();
5345
5948
  export const POST = ctrl.handle('createRole');
5346
5949
  export const DELETE = ctrl.handle('deleteRole');
5347
- `}static apiAdminPermissions(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5950
+ `}static apiAdminPermissions(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5348
5951
 
5349
5952
  const ctrl = new AdminController();
5350
5953
  export const POST = ctrl.handle('createPermission');
5351
5954
  export const DELETE = ctrl.handle('deletePermission');
5352
- `}static apiAdminRolePermissions(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5955
+ `}static apiAdminRolePermissions(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5353
5956
 
5354
5957
  const ctrl = new AdminController();
5355
5958
  export const POST = ctrl.handle('attachRolePermission');
5356
5959
  export const DELETE = ctrl.handle('detachRolePermission');
5357
- `}static apiAdminUserRoles(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5960
+ `}static apiAdminUserRoles(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5358
5961
 
5359
5962
  const ctrl = new AdminController();
5360
5963
  export const POST = ctrl.handle('assignUserRole');
5361
5964
  export const DELETE = ctrl.handle('removeUserRole');
5362
- `}static apiAdminUserPermissions(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5965
+ `}static apiAdminUserPermissions(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5363
5966
 
5364
5967
  const ctrl = new AdminController();
5365
5968
  export const POST = ctrl.handle('grantUserPermission');
5366
5969
  export const DELETE = ctrl.handle('revokeUserPermission');
5367
- `}static apiAdminExport(){return`import { AdminController } from '$lib/controllers/AdminController.js';
5970
+ `}static apiAdminExport(){return`import { AdminController } from '$lib/modules/admin/AdminController.js';
5368
5971
 
5369
5972
  const ctrl = new AdminController();
5370
5973
  export const POST = ctrl.handle('exportData');
5974
+ `}static apiAdminHealth(){return`import { json } from '@sveltejs/kit';
5975
+ import type { RequestHandler } from '@sveltejs/kit';
5976
+
5977
+ export const GET: RequestHandler = async () => {
5978
+ const health = {
5979
+ status: 'ok',
5980
+ timestamp: new Date().toISOString(),
5981
+ uptime: process.uptime(),
5982
+ memory: process.memoryUsage(),
5983
+ version: '0.1.0',
5984
+ };
5985
+
5986
+ return json(health);
5987
+ };
5988
+ `}static apiAdminQueue(){return`import { json } from '@sveltejs/kit';
5989
+ import type { RequestHandler } from '@sveltejs/kit';
5990
+ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
5991
+
5992
+ export const GET: RequestHandler = async (event) => {
5993
+ const { searchParams } = event.url;
5994
+ const status = searchParams.get('status') || 'all';
5995
+ const queueName = searchParams.get('queue') || 'default';
5996
+ const limit = parseInt(searchParams.get('limit') || '50');
5997
+ const offset = parseInt(searchParams.get('offset') || '0');
5998
+
5999
+ try {
6000
+ const jobs = await JobMonitor.listJobs({
6001
+ queue: queueName,
6002
+ status: status === 'all' ? undefined : status as any,
6003
+ limit,
6004
+ offset,
6005
+ });
6006
+ const counts = await JobMonitor.getCounts(queueName);
6007
+ return json({ jobs, counts, queueName });
6008
+ } catch (error: any) {
6009
+ return json({ error: error.message || 'Failed to fetch queue jobs' }, { status: 500 });
6010
+ }
6011
+ };
6012
+ `}static apiAdminQueueRetry(){return`import { json } from '@sveltejs/kit';
6013
+ import type { RequestHandler } from '@sveltejs/kit';
6014
+ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
6015
+
6016
+ export const POST: RequestHandler = async (event) => {
6017
+ const { id } = event.params;
6018
+ try {
6019
+ await JobMonitor.retryJob(id);
6020
+ return json({ success: true, message: 'Job queued for retry' });
6021
+ } catch (error: any) {
6022
+ return json({ error: error.message || 'Failed to retry job' }, { status: 500 });
6023
+ }
6024
+ };
6025
+ `}static apiAdminQueueDelete(){return`import { json } from '@sveltejs/kit';
6026
+ import type { RequestHandler } from '@sveltejs/kit';
6027
+ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
6028
+
6029
+ export const DELETE: RequestHandler = async (event) => {
6030
+ const { id } = event.params;
6031
+ try {
6032
+ await JobMonitor.deleteJob(id);
6033
+ return json({ success: true, message: 'Job removed' });
6034
+ } catch (error: any) {
6035
+ return json({ error: error.message || 'Failed to remove job' }, { status: 500 });
6036
+ }
6037
+ };
6038
+ `}static apiAdminScheduler(){return`import { json } from '@sveltejs/kit';
6039
+ import type { RequestHandler } from '@sveltejs/kit';
6040
+ import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
6041
+
6042
+ export const GET: RequestHandler = async () => {
6043
+ try {
6044
+ const tasks = await ScheduleMonitor.listTasks();
6045
+ const health = await ScheduleMonitor.getHealth();
6046
+ return json({ tasks, health });
6047
+ } catch (error: any) {
6048
+ return json({ error: error.message || 'Failed to fetch scheduled tasks' }, { status: 500 });
6049
+ }
6050
+ };
6051
+ `}static apiAdminSchedulerRun(){return`import { json } from '@sveltejs/kit';
6052
+ import type { RequestHandler } from '@sveltejs/kit';
6053
+ import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
6054
+
6055
+ export const POST: RequestHandler = async (event) => {
6056
+ const { name } = event.params;
6057
+ try {
6058
+ await ScheduleMonitor.runTask(name);
6059
+ return json({ success: true, message: \`Task '\${name}' triggered\` });
6060
+ } catch (error: any) {
6061
+ return json({ error: error.message || 'Failed to run task' }, { status: 500 });
6062
+ }
6063
+ };
6064
+ `}static apiAdminSchedulerToggle(){return`import { json } from '@sveltejs/kit';
6065
+ import type { RequestHandler } from '@sveltejs/kit';
6066
+ import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
6067
+
6068
+ export const POST: RequestHandler = async (event) => {
6069
+ const { name } = event.params;
6070
+ const body = await event.request.json();
6071
+ const enabled = body.enabled ?? true;
6072
+
6073
+ try {
6074
+ if (enabled) {
6075
+ ScheduleMonitor.enableTask(name);
6076
+ } else {
6077
+ ScheduleMonitor.disableTask(name);
6078
+ }
6079
+ return json({ success: true, message: \`Task '\${name}' \${enabled ? 'enabled' : 'disabled'}\` });
6080
+ } catch (error: any) {
6081
+ return json({ error: error.message || 'Failed to toggle task' }, { status: 500 });
6082
+ }
6083
+ };
6084
+ `}static apiAdminLogs(){return`import { json } from '@sveltejs/kit';
6085
+ import type { RequestHandler } from '@sveltejs/kit';
6086
+ import { LogViewer } from '@beeblock/svelar/logging/LogViewer';
6087
+
6088
+ export const GET: RequestHandler = async (event) => {
6089
+ const { searchParams } = event.url;
6090
+ const level = searchParams.get('level');
6091
+ const channel = searchParams.get('channel');
6092
+ const search = searchParams.get('search');
6093
+ const limit = parseInt(searchParams.get('limit') || '100');
6094
+ const offset = parseInt(searchParams.get('offset') || '0');
6095
+
6096
+ try {
6097
+ const logs = LogViewer.query({
6098
+ level: level as any,
6099
+ channel: channel ?? undefined,
6100
+ search: search ?? undefined,
6101
+ limit,
6102
+ offset,
6103
+ });
6104
+ const stats = LogViewer.getStats();
6105
+ return json({ logs, total: stats.totalEntries, limit, offset });
6106
+ } catch (error: any) {
6107
+ return json({ error: error.message || 'Failed to fetch logs' }, { status: 500 });
6108
+ }
6109
+ };
6110
+ `}static apiAdminStats(){return`import { json } from '@sveltejs/kit';
6111
+ import type { RequestHandler } from '@sveltejs/kit';
6112
+ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
6113
+ import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
6114
+ import { LogViewer } from '@beeblock/svelar/logging/LogViewer';
6115
+
6116
+ export const GET: RequestHandler = async () => {
6117
+ try {
6118
+ const [queueHealth, recentErrors] = await Promise.all([
6119
+ JobMonitor.getHealth(),
6120
+ Promise.resolve(LogViewer.getRecentErrors(10)),
6121
+ ]);
6122
+ const schedulerHealth = await ScheduleMonitor.getHealth();
6123
+ const logStats = LogViewer.getStats();
6124
+
6125
+ return json({
6126
+ queue: queueHealth,
6127
+ scheduler: schedulerHealth,
6128
+ logs: logStats,
6129
+ recentErrors,
6130
+ timestamp: new Date().toISOString(),
6131
+ });
6132
+ } catch (error: any) {
6133
+ return json({ error: error.message || 'Failed to fetch stats' }, { status: 500 });
6134
+ }
6135
+ };
5371
6136
  `}static sendWelcomeEmail(){return`import { Job } from '@beeblock/svelar/queue';
5372
6137
  import { EmailTemplates } from '@beeblock/svelar/email-templates';
5373
6138
  import { Mailer } from '@beeblock/svelar/mail';
@@ -5405,8 +6170,8 @@ export class SendWelcomeEmail extends Job {
5405
6170
  }
5406
6171
  `}static dailyDigestJob(){return`import { Job } from '@beeblock/svelar/queue';
5407
6172
  import { Mailer } from '@beeblock/svelar/mail';
5408
- import { User } from '../../models/User.js';
5409
- import { Post } from '../../models/Post.js';
6173
+ import { User } from '$lib/modules/auth/User.js';
6174
+ import { Post } from '$lib/modules/posts/Post.js';
5410
6175
 
5411
6176
  export class DailyDigestJob extends Job {
5412
6177
  maxAttempts = 3;
@@ -5471,8 +6236,8 @@ export class DailyDigestJob extends Job {
5471
6236
  }
5472
6237
  `}static exportDataJob(){return`import { Job } from '@beeblock/svelar/queue';
5473
6238
  import { Storage } from '@beeblock/svelar/storage';
5474
- import { User } from '../../models/User.js';
5475
- import { Post } from '../../models/Post.js';
6239
+ import { User } from '$lib/modules/auth/User.js';
6240
+ import { Post } from '$lib/modules/posts/Post.js';
5476
6241
 
5477
6242
  export class ExportDataJob extends Job {
5478
6243
  maxAttempts = 2;
@@ -5580,7 +6345,7 @@ export default class CleanExpiredSessions extends ScheduledTask {
5580
6345
  }
5581
6346
  `}static dailyDigestEmail(){return`import { ScheduledTask } from '@beeblock/svelar/scheduler';
5582
6347
  import { Queue } from '@beeblock/svelar/queue';
5583
- import { DailyDigestJob } from '../jobs/DailyDigestJob.js';
6348
+ import { DailyDigestJob } from '$lib/shared/jobs/DailyDigestJob.js';
5584
6349
 
5585
6350
  export default class DailyDigestEmail extends ScheduledTask {
5586
6351
  name = 'daily-digest-email';
@@ -5749,8 +6514,8 @@ export async function load(event: ServerLoadEvent) {
5749
6514
  }
5750
6515
  `}static sendWelcomeEmailListener(){return`import { Queue } from '@beeblock/svelar/queue';
5751
6516
  import { Notifier } from '@beeblock/svelar/notifications';
5752
- import { SendWelcomeEmail } from '../shared/jobs/SendWelcomeEmail.js';
5753
- import { WelcomeNotification } from '../notifications/WelcomeNotification.js';
6517
+ import { SendWelcomeEmail } from '$lib/shared/jobs/SendWelcomeEmail.js';
6518
+ import { WelcomeNotification } from './WelcomeNotification.js';
5754
6519
 
5755
6520
  export class SendWelcomeEmailListener {
5756
6521
  async handle(event: any): Promise<void> {
@@ -5785,8 +6550,8 @@ export class WelcomeNotification extends Notification {
5785
6550
  }
5786
6551
  }
5787
6552
  `}static eventServiceProvider(){return`import { EventServiceProvider as BaseProvider } from '@beeblock/svelar/events';
5788
- import { UserRegistered } from '../../events/UserRegistered.js';
5789
- import { SendWelcomeEmailListener } from '../../listeners/SendWelcomeEmailListener.js';
6553
+ import { UserRegistered } from '$lib/modules/auth/UserRegistered.js';
6554
+ import { SendWelcomeEmailListener } from '$lib/modules/auth/SendWelcomeEmailListener.js';
5790
6555
 
5791
6556
  export class EventServiceProvider extends BaseProvider {
5792
6557
  protected listen = {
@@ -5845,12 +6610,12 @@ export class EventServiceProvider extends BaseProvider {
5845
6610
  </Card>
5846
6611
  </div>
5847
6612
  </div>
5848
- `}};var ts=class extends h{name="new";description="Create a new SvelteKit project with Svelar pre-configured";arguments=["name"];flags=[{name:"no-install",alias:"n",description:"Skip npm install",type:"boolean",default:!1}];async handle(e,t){let{join:s,resolve:r}=await import("path"),{existsSync:n,mkdirSync:i,writeFileSync:a}=await import("fs"),{execSync:o}=await import("child_process"),c=e[0];c||(this.error("Please provide a project name: npx svelar new my-app"),process.exit(1));let u=r(process.cwd(),c);n(u)&&(this.error(`Directory "${c}" already exists.`),process.exit(1)),this.log(""),this.log(` \x1B[1m\x1B[38;5;208m</> Svelar\x1B[0m \u2014 Creating new project
5849
- `);let d=(M,Ar)=>{let K=s(u,M);i(s(K,".."),{recursive:!0}),a(K,Ar)};this.info("Creating project structure...");let p=["","src","src/lib","src/lib/models","src/lib/repositories","src/lib/services","src/lib/controllers","src/lib/dtos","src/lib/actions","src/lib/auth","src/lib/schemas","src/lib/shared/jobs","src/lib/shared/scheduler","src/lib/events","src/lib/listeners","src/lib/resources","src/lib/notifications","src/lib/shared/middleware","src/lib/shared/components","src/lib/shared/stores","src/lib/shared/plugins","src/lib/shared/channels","src/lib/shared/commands","src/lib/shared/providers","src/lib/database/migrations","src/lib/database/seeders","src/routes","src/routes/api","static","storage/logs","storage/cache","storage/uploads","storage/sessions"];for(let M of p)i(s(u,M),{recursive:!0});this.info("Writing config files...");let{dirname:f}=await import("path"),{fileURLToPath:y}=await import("url"),S=s(f(f(f(y(import.meta.url)))),"package.json"),ls=JSON.parse((await import("fs")).readFileSync(S,"utf-8")).version??"0.4.0";d("package.json",m.packageJson(c,ls)),d("svelte.config.js",m.svelteConfig()),d("vite.config.ts",m.viteConfig()),d("tsconfig.json",m.tsConfig()),d("src/app.html",m.appHtml()),d("src/app.css",m.appCss()),d("src/app.ts",m.appTs()),d("src/hooks.server.ts",m.hooksServerTs()),d(".env.example",m.envExample());let{randomBytes:ve}=await import("crypto"),Be=ve(32).toString("hex"),be=ve(16).toString("hex"),we=m.envExample().replace("APP_KEY=change-me-to-a-random-string",`APP_KEY=${Be}`).replace("INTERNAL_SECRET=change-me-to-a-random-string",`INTERNAL_SECRET=${be}`);d(".env",we),d(".gitignore",m.gitignore()),d("svelar.database.json",m.svelarDatabaseJson());for(let M of["storage/logs","storage/cache","storage/uploads","storage/sessions"])d(`${M}/.gitkeep`,"");if(this.info("Scaffolding domain layer..."),d("src/lib/models/User.ts",m.userModel()),d("src/lib/models/Post.ts",m.postModel()),d("src/lib/repositories/UserRepository.ts",m.userRepository()),d("src/lib/repositories/PostRepository.ts",m.postRepository()),d("src/lib/services/AuthService.ts",m.authService()),d("src/lib/services/PostService.ts",m.postService()),d("src/lib/controllers/AuthController.ts",m.authController()),d("src/lib/controllers/PostController.ts",m.postController()),d("src/lib/controllers/AdminController.ts",m.adminController()),d("src/lib/dtos/RegisterRequest.ts",m.registerRequest()),d("src/lib/dtos/LoginRequest.ts",m.loginRequest()),d("src/lib/dtos/CreatePostRequest.ts",m.createPostRequest()),d("src/lib/dtos/UpdatePostRequest.ts",m.updatePostRequest()),d("src/lib/dtos/UpdateUserRoleRequest.ts",m.updateUserRoleRequest()),d("src/lib/dtos/DeleteUserRequest.ts",m.deleteUserRequest()),d("src/lib/dtos/CreateRoleRequest.ts",m.createRoleRequest()),d("src/lib/dtos/DeleteRoleRequest.ts",m.deleteRoleRequest()),d("src/lib/dtos/CreatePermissionRequest.ts",m.createPermissionRequest()),d("src/lib/dtos/DeletePermissionRequest.ts",m.deletePermissionRequest()),d("src/lib/dtos/RolePermissionRequest.ts",m.rolePermissionRequest()),d("src/lib/dtos/UserRoleRequest.ts",m.userRoleRequest()),d("src/lib/dtos/UserPermissionRequest.ts",m.userPermissionRequest()),d("src/lib/dtos/ExportDataRequest.ts",m.exportDataRequest()),d("src/lib/actions/RegisterUserAction.ts",m.registerUserAction()),d("src/lib/actions/CreatePostAction.ts",m.createPostAction()),d("src/lib/auth/gates.ts",m.gates()),d("src/lib/schemas/auth.ts",m.authSchema()),d("src/lib/schemas/post.ts",m.postSchema()),d("src/lib/schemas/admin.ts",m.adminSchema()),d("src/lib/services/AdminService.ts",m.adminService()),d("src/lib/resources/RoleResource.ts",m.roleResource()),d("src/lib/resources/PermissionResource.ts",m.permissionResource()),d("src/lib/shared/providers/EventServiceProvider.ts",m.eventServiceProvider()),d("src/lib/resources/UserResource.ts",m.userResource()),d("src/lib/resources/PostResource.ts",m.postResource()),d("src/lib/events/UserRegistered.ts",m.userRegisteredEvent()),d("src/lib/listeners/SendWelcomeEmailListener.ts",m.sendWelcomeEmailListener()),d("src/lib/notifications/WelcomeNotification.ts",m.welcomeNotification()),this.info("Creating migrations..."),d("src/lib/database/migrations/00000001_create_users_table.ts",m.createUsersTable()),d("src/lib/database/migrations/00000002_create_posts_table.ts",m.createPostsTable()),d("src/lib/database/migrations/00000003_create_permissions_tables.ts",m.createPermissionsTables()),d("src/lib/database/migrations/00000004_add_role_to_users.ts",m.addRoleToUsers()),d("src/lib/database/migrations/00000005_create_sessions_table.ts",m.createSessionsTable()),d("src/lib/database/migrations/00000006_create_audit_logs_table.ts",m.createAuditLogsTable()),d("src/lib/database/migrations/00000007_create_notifications_table.ts",m.createNotificationsTable()),d("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",m.createFailedJobsTable()),d("src/lib/database/seeders/DatabaseSeeder.ts",m.databaseSeeder()),this.info("Creating auth pages..."),d("src/routes/login/+page.server.ts",m.loginPageServer()),d("src/routes/login/+page.svelte",m.loginPageSvelte()),d("src/routes/register/+page.server.ts",m.registerPageServer()),d("src/routes/register/+page.svelte",m.registerPageSvelte()),d("src/routes/logout/+page.server.ts",m.logoutPageServer()),d("src/routes/forgot-password/+page.server.ts",m.forgotPasswordPageServer()),d("src/routes/forgot-password/+page.svelte",m.forgotPasswordPageSvelte()),d("src/routes/reset-password/+page.server.ts",m.resetPasswordPageServer()),d("src/routes/reset-password/+page.svelte",m.resetPasswordPageSvelte()),d("src/routes/otp-login/+page.server.ts",m.otpLoginPageServer()),d("src/routes/otp-login/+page.svelte",m.otpLoginPageSvelte()),d("src/routes/verify-email/+page.server.ts",m.verifyEmailPageServer()),d("src/routes/verify-email/+page.svelte",m.verifyEmailPageSvelte()),this.info("Creating dashboard..."),d("src/routes/dashboard/+layout.server.ts",m.dashboardLayoutServer()),d("src/routes/dashboard/+page.server.ts",m.dashboardPageServer()),d("src/routes/dashboard/+page.svelte",m.dashboardPageSvelte()),d("src/routes/dashboard/api-keys/+page.server.ts",m.apiKeysPageServer()),d("src/routes/dashboard/api-keys/+page.svelte",m.apiKeysPageSvelte()),d("src/routes/dashboard/team/+page.server.ts",m.teamPageServer()),d("src/routes/dashboard/team/+page.svelte",m.teamPageSvelte()),this.info("Creating admin panel..."),d("src/routes/admin/+layout.server.ts",m.adminLayoutServer()),d("src/routes/admin/+page.server.ts",m.adminPageServer()),d("src/routes/admin/+page.svelte",m.adminPageSvelte()),this.info("Creating API routes..."),d("src/routes/api/health/+server.ts",m.apiHealth()),d("src/routes/api/auth/register/+server.ts",m.apiAuthRegister()),d("src/routes/api/auth/login/+server.ts",m.apiAuthLogin()),d("src/routes/api/auth/logout/+server.ts",m.apiAuthLogout()),d("src/routes/api/auth/me/+server.ts",m.apiAuthMe()),d("src/routes/api/auth/forgot-password/+server.ts",m.apiAuthForgotPassword()),d("src/routes/api/auth/reset-password/+server.ts",m.apiAuthResetPassword()),d("src/routes/api/auth/otp/send/+server.ts",m.apiAuthOtpSend()),d("src/routes/api/auth/otp/verify/+server.ts",m.apiAuthOtpVerify()),d("src/routes/api/auth/verify-email/+server.ts",m.apiAuthVerifyEmail()),d("src/routes/api/posts/+server.ts",m.apiPosts()),d("src/routes/api/posts/[id]/+server.ts",m.apiPostsSingle()),d("src/routes/api/posts/mine/+server.ts",m.apiPostsMine()),d("src/routes/api/broadcasting/[channel]/+server.ts",m.apiBroadcasting()),d("src/routes/api/internal/broadcast/+server.ts",m.apiInternalBroadcast()),d("src/routes/api/admin/users/+server.ts",m.apiAdminUsers()),d("src/routes/api/admin/roles/+server.ts",m.apiAdminRoles()),d("src/routes/api/admin/permissions/+server.ts",m.apiAdminPermissions()),d("src/routes/api/admin/role-permissions/+server.ts",m.apiAdminRolePermissions()),d("src/routes/api/admin/user-roles/+server.ts",m.apiAdminUserRoles()),d("src/routes/api/admin/user-permissions/+server.ts",m.apiAdminUserPermissions()),d("src/routes/api/admin/export/+server.ts",m.apiAdminExport()),this.info("Creating background jobs..."),d("src/lib/shared/jobs/SendWelcomeEmail.ts",m.sendWelcomeEmail()),d("src/lib/shared/jobs/DailyDigestJob.ts",m.dailyDigestJob()),d("src/lib/shared/jobs/ExportDataJob.ts",m.exportDataJob()),this.info("Creating scheduled tasks..."),d("src/lib/shared/scheduler/CleanupExpiredTokens.ts",m.cleanupExpiredTokens()),d("src/lib/shared/scheduler/CleanExpiredSessions.ts",m.cleanExpiredSessions()),d("src/lib/shared/scheduler/DailyDigestEmail.ts",m.dailyDigestEmail()),d("src/lib/shared/scheduler/PruneAuditLogs.ts",m.pruneAuditLogs()),d("src/lib/shared/scheduler/QueueHealthCheck.ts",m.queueHealthCheck()),this.info("Creating layouts..."),d("src/routes/+layout.svelte",m.rootLayoutSvelte(c)),d("src/routes/+layout.server.ts",m.rootLayoutServer()),d("src/routes/+error.svelte",m.errorSvelte()),d("src/routes/+page.svelte",m.homePage(c)),this.success("Project structure created"),!t["no-install"]){this.info("Installing dependencies...");try{o("npm install",{cwd:u,stdio:"inherit"}),this.success("Dependencies installed")}catch{this.warn("npm install failed \u2014 run it manually with: cd "+c+" && npm install")}this.info("Running migrations...");try{o("npx svelar migrate",{cwd:u,stdio:"inherit"}),this.success("Migrations complete")}catch{this.warn("Migrations failed \u2014 run manually: cd "+c+" && npx svelar migrate")}this.info("Seeding database...");try{o("npx svelar seed:run",{cwd:u,stdio:"inherit"}),this.success("Database seeded")}catch{this.warn("Seeding failed \u2014 run manually: cd "+c+" && npx svelar seed:run")}}this.log(""),this.log(` \x1B[32m+\x1B[0m Project \x1B[1m${c}\x1B[0m created successfully!
6613
+ `}};var ts=class extends g{name="new";description="Create a new SvelteKit project with Svelar pre-configured";arguments=["name"];flags=[{name:"no-install",alias:"n",description:"Skip npm install",type:"boolean",default:!1},{name:"flat",description:"Use flat folder structure instead of DDD modules",type:"boolean",default:!1}];async handle(e,t){let{join:s,resolve:r}=await import("path"),{existsSync:i,mkdirSync:n,writeFileSync:a}=await import("fs"),{execSync:l}=await import("child_process"),c=e[0];c||(this.error("Please provide a project name: npx svelar new my-app"),process.exit(1));let d=r(process.cwd(),c);i(d)&&(this.error(`Directory "${c}" already exists.`),process.exit(1));let p=t.flat||!1,h=p?"flat":"DDD modular";this.log(""),this.log(` \x1B[1m\x1B[38;5;208m</> Svelar\x1B[0m \u2014 Creating new project (${h})
6614
+ `);let u=($,Fe)=>{let ds=p?go($):$,Be=p?fo(Fe,$):Fe,He=s(d,ds);n(s(He,".."),{recursive:!0}),a(He,Be)};this.info("Creating project structure...");let v=p?["","src","src/lib","src/lib/models","src/lib/services","src/lib/controllers","src/lib/repositories","src/lib/dtos","src/lib/actions","src/lib/resources","src/lib/events","src/lib/listeners","src/lib/notifications","src/lib/schemas","src/lib/jobs","src/lib/scheduler","src/lib/middleware","src/lib/components","src/lib/stores","src/lib/plugins","src/lib/channels","src/lib/commands","src/lib/providers","src/lib/database/migrations","src/lib/database/seeders","src/routes","src/routes/api","static","storage/logs","storage/cache","storage/uploads","storage/sessions"]:["","src","src/lib","src/lib/modules/auth","src/lib/modules/posts","src/lib/modules/admin","src/lib/shared/jobs","src/lib/shared/scheduler","src/lib/shared/middleware","src/lib/shared/components","src/lib/shared/stores","src/lib/shared/plugins","src/lib/shared/channels","src/lib/shared/commands","src/lib/shared/providers","src/lib/database/migrations","src/lib/database/seeders","src/routes","src/routes/api","static","storage/logs","storage/cache","storage/uploads","storage/sessions"];for(let $ of v)n(s(d,$),{recursive:!0});this.info("Writing config files...");let{dirname:x}=await import("path"),{fileURLToPath:k}=await import("url"),ls=s(x(x(x(k(import.meta.url)))),"package.json"),Ue=JSON.parse((await import("fs")).readFileSync(ls,"utf-8")).version??"0.4.0";u("package.json",m.packageJson(c,Ue)),u("svelte.config.js",m.svelteConfig()),u("vite.config.ts",m.viteConfig()),u("tsconfig.json",m.tsConfig()),u("src/app.html",m.appHtml()),u("static/favicon.svg",m.faviconSvg()),u("src/app.css",m.appCss()),u("src/app.ts",m.appTs()),u("src/hooks.server.ts",m.hooksServerTs()),u(".env.example",m.envExample());let{randomBytes:z}=await import("crypto"),ye=z(32).toString("hex"),be=z(16).toString("hex"),Mr=m.envExample().replace("APP_KEY=change-me-to-a-random-string",`APP_KEY=${ye}`).replace("INTERNAL_SECRET=change-me-to-a-random-string",`INTERNAL_SECRET=${be}`);u(".env",Mr),u(".gitignore",m.gitignore()),u("svelar.database.json",m.svelarDatabaseJson());for(let $ of["storage/logs","storage/cache","storage/uploads","storage/sessions"])u(`${$}/.gitkeep`,"");if(this.info("Scaffolding domain layer..."),u("src/lib/modules/auth/User.ts",m.userModel()),u("src/lib/modules/auth/UserRepository.ts",m.userRepository()),u("src/lib/modules/auth/AuthService.ts",m.authService()),u("src/lib/modules/auth/AuthController.ts",m.authController()),u("src/lib/modules/auth/RegisterUserAction.ts",m.registerUserAction()),u("src/lib/modules/auth/RegisterRequest.ts",m.registerRequest()),u("src/lib/modules/auth/LoginRequest.ts",m.loginRequest()),u("src/lib/modules/auth/ForgotPasswordRequest.ts",m.forgotPasswordRequest()),u("src/lib/modules/auth/ResetPasswordRequest.ts",m.resetPasswordRequest()),u("src/lib/modules/auth/OtpSendRequest.ts",m.otpSendRequest()),u("src/lib/modules/auth/OtpVerifyRequest.ts",m.otpVerifyRequest()),u("src/lib/modules/auth/UserResource.ts",m.userResource()),u("src/lib/modules/auth/gates.ts",m.gates()),u("src/lib/modules/auth/schemas.ts",m.authSchema()),u("src/lib/modules/auth/UserRegistered.ts",m.userRegisteredEvent()),u("src/lib/modules/auth/SendWelcomeEmailListener.ts",m.sendWelcomeEmailListener()),u("src/lib/modules/auth/WelcomeNotification.ts",m.welcomeNotification()),u("src/lib/modules/posts/Post.ts",m.postModel()),u("src/lib/modules/posts/PostRepository.ts",m.postRepository()),u("src/lib/modules/posts/PostService.ts",m.postService()),u("src/lib/modules/posts/PostController.ts",m.postController()),u("src/lib/modules/posts/CreatePostAction.ts",m.createPostAction()),u("src/lib/modules/posts/CreatePostRequest.ts",m.createPostRequest()),u("src/lib/modules/posts/UpdatePostRequest.ts",m.updatePostRequest()),u("src/lib/modules/posts/PostResource.ts",m.postResource()),u("src/lib/modules/posts/schemas.ts",m.postSchema()),u("src/lib/modules/admin/AdminService.ts",m.adminService()),u("src/lib/modules/admin/AdminController.ts",m.adminController()),u("src/lib/modules/admin/UpdateUserRoleRequest.ts",m.updateUserRoleRequest()),u("src/lib/modules/admin/DeleteUserRequest.ts",m.deleteUserRequest()),u("src/lib/modules/admin/CreateRoleRequest.ts",m.createRoleRequest()),u("src/lib/modules/admin/DeleteRoleRequest.ts",m.deleteRoleRequest()),u("src/lib/modules/admin/CreatePermissionRequest.ts",m.createPermissionRequest()),u("src/lib/modules/admin/DeletePermissionRequest.ts",m.deletePermissionRequest()),u("src/lib/modules/admin/RolePermissionRequest.ts",m.rolePermissionRequest()),u("src/lib/modules/admin/UserRoleRequest.ts",m.userRoleRequest()),u("src/lib/modules/admin/UserPermissionRequest.ts",m.userPermissionRequest()),u("src/lib/modules/admin/ExportDataRequest.ts",m.exportDataRequest()),u("src/lib/modules/admin/RoleResource.ts",m.roleResource()),u("src/lib/modules/admin/PermissionResource.ts",m.permissionResource()),u("src/lib/modules/admin/schemas.ts",m.adminSchema()),u("src/lib/shared/providers/EventServiceProvider.ts",m.eventServiceProvider()),this.info("Creating migrations..."),u("src/lib/database/migrations/00000001_create_users_table.ts",m.createUsersTable()),u("src/lib/database/migrations/00000002_create_posts_table.ts",m.createPostsTable()),u("src/lib/database/migrations/00000003_create_permissions_tables.ts",m.createPermissionsTables()),u("src/lib/database/migrations/00000004_add_role_to_users.ts",m.addRoleToUsers()),u("src/lib/database/migrations/00000005_create_sessions_table.ts",m.createSessionsTable()),u("src/lib/database/migrations/00000006_create_audit_logs_table.ts",m.createAuditLogsTable()),u("src/lib/database/migrations/00000007_create_notifications_table.ts",m.createNotificationsTable()),u("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",m.createFailedJobsTable()),u("src/lib/database/seeders/DatabaseSeeder.ts",m.databaseSeeder()),this.info("Creating auth pages..."),u("src/routes/login/+page.server.ts",m.loginPageServer()),u("src/routes/login/+page.svelte",m.loginPageSvelte()),u("src/routes/register/+page.server.ts",m.registerPageServer()),u("src/routes/register/+page.svelte",m.registerPageSvelte()),u("src/routes/logout/+page.server.ts",m.logoutPageServer()),u("src/routes/forgot-password/+page.server.ts",m.forgotPasswordPageServer()),u("src/routes/forgot-password/+page.svelte",m.forgotPasswordPageSvelte()),u("src/routes/reset-password/+page.server.ts",m.resetPasswordPageServer()),u("src/routes/reset-password/+page.svelte",m.resetPasswordPageSvelte()),u("src/routes/otp-login/+page.server.ts",m.otpLoginPageServer()),u("src/routes/otp-login/+page.svelte",m.otpLoginPageSvelte()),u("src/routes/verify-email/+page.server.ts",m.verifyEmailPageServer()),u("src/routes/verify-email/+page.svelte",m.verifyEmailPageSvelte()),this.info("Creating dashboard..."),u("src/routes/dashboard/+layout.server.ts",m.dashboardLayoutServer()),u("src/routes/dashboard/+layout.svelte",m.dashboardLayoutSvelte()),u("src/routes/dashboard/+page.server.ts",m.dashboardPageServer()),u("src/routes/dashboard/+page.svelte",m.dashboardPageSvelte()),u("src/routes/dashboard/api-keys/+page.server.ts",m.apiKeysPageServer()),u("src/routes/dashboard/api-keys/+page.svelte",m.apiKeysPageSvelte()),u("src/routes/dashboard/team/+page.server.ts",m.teamPageServer()),u("src/routes/dashboard/team/+page.svelte",m.teamPageSvelte()),this.info("Creating admin panel..."),u("src/routes/admin/+layout.server.ts",m.adminLayoutServer()),u("src/routes/admin/+layout.svelte",m.adminLayoutSvelte()),u("src/routes/admin/+page.server.ts",m.adminPageServer()),u("src/routes/admin/+page.svelte",m.adminPageSvelte()),this.info("Creating API routes..."),u("src/routes/api/health/+server.ts",m.apiHealth()),u("src/routes/api/auth/register/+server.ts",m.apiAuthRegister()),u("src/routes/api/auth/login/+server.ts",m.apiAuthLogin()),u("src/routes/api/auth/logout/+server.ts",m.apiAuthLogout()),u("src/routes/api/auth/me/+server.ts",m.apiAuthMe()),u("src/routes/api/auth/forgot-password/+server.ts",m.apiAuthForgotPassword()),u("src/routes/api/auth/reset-password/+server.ts",m.apiAuthResetPassword()),u("src/routes/api/auth/otp/send/+server.ts",m.apiAuthOtpSend()),u("src/routes/api/auth/otp/verify/+server.ts",m.apiAuthOtpVerify()),u("src/routes/api/auth/verify-email/+server.ts",m.apiAuthVerifyEmail()),u("src/routes/api/posts/+server.ts",m.apiPosts()),u("src/routes/api/posts/[id]/+server.ts",m.apiPostsSingle()),u("src/routes/api/posts/mine/+server.ts",m.apiPostsMine()),u("src/routes/api/broadcasting/[channel]/+server.ts",m.apiBroadcasting()),u("src/routes/api/internal/broadcast/+server.ts",m.apiInternalBroadcast()),u("src/routes/api/admin/users/+server.ts",m.apiAdminUsers()),u("src/routes/api/admin/roles/+server.ts",m.apiAdminRoles()),u("src/routes/api/admin/permissions/+server.ts",m.apiAdminPermissions()),u("src/routes/api/admin/role-permissions/+server.ts",m.apiAdminRolePermissions()),u("src/routes/api/admin/user-roles/+server.ts",m.apiAdminUserRoles()),u("src/routes/api/admin/user-permissions/+server.ts",m.apiAdminUserPermissions()),u("src/routes/api/admin/export/+server.ts",m.apiAdminExport()),u("src/routes/api/admin/health/+server.ts",m.apiAdminHealth()),u("src/routes/api/admin/queue/+server.ts",m.apiAdminQueue()),u("src/routes/api/admin/queue/[id]/retry/+server.ts",m.apiAdminQueueRetry()),u("src/routes/api/admin/queue/[id]/+server.ts",m.apiAdminQueueDelete()),u("src/routes/api/admin/scheduler/+server.ts",m.apiAdminScheduler()),u("src/routes/api/admin/scheduler/[name]/run/+server.ts",m.apiAdminSchedulerRun()),u("src/routes/api/admin/scheduler/[name]/toggle/+server.ts",m.apiAdminSchedulerToggle()),u("src/routes/api/admin/logs/+server.ts",m.apiAdminLogs()),u("src/routes/api/admin/stats/+server.ts",m.apiAdminStats()),this.info("Creating background jobs..."),u("src/lib/shared/jobs/SendWelcomeEmail.ts",m.sendWelcomeEmail()),u("src/lib/shared/jobs/DailyDigestJob.ts",m.dailyDigestJob()),u("src/lib/shared/jobs/ExportDataJob.ts",m.exportDataJob()),this.info("Creating scheduled tasks..."),u("src/lib/shared/scheduler/CleanupExpiredTokens.ts",m.cleanupExpiredTokens()),u("src/lib/shared/scheduler/CleanExpiredSessions.ts",m.cleanExpiredSessions()),u("src/lib/shared/scheduler/DailyDigestEmail.ts",m.dailyDigestEmail()),u("src/lib/shared/scheduler/PruneAuditLogs.ts",m.pruneAuditLogs()),u("src/lib/shared/scheduler/QueueHealthCheck.ts",m.queueHealthCheck()),this.info("Creating layouts..."),u("src/routes/+layout.svelte",m.rootLayoutSvelte(c)),u("src/routes/+layout.server.ts",m.rootLayoutServer()),u("src/routes/+error.svelte",m.errorSvelte()),u("src/routes/+page.svelte",m.homePage(c)),this.success(`Project structure created (${h})`),!t["no-install"]){this.info("Installing dependencies...");try{l("npm install",{cwd:d,stdio:"inherit"}),this.success("Dependencies installed")}catch{this.warn("npm install failed \u2014 run it manually with: cd "+c+" && npm install")}this.info("Running migrations...");try{l("npx svelar migrate",{cwd:d,stdio:"inherit"}),this.success("Migrations complete")}catch{this.warn("Migrations failed \u2014 run manually: cd "+c+" && npx svelar migrate")}this.info("Seeding database...");try{l("npx svelar seed:run",{cwd:d,stdio:"inherit"}),this.success("Database seeded")}catch{this.warn("Seeding failed \u2014 run manually: cd "+c+" && npx svelar seed:run")}}this.log(""),this.log(` \x1B[32m+\x1B[0m Project \x1B[1m${c}\x1B[0m created successfully!
5850
6615
  `),this.log(` Next steps:
5851
- `),this.log(` cd ${c}`),t["no-install"]&&(this.log(" npm install"),this.log(" npx svelar migrate"),this.log(" npx svelar seed:run")),this.log(" npm run dev"),this.log(""),this.log(" Default accounts:"),this.log(" Admin: admin@svelar.dev / admin123"),this.log(" Demo: demo@svelar.dev / password"),this.log("")}};var ss=class extends h{name="key:generate";description="Generate a new APP_KEY and set it in .env";flags=[{name:"show",alias:"s",description:"Only display the key, do not write to .env",type:"boolean",default:!1},{name:"force",alias:"f",description:"Overwrite existing APP_KEY",type:"boolean",default:!1}];async handle(e,t){let{randomBytes:s}=await import("crypto"),{join:r}=await import("path"),{existsSync:n,readFileSync:i,writeFileSync:a}=await import("fs"),o=s(32).toString("hex");if(t.show){this.log(`
5852
- APP_KEY=${o}
5853
- `);return}let c=r(process.cwd(),".env");if(!n(c)){let p=r(process.cwd(),".env.example");if(n(p)){let f=i(p,"utf-8");f=f.replace(/^APP_KEY=.*$/m,`APP_KEY=${o}`),a(c,f),this.success("Application key set (created .env from .env.example).")}else a(c,`APP_KEY=${o}
5854
- `),this.success("Application key set (created .env).");return}let u=i(c,"utf-8"),d=u.match(/^APP_KEY=(.*)$/m);if(d&&d[1]&&d[1]!=="change-me-to-a-random-string"&&!t.force){this.warn("APP_KEY already set. Use --force to overwrite.");return}if(d){let p=u.replace(/^APP_KEY=.*$/m,`APP_KEY=${o}`);a(c,p)}else a(c,`APP_KEY=${o}
5855
- ${u}`);this.success("Application key set.")}};var ns=class extends h{name="plugin:list";description="List all discovered and enabled plugins";arguments=[];flags=[];async handle(e,t){try{let{PluginRegistry:s}=await Promise.resolve().then(()=>(is(),Sr)),r=s;await r.discover();let n=r.list();if(n.length===0){this.info("No plugins discovered.");return}let i=["Name","Version","Description","Status","Config","Migrations"],a=n.map(o=>[o.name,o.version,o.description||"-",o.enabled?"\u2713 Enabled":" Disabled",o.hasConfig?"\u2713":"-",o.hasMigrations?"\u2713":"-"]);this.newLine(),this.table(i,a),this.newLine(),this.info(`Total: ${n.length} plugin(s)`)}catch(s){this.error(`Failed to list plugins: ${s?.message??String(s)}`)}}};var as=class extends h{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(()=>(is(),Sr)),{PluginPublisher:n}=await Promise.resolve().then(()=>(Er(),dn)),i=r,a=n;await i.discover();let o=i.get(s);if(!o){this.error(`Plugin "${s}" not found.`);return}let c=await this.loadPluginClass(o.packageName);if(!c){this.error(`Failed to load plugin class for "${s}".`);return}let u=new c,d={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let p=await a.publish(u,d);this.newLine(),p.configs.length>0&&(this.success(`${p.configs.length} config file(s) published:`),p.configs.forEach(f=>this.log(` - ${f}`))),p.migrations.length>0&&(this.success(`${p.migrations.length} migration file(s) published:`),p.migrations.forEach(f=>this.log(` - ${f}`))),p.assets.length>0&&(this.success(`${p.assets.length} asset file(s) published:`),p.assets.forEach(f=>this.log(` - ${f}`))),p.configs.length===0&&p.migrations.length===0&&p.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 os=class extends h{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(()=>(mn(),un)),n=r;this.info(`Installing plugin package: ${s}`),this.newLine();let i=await n.install(s,{publish:!t["no-publish"]});this.newLine(),i.success?(this.success(`Plugin installed: ${i.pluginName} (v${i.version})`),i.published&&(i.published.configs.length>0&&this.info(`${i.published.configs.length} config file(s) published`),i.published.migrations.length>0&&this.info(`${i.published.migrations.length} migration file(s) published`),i.published.assets.length>0&&this.info(`${i.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: ${i.error}`),this.newLine()}catch(r){this.error(`Installation error: ${r?.message??String(r)}`)}}};var pn=$r(process.cwd(),".env");if(wo(pn))for(let l of fn(pn,"utf-8").split(`
5856
- `)){let e=l.trim();if(!e||e.startsWith("#"))continue;let t=e.indexOf("=");if(t===-1)continue;let s=e.slice(0,t).trim(),r=e.slice(t+1).trim();(r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'"))&&(r=r.slice(1,-1)),s in process.env||(process.env[s]=r)}var xo=hn(gn(import.meta.url));bo(vo($r(xo,"ts-resolve-hook.mjs")).href,import.meta.url);var Co=hn(gn(import.meta.url)),Po=$r(Co,"..","..","package.json"),So=JSON.parse(fn(Po,"utf-8")),b=new ze(So.version);b.register(ts);b.register(ss);b.register(Ke);b.register(We);b.register(Je);b.register(Ve);b.register(Qe);b.register(Ge);b.register(Ye);b.register(Xe);b.register(Ze);b.register(et);b.register(dt);b.register(ut);b.register(tt);b.register(st);b.register(rt);b.register(it);b.register(nt);b.register(at);b.register(ot);b.register(lt);b.register(ct);b.register(mt);b.register(pt);b.register(ht);b.register(gt);b.register(ft);b.register(yt);b.register(vt);b.register(xt);b.register(St);b.register(Tt);b.register(Rt);b.register(Et);b.register(es);b.register(ns);b.register(as);b.register(os);async function To(){let{join:l}=await import("path"),{existsSync:e,readdirSync:t}=await import("fs"),{pathToFileURL:s}=await import("url"),r=l(process.cwd(),"src","lib","shared","commands");if(!e(r))return;let n=t(r).filter(i=>(i.endsWith(".ts")||i.endsWith(".js"))&&!i.startsWith("."));for(let i of n)try{let a=l(r,i),c=await import(s(a).href),u=c.default??Object.values(c).find(d=>typeof d=="function"&&d.prototype&&"handle"in d.prototype);u&&typeof u=="function"&&b.add(new u)}catch{}}To().then(()=>b.run());
6616
+ `),this.log(` cd ${c}`),t["no-install"]&&(this.log(" npm install"),this.log(" npx svelar migrate"),this.log(" npx svelar seed:run")),this.log(" npm run dev"),this.log(""),this.log(" Default accounts:"),this.log(" Admin: admin@svelar.dev / admin123"),this.log(" Demo: demo@svelar.dev / password"),this.log("")}};function ho(o){return/Service\./.test(o)?"services":/Controller\./.test(o)?"controllers":/Repository\./.test(o)?"repositories":/Request\./.test(o)?"dtos":/Resource\./.test(o)?"resources":/Action\./.test(o)?"actions":/Listener\./.test(o)?"listeners":/Notification\./.test(o)?"notifications":/Registered|Created|Updated|Deleted|Verified|Invited/.test(o)?"events":"models"}function go(o){let e=o.match(/^src\/lib\/modules\/(\w+)\/(.+)$/);if(e){let[,s,r]=e;return r==="schemas.ts"?`src/lib/schemas/${s}.ts`:r==="gates.ts"?"src/lib/gates.ts":`src/lib/${ho(r)}/${r}`}let t=o.match(/^src\/lib\/shared\/(.+)$/);return t?`src/lib/${t[1]}`:o}function Sr(o,e,t){return e==="schemas"?`$lib/schemas/${o}${t}`:e==="gates"?`$lib/gates${t}`:`$lib/${mn(e)}/${e}${t}`}function mn(o){return/Service$/.test(o)?"services":/Controller$/.test(o)?"controllers":/Repository$/.test(o)?"repositories":/Request$/.test(o)?"dtos":/Resource$/.test(o)?"resources":/Action$/.test(o)?"actions":/Listener$/.test(o)?"listeners":/Notification$/.test(o)?"notifications":/Registered|Created|Updated|Deleted|Verified|Invited/.test(o)?"events":"models"}function fo(o,e){let s=e.match(/modules\/(\w+)\//)?.[1]||"";return o=o.replace(/\$lib\/modules\/(\w+)\/(\w+)(\.js)?/g,(r,i,n,a)=>Sr(i,n,a||"")),o=o.replace(/\.\/lib\/modules\/(\w+)\/(\w+)(\.js)?/g,(r,i,n,a)=>n==="schemas"?`./lib/schemas/${i}${a||""}`:n==="gates"?`./lib/gates${a||""}`:`./lib/${mn(n)}/${n}${a||""}`),o=o.replace(/\$lib\/shared\//g,"$lib/"),o=o.replace(/\.\/lib\/shared\//g,"./lib/"),s&&(o=o.replace(/from '\.\/(\w+)(\.js)?'/g,(r,i,n)=>i.startsWith("$")||i==="app"?r:(n=n||"",`from '${Sr(s,i,n)}'`)),o=o.replace(/import '\.\/(\w+)(\.js)?'/g,(r,i,n)=>i.startsWith("$")||i==="app"?r:(n=n||"",`import '${Sr(s,i,n)}'`))),o}var ss=class extends g{name="key:generate";description="Generate a new APP_KEY and set it in .env";flags=[{name:"show",alias:"s",description:"Only display the key, do not write to .env",type:"boolean",default:!1},{name:"force",alias:"f",description:"Overwrite existing APP_KEY",type:"boolean",default:!1}];async handle(e,t){let{randomBytes:s}=await import("crypto"),{join:r}=await import("path"),{existsSync:i,readFileSync:n,writeFileSync:a}=await import("fs"),l=s(32).toString("hex");if(t.show){this.log(`
6617
+ APP_KEY=${l}
6618
+ `);return}let c=r(process.cwd(),".env");if(!i(c)){let h=r(process.cwd(),".env.example");if(i(h)){let u=n(h,"utf-8");u=u.replace(/^APP_KEY=.*$/m,`APP_KEY=${l}`),a(c,u),this.success("Application key set (created .env from .env.example).")}else a(c,`APP_KEY=${l}
6619
+ `),this.success("Application key set (created .env).");return}let d=n(c,"utf-8"),p=d.match(/^APP_KEY=(.*)$/m);if(p&&p[1]&&p[1]!=="change-me-to-a-random-string"&&!t.force){this.warn("APP_KEY already set. Use --force to overwrite.");return}if(p){let h=d.replace(/^APP_KEY=.*$/m,`APP_KEY=${l}`);a(c,h)}else a(c,`APP_KEY=${l}
6620
+ ${d}`);this.success("Application key set.")}};var ns=class extends g{name="plugin:list";description="List all discovered and enabled plugins";arguments=[];flags=[];async handle(e,t){try{let{PluginRegistry:s}=await Promise.resolve().then(()=>(is(),Er)),r=s;await r.discover();let i=r.list();if(i.length===0){this.info("No plugins discovered.");return}let n=["Name","Version","Description","Status","Config","Migrations"],a=i.map(l=>[l.name,l.version,l.description||"-",l.enabled?"\u2713 Enabled":" Disabled",l.hasConfig?"\u2713":"-",l.hasMigrations?"\u2713":"-"]);this.newLine(),this.table(n,a),this.newLine(),this.info(`Total: ${i.length} plugin(s)`)}catch(s){this.error(`Failed to list plugins: ${s?.message??String(s)}`)}}};var as=class extends g{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(()=>(is(),Er)),{PluginPublisher:i}=await Promise.resolve().then(()=>(Ar(),pn)),n=r,a=i;await n.discover();let l=n.get(s);if(!l){this.error(`Plugin "${s}" not found.`);return}let c=await this.loadPluginClass(l.packageName);if(!c){this.error(`Failed to load plugin class for "${s}".`);return}let d=new c,p={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let h=await a.publish(d,p);this.newLine(),h.configs.length>0&&(this.success(`${h.configs.length} config file(s) published:`),h.configs.forEach(u=>this.log(` - ${u}`))),h.migrations.length>0&&(this.success(`${h.migrations.length} migration file(s) published:`),h.migrations.forEach(u=>this.log(` - ${u}`))),h.assets.length>0&&(this.success(`${h.assets.length} asset file(s) published:`),h.assets.forEach(u=>this.log(` - ${u}`))),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 os=class extends g{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(()=>(gn(),hn)),i=r;this.info(`Installing plugin package: ${s}`),this.newLine();let n=await i.install(s,{publish:!t["no-publish"]});this.newLine(),n.success?(this.success(`Plugin installed: ${n.pluginName} (v${n.version})`),n.published&&(n.published.configs.length>0&&this.info(`${n.published.configs.length} config file(s) published`),n.published.migrations.length>0&&this.info(`${n.published.migrations.length} migration file(s) published`),n.published.assets.length>0&&this.info(`${n.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: ${n.error}`),this.newLine()}catch(r){this.error(`Installation error: ${r?.message??String(r)}`)}}};var fn=Lr(process.cwd(),".env");if(wo(fn))for(let o of vn(fn,"utf-8").split(`
6621
+ `)){let e=o.trim();if(!e||e.startsWith("#"))continue;let t=e.indexOf("=");if(t===-1)continue;let s=e.slice(0,t).trim(),r=e.slice(t+1).trim();(r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'"))&&(r=r.slice(1,-1)),s in process.env||(process.env[s]=r)}var Co=yn(bn(import.meta.url));vo(bo(Lr(Co,"ts-resolve-hook.mjs")).href,import.meta.url);var xo=yn(bn(import.meta.url)),Po=Lr(xo,"..","..","package.json"),Ro=JSON.parse(vn(Po,"utf-8")),b=new Ke(Ro.version);b.register(ts);b.register(ss);b.register(We);b.register(Je);b.register(Ve);b.register(Qe);b.register(Ge);b.register(Ye);b.register(Ze);b.register(Xe);b.register(et);b.register(tt);b.register(dt);b.register(ut);b.register(st);b.register(rt);b.register(it);b.register(nt);b.register(at);b.register(ot);b.register(lt);b.register(ct);b.register(mt);b.register(pt);b.register(ht);b.register(gt);b.register(ft);b.register(yt);b.register(bt);b.register(Ct);b.register(Rt);b.register(St);b.register(Tt);b.register(Et);b.register(es);b.register(ns);b.register(as);b.register(os);async function So(){let{join:o}=await import("path"),{existsSync:e,readdirSync:t}=await import("fs"),{pathToFileURL:s}=await import("url"),r=o(process.cwd(),"src","lib","shared","commands");if(!e(r))return;let i=t(r).filter(n=>(n.endsWith(".ts")||n.endsWith(".js"))&&!n.startsWith("."));for(let n of i)try{let a=o(r,n),c=await import(s(a).href),d=c.default??Object.values(c).find(p=>typeof p=="function"&&p.prototype&&"handle"in p.prototype);d&&typeof d=="function"&&b.add(new d)}catch{}}So().then(()=>b.run());