@beeblock/svelar 0.5.1 → 0.6.1
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/README.md +5 -6
- package/dist/cli/bin.js +374 -846
- package/dist/cli/commands/NewCommandTemplates.d.ts +2 -10
- package/dist/cli/commands/UpdateCommand.d.ts +3 -0
- package/dist/cli/index.js +1 -1
- package/dist/plugins/PluginInstaller.js +1 -1
- package/package.json +2 -13
- package/src/ui/Seo.svelte +104 -0
- package/src/ui/index.ts +1 -0
- package/dist/stripe/Invoice.d.ts +0 -44
- package/dist/stripe/StripeService.d.ts +0 -52
- package/dist/stripe/StripeWebhookHandler.d.ts +0 -14
- package/dist/stripe/Subscription.d.ts +0 -40
- package/dist/stripe/SubscriptionManager.d.ts +0 -39
- package/dist/stripe/SubscriptionPlan.d.ts +0 -41
- package/dist/stripe/SyncStripeCustomerJob.d.ts +0 -11
- package/dist/stripe/index.d.ts +0 -22
- package/dist/stripe/index.js +0 -1
package/dist/cli/bin.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
2
|
+
var gn=Object.defineProperty;var Qe=(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 w=(l,e)=>()=>(l&&(e=l(l=0)),e);var M=(l,e)=>{for(var t in e)gn(l,t,{get:e[t],enumerable:!0})};function C(l,e){let t=Symbol.for(l),s=globalThis;return s[t]||(s[t]=e()),s[t]}var k=w(()=>{"use strict"});var S={};M(S,{Connection:()=>b});var ws,b,P=w(()=>{"use strict";k();ws=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(m=>typeof m=="boolean"?m?1:0:m instanceof Date?m.toISOString():m),o=n.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 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(o){let c=i.prepare(o);return{all(...m){return c.all(...m)},run(...m){return c.run(...m)},get(...m){return c.get(...m)}}},exec(o){i.exec(o)},pragma(o){return i.prepare(`PRAGMA ${o}`).all()},close(){i.close()}},a;try{let{drizzle:o}=await import("drizzle-orm/better-sqlite3");a=o(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{}}},b=C("svelar.connection",()=>new ws)});var H,Rs,ee,z,Xr,Ts=w(()=>{"use strict";P();k();H=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 Rs(this.column)}build(){return this.column}},Rs=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},ee=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 H(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 H(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 H(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 H(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 i of this.indices){let
|
|
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}},z=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new ee;t(s);let r=b.getDriver(this.connectionName),i=s.toSQL(e,r);for(let n of i)await b.raw(n,[],this.connectionName)}async dropTable(e){await b.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async dropTableIfExists(e){await b.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async renameTable(e,t){b.getDriver(this.connectionName)==="mysql"?await b.raw(`RENAME TABLE ${e} TO ${t}`,[],this.connectionName):await b.raw(`ALTER TABLE ${e} RENAME TO ${t}`,[],this.connectionName)}async hasTable(e){let t=b.getDriver(this.connectionName),s;switch(t){case"sqlite":s=await b.raw("SELECT name FROM sqlite_master WHERE type='table' AND name=?",[e],this.connectionName);break;case"postgres":s=await b.raw("SELECT tablename FROM pg_tables WHERE tablename = $1",[e],this.connectionName);break;case"mysql":s=await b.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 ee;t(s);let r=b.getDriver(this.connectionName),i=s.columns;for(let n of i){let a=s.columnToSQL(n,r);await b.raw(`ALTER TABLE ${e} ADD COLUMN ${a}`,[],this.connectionName)}}async dropColumn(e,t){await b.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},Xr=C("svelar.schema",()=>new z)});var ei={};M(ei,{Migration:()=>Te,Migrator:()=>ke});var Te,ke,ks=w(()=>{"use strict";P();Ts();Te=class{schema=new z},ke=class{migrationsTable="svelar_migrations";connectionName;constructor(e){this.connectionName=e}async ensureMigrationsTable(){let e=new z(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 b.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 b.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(o=>o.name===n);a&&(await a.migration.down(),await b.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=b.getDriver(this.connectionName),t=[];switch(e){case"sqlite":{t=(await b.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",[],this.connectionName)).map(r=>r.name),await b.raw("PRAGMA foreign_keys = OFF",[],this.connectionName);for(let r of t)await b.raw(`DROP TABLE IF EXISTS "${r}"`,[],this.connectionName);await b.raw("PRAGMA foreign_keys = ON",[],this.connectionName);break}case"mysql":{t=(await b.raw("SHOW TABLES",[],this.connectionName)).map(r=>Object.values(r)[0]),await b.raw("SET FOREIGN_KEY_CHECKS = 0",[],this.connectionName);for(let r of t)await b.raw(`DROP TABLE IF EXISTS \`${r}\``,[],this.connectionName);await b.raw("SET FOREIGN_KEY_CHECKS = 1",[],this.connectionName);break}case"postgres":{t=(await b.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'",[],this.connectionName)).map(r=>r.tablename);for(let r of t)await b.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 b.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 b.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 b.raw(`SELECT MAX(batch) as max_batch FROM ${this.migrationsTable}`,[],this.connectionName))[0]?.max_batch??0}catch{return 0}}}});var kt={};M(kt,{SchedulerLock:()=>$e});import{hostname as ao}from"os";async function Ee(){let{Connection:l}=await Promise.resolve().then(()=>(P(),S));return l}async function oo(){return(await Ee()).getDriver()}var ri,V,$e,Ae=w(()=>{"use strict";ri=!1,V=`${ao()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;$e=class{static getOwnerId(){return V}static async ensureTable(){if(ri)return;let e=await Ee();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 ha=Object.defineProperty;var Qe=(o=>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}
|
|
17
|
+
) ENGINE=InnoDB`);break}ri=!0}static async acquire(e,t=5){await this.ensureTable();let s=await Ee(),r=await oo(),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,V,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,V,n]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,V,n]);break}});let a=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return a.length>0&&a[0].owner===V}catch{return!1}}static async release(e){try{await(await Ee()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,V])}catch{}}static async releaseAll(){try{await(await Ee()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[V])}catch{}}}});var ni={};M(ni,{ScheduledTask:()=>Et,Scheduler:()=>As,SchedulerLock:()=>$e,cronMatches:()=>$s,parseCron:()=>ii,task:()=>lo});function De(l,e,t){if(l==="*")return null;let s=new Set;for(let r of l.split(",")){let[i,n]=r.split("/"),a=n?parseInt(n,10):1;if(i==="*")for(let o=e;o<=t;o+=a)s.add(o);else if(i.includes("-")){let[o,c]=i.split("-"),m=parseInt(o,10),p=parseInt(c,10);for(let h=m;h<=p;h+=a)s.add(h)}else s.add(parseInt(i,10))}return[...s].sort((r,i)=>r-i)}function ii(l){let e=l.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${l}". Expected 5 fields.`);return{minute:De(e[0],0,59),hour:De(e[1],0,23),dayOfMonth:De(e[2],1,31),month:De(e[3],1,12),dayOfWeek:De(e[4],0,6)}}function $s(l,e){let t=ii(l),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 lo(l,e,t){class s extends Et{name=l;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var Et,As,ai=w(()=>{"use strict";Ae();Et=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(()=>(Ae(),kt));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(()=>(Ae(),kt));await s.release(this.name)}catch{}}}},As=class{tasks=[];timer=null;history=[];maxHistory=100;_persistToDb=!1;persistToDatabase(){return this._persistToDb=!0,this}register(e){return this.tasks.push(e),this}registerMany(e){for(let t of e)this.register(t);return this}async run(e){let t=e??new Date,s=[];for(let r of this.tasks){let i=r.getExpression();if($s(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(()=>(Ae(),kt));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=>$s(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(()=>(P(),S));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 ha=Object.defineProperty;var Qe=(o=>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(()=>(
|
|
38
|
+
) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(P(),S));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 Le={};M(Le,{Job:()=>se,Queue:()=>js});var se,At,Ls,te,Dt,Ms,Ns,Is,_s,js,re=w(()=>{"use strict";k();se=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)}},At=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(){}},Ls=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()}},te=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(P(),S));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 i=r[0];await t.raw(`UPDATE ${this.table} SET reserved_at = ?, attempts = attempts + 1 WHERE id = ?`,[s,i.id]);let
|
|
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}},Ms=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)}},Ns=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new Ms;failedStore=new _s;_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 a={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(a)}async dispatchSync(e){let t=new At,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 Is(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 Dt){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 m=()=>{this.processing?setTimeout(m,500):l.close().then(c).catch(c)};m()}),0}let i=e?.maxJobs??1/0,a=(e?.sleep??1)*1e3,n=0;for(this.processing=!0;this.processing&&n<i;){let l=await s.pop(r);if(!l){if(i===1/0){await new Promise(c=>setTimeout(c,a));continue}break}l.attempts++,l.job.attempts=l.attempts;try{await l.job.handle(),n++,s instanceof Z&&await s.delete(l.id)}catch(c){if(l.attempts<l.maxAttempts){l.job.retrying(l.attempts);let m=l.job.retryDelay??60;s instanceof Z?await s.release(l.id,m):(l.availableAt=Date.now()+m*1e3,await s.push(l))}else l.job.failed(c),await this.failedStore.store(l,c),s instanceof Z&&await s.delete(l.id)}}return n}async stop(){this.processing=!1,this._activeWorker&&(await this._activeWorker.close(),this._activeWorker=null)}async size(e){return this.resolveDriver(this.config.default).size(e)}async clear(e){return this.resolveDriver(this.config.default).clear(e)}async failed(){return this.failedStore.all()}async retry(e){let t=await this.failedStore.find(e);if(!t)return!1;let s=this.jobRegistry.resolve(t.jobClass,t.payload);return s.queue=t.queue,await this.dispatch(s,{queue:t.queue}),await this.failedStore.forget(e),!0}async retryAll(){let e=await this.failedStore.all(),t=0;for(let s of e)try{let r=this.jobRegistry.resolve(s.jobClass,s.payload);r.queue=s.queue,await this.dispatch(r,{queue:s.queue}),await this.failedStore.forget(s.id),t++}catch{}return t}async forgetFailed(e){return this.failedStore.forget(e)}async flushFailed(){return this.failedStore.flush()}resolveDriver(e){if(this.drivers.has(e))return this.drivers.get(e);let t=this.config.connections[e];if(!t)throw new Error(`Queue connection "${e}" is not defined.`);let s;switch(t.driver){case"sync":s=new At;break;case"memory":s=new Ls;break;case"database":s=new Z(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Dt(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},Is=class extends X{remainingJobs;constructor(e){super(),this.remainingJobs=[...e],this.maxAttempts=1}async handle(){for(let e of this.remainingJobs){let t=null,s=!1;for(let r=1;r<=e.maxAttempts;r++){e.attempts=r;try{await e.handle(),s=!0;break}catch(i){t=i,r<e.maxAttempts&&(e.retrying(r),e.retryDelay>0&&await new Promise(a=>setTimeout(a,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()}))})}},js=P("svelar.queue",()=>new Ns)});var j,Os=x(()=>{"use strict";S();j=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(),a=r.replace(/^WHERE /,"");this.whereClauses.push({type:"raw",raw:`(${a})`,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:a}=r.toSQL();return this.whereClauses.push({type:"sub",column:e,operator:t,subSQL:i,subBindings:a,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:a}=r.toSQL();return this.cteClauses.push({name:e,sql:i,bindings:a,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 a=await i.get();if(a.length===0||await t(a,s)===!1||a.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),a=Object.values(e),n=a.map(()=>"?").join(", "),l=s??i.filter(m=>!t.includes(m)),c;if(r==="postgres"){let m=l.map(p=>`${p} = EXCLUDED.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${m}`}else if(r==="mysql"){let m=l.map(p=>`${p} = VALUES(${p})`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON DUPLICATE KEY UPDATE ${m}`}else{let m=l.map(p=>`${p} = excluded.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${n}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${m}`}return f.raw(c,a,this.connectionName)}async insertMany(e){if(e.length===0)return;let t=Object.keys(e[0]),s=[],r=[];for(let a of e){let n=t.map(l=>a[l]);s.push(...n),r.push(`(${n.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[a,n]of Object.entries(e))this.where(a,n);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[n,l]of Object.entries(e))s.where(n,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},a=await new o(this.tableName,this.modelClass,this.connectionName).insertGetId(i);return new o(this.tableName,this.modelClass,this.connectionName).findOrFail(a)}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(),a=`(${r}) as ${t}`;return this.selectColumns[0]==="*"?this.selectColumns=[a]:this.selectColumns.push(a),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),a=i.map(()=>"?").join(", "),n=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${a})`;return s==="postgres"?(n+=` RETURNING ${t}`,(await f.raw(n,i,this.connectionName))[0]?.[t]):(await f.raw(n,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:a}=this.buildWhere(),n=`UPDATE ${this.tableName} SET ${r}${i}`;return await f.raw(n,[...s,...a],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 n=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(`${n} ${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 a of this.joinClauses)a.type==="CROSS"?e.push(`CROSS JOIN ${a.table}`):e.push(`${a.type} JOIN ${a.table} ON ${a.first} ${a.operator} ${a.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 a=[];for(let n of this.havingClauses)n.type==="raw"?(a.push(n.raw),n.values&&t.push(...n.values)):(a.push(`${n.column} ${n.operator} ?`),t.push(n.value));e.push(`HAVING ${a.join(" AND ")}`)}if(this.orderClauses.length>0){let a=this.orderClauses.map(n=>n.__raw?n.column:`${n.column} ${n.direction.toUpperCase()}`);e.push(`ORDER BY ${a.join(", ")}`)}if(this.limitValue!==null&&e.push(`LIMIT ${this.limitValue}`),this.offsetValue!==null&&e.push(`OFFSET ${this.offsetValue}`),this.unionClauses.length>0)for(let a of this.unionClauses)e.push(a.all?"UNION ALL":"UNION"),e.push(a.sql),t.push(...a.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 a=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} IN (${a})`),t.push(...r.values);break;case"notIn":let n=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} NOT IN (${n})`),t.push(...r.values);break;case"null":e.push(`${i} ${r.column} IS NULL`);break;case"notNull":e.push(`${i} ${r.column} IS NOT NULL`);break;case"between":e.push(`${i} ${r.column} BETWEEN ? AND ?`),t.push(r.values[0],r.values[1]);break;case"raw":e.push(`${i} ${r.raw}`),r.values&&t.push(...r.values);break;case"exists":e.push(`${i} EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"notExists":e.push(`${i} NOT EXISTS (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break;case"sub":e.push(`${i} ${r.column} ${r.operator} (${r.subSQL})`),r.subBindings&&t.push(...r.subBindings);break}}return{whereSQL:e.join(" "),whereBindings:t}}buildAggregate(e){let t=this.selectColumns;this.selectColumns=[`${e} as aggregate`];let s=this.toSQL();return this.selectColumns=t,s}hydrateMany(e){return this.modelClass?e.map(t=>this.modelClass.hydrate(t)):e}async loadRelations(e){if(!(!this.modelClass||e.length===0))for(let t of this.eagerLoads){let r=new this.modelClass()[t]?.();r&&typeof r.eagerLoad=="function"&&await r.eagerLoad(e,t)}}}});var te,se,re,ie,ae,qs=x(()=>{"use strict";S();te=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},se=class extends te{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.localKey=i}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).first()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),a=new Map;for(let n of i)a.set(n.getAttribute(this.foreignKey),n);for(let n of t){let l=n.getAttribute(this.localKey);n.setRelation(s,a.get(l)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},re=class extends te{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.localKey=i}async load(t){let s=t.getAttribute(this.localKey);return this.relatedModel.query().where(this.foreignKey,s).get()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),a=new Map;for(let n of i){let l=n.getAttribute(this.foreignKey);a.has(l)||a.set(l,[]),a.get(l).push(n)}for(let n of t){let l=n.getAttribute(this.localKey);n.setRelation(s,a.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}},ie=class extends te{constructor(t,s,r,i="id"){super(t,s);this.foreignKey=r;this.ownerKey=i}async load(t){let s=t.getAttribute(this.foreignKey);return s==null?null:this.relatedModel.query().where(this.ownerKey,s).first()}async eagerLoad(t,s){let r=t.map(n=>n.getAttribute(this.foreignKey)).filter(n=>n!=null);if(r.length===0){for(let n of t)n.setRelation(s,null);return}let i=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),a=new Map;for(let n of i)a.set(n.getAttribute(this.ownerKey),n);for(let n of t){let l=n.getAttribute(this.foreignKey);n.setRelation(s,a.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}},ae=class extends te{constructor(t,s,r,i,a,n="id",l="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=i;this.relatedPivotKey=a;this.parentKey=n;this.relatedKey=l}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,a=(await f.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(n=>n[this.relatedPivotKey]);return a.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,a).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(", "),a=await f.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${i})`,r),n=[...new Set(a.map(p=>p[this.relatedPivotKey]))],l=n.length>0?await this.relatedModel.query().whereIn(this.relatedKey,n).get():[],c=new Map;for(let p of l)c.set(p.getAttribute(this.relatedKey),p);let m=new Map;for(let p of a){let h=p[this.foreignPivotKey],u=p[this.relatedPivotKey],b=c.get(u);b&&(m.has(h)||m.set(h,[]),m.get(h).push(b))}for(let p of t){let h=p.getAttribute(this.parentKey);p.setRelation(s,m.get(h)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),i={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},a=Object.keys(i),n=Object.values(i),l=n.map(()=>"?").join(", ");await f.raw(`INSERT INTO ${this.pivotTable} (${a.join(", ")}) VALUES (${l})`,n)}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 li=x(()=>{"use strict"});var _e,Us=x(()=>{"use strict";_e=class{app;constructor(e){this.app=e}boot(){}}});var ci=x(()=>{"use strict";Us();It()});var Me,ne,It=x(()=>{"use strict";E();li();ci();Me=class{listeners=new Map;wildcardListeners=[];onceListeners=new Map;listen(e,t){let s=typeof e=="string"?e:e.name;return this.listeners.has(s)||this.listeners.set(s,[]),this.listeners.get(s).push(t),()=>{let r=this.listeners.get(s);if(r){let i=r.indexOf(t);i>=0&&r.splice(i,1)}}}once(e,t){let s=typeof e=="string"?e:e.name;return this.onceListeners.has(s)||this.onceListeners.set(s,[]),this.onceListeners.get(s).push(t),()=>{let r=this.onceListeners.get(s);if(r){let i=r.indexOf(t);i>=0&&r.splice(i,1)}}}onAny(e){return this.wildcardListeners.push(e),()=>{let t=this.wildcardListeners.indexOf(e);t>=0&&this.wildcardListeners.splice(t,1)}}async dispatch(e){let t=e.constructor.name,s=this.listeners.get(t)??[];for(let i of s)await i(e);let r=this.onceListeners.get(t)??[];for(let i of r)await i(e);this.onceListeners.delete(t);for(let i of this.wildcardListeners)await i(t,e)}async emit(e,t){let s=this.listeners.get(e)??[];for(let i of s)await i(t);let r=this.onceListeners.get(e)??[];for(let i of r)await i(t);this.onceListeners.delete(e);for(let i of this.wildcardListeners)await i(e,t)}subscribe(e){e.subscribe(this)}forget(e){let t=typeof e=="string"?e:e.name;this.listeners.delete(t),this.onceListeners.delete(t)}flush(){this.listeners.clear(),this.onceListeners.clear(),this.wildcardListeners=[]}hasListeners(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)>0||(this.onceListeners.get(t)?.length??0)>0||this.wildcardListeners.length>0}listenerCount(e){let t=typeof e=="string"?e:e.name;return(this.listeners.get(t)?.length??0)+(this.onceListeners.get(t)?.length??0)}},ne=P("svelar.event",()=>new Me)});var jt,di=x(()=>{"use strict";Os();qs();It();jt=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 j(t.table,this,t.connection)}static async find(e){let t=this;return this.query().find(e,t.primaryKey)}static async findOrFail(e){let t=this;return this.query().findOrFail(e,t.primaryKey)}static async all(){return this.query().get()}static async first(){return this.query().first()}static async firstOrFail(){return this.query().firstOrFail()}static where(e,t,s){return this.query().where(e,t,s)}static whereIn(e,t){return this.query().whereIn(e,t)}static whereNull(e){return this.query().whereNull(e)}static whereNotNull(e){return this.query().whereNotNull(e)}static orderBy(e,t){return this.query().orderBy(e,t)}static latest(e){return this.query().latest(e)}static oldest(e){return this.query().oldest(e)}static with(...e){return this.query().with(...e)}static async count(){return this.query().count()}static async create(e){let t=new this,s=this;if(t.fill(e),await t.fireHook("creating"),await t.fireHook("saving"),s.timestamps){let n=new Date().toISOString();t.setAttribute(s.createdAt,n),t.setAttribute(s.updatedAt,n)}let r=t.getInsertableAttributes(),a=await new j(s.table,this,s.connection).insertGetId(r,s.primaryKey);return s.incrementing&&a&&t.setAttribute(s.primaryKey,a),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 j(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 j(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 j(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 se(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new re(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new ie(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,i,a){return new ae(this,e,t,s,r,i??this.constructor.primaryKey,a??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 a of r){let n=a[e];typeof n=="function"&&await n.call(a,this)}let i=t.name.toLowerCase();await ne.emit(`${i}.${e}`,this)}async fireEvent(e){let t=this.constructor;if(!t.events.includes(e))throw new Error(`Event "${e}" is not declared in ${t.name}.events. Add it to: static events = ['${e}', ...];`);let s=o.observers.get(t.name)??[];for(let i of s){let a=i[e];typeof a=="function"&&await a.call(i,this)}let r=t.name.toLowerCase();await ne.emit(`${r}.${e}`,this)}syncOriginal(){this.originalAttributes={...this.attributes}}getInsertableAttributes(){let e=this.constructor,t={...this.attributes};return e.incrementing&&t[e.primaryKey]===void 0&&delete t[e.primaryKey],t}static get tableName(){return this.table}}});var Ot,ui=x(()=>{"use strict";Ot=class{async call(e){await new e().run()}}});var J,mi,Fs=x(()=>{"use strict";E();J=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}},mi=P("svelar.container",()=>new J)});var qt,pi=x(()=>{"use strict";Fs();qt=class{container;providers=[];booted=!1;constructor(e){this.container=e??new J,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 $,H,Ut,oe,Ft,le,ce,Bt,de,ue=x(()=>{"use strict";$=class{},H=class{middleware=[];namedMiddleware=new Map;use(e){return typeof e=="function"&&"prototype"in e&&typeof e.prototype?.handle=="function"?this.middleware.push(new e):this.middleware.push(e),this}register(e,t){return typeof t=="function"&&"prototype"in t&&typeof t.prototype?.handle=="function"?this.namedMiddleware.set(e,new t):this.namedMiddleware.set(e,t),this}get(e){return this.namedMiddleware.get(e)}async execute(e,t,s){let r=[...this.middleware];if(s)for(let a of s){let n=this.namedMiddleware.get(a);n&&r.push(n)}let i=t;for(let a=r.length-1;a>=0;a--){let n=r[a],l=i;typeof n.handle=="function"?i=()=>n.handle(e,l):i=()=>n(e,l)}return i()}count(){return this.middleware.length}},Ut=class extends ${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}},oe=class extends ${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()}},Ft=class extends ${async handle(e,t){let s=Date.now(),r=e.event.request.method,i=e.event.url.pathname,a=await t(),n=Date.now()-s,l=a instanceof Response?a.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${i} \u2192 ${l} (${n}ms)`),a}},le=class extends ${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 a=s.url.pathname;if(this.onlyPaths&&!this.onlyPaths.some(c=>a.startsWith(c)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(c=>a.startsWith(c)))return t();let n=this.getCookieToken(s),l=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!n||!l||!this.timingSafeEqual(n,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),a=0;for(let n=0;n<r.length;n++)a|=r[n]^i[n];return a===0}},ce=class extends ${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 a=s.request.headers.get("origin");if(!a)return t();let n=s.url.origin;return a===n||this.allowedOrigins.has(a)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},Bt=class extends ${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 v=s.url.pathname;if(!this.onlyPaths.some(y=>v.startsWith(y)))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 a=parseInt(i,10),n=Math.floor(Date.now()/1e3);if(isNaN(a)||Math.abs(n-a)>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:m}=await import("crypto"),p=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,u=`${i}.${p}.${h}.${c}`,b=m("sha256",this.secret).update(u).digest("hex");return r.length!==b.length||!this.timingSafeCompare(r,b)?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),a=0;for(let n=0;n<r.length;n++)a|=r[n]^i[n];return a===0}static sign(e,t,s,r,i){let{createHmac:a}=Qe("crypto"),n=i??Math.floor(Date.now()/1e3),l=`${n}.${t.toUpperCase()}.${s}.${r}`;return{signature:a("sha256",e).update(l).digest("hex"),timestamp:n}}},de=class extends ${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(),a=this.attempts.get(r);if(a){if(i<a.blockedUntil){let l=Math.ceil((a.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(a.count>=this.maxAttempts){a.blockedUntil=i+this.decayMinutes*6e4,a.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 n=await t();if(n instanceof Response&&n.status>=400&&n.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,m]of this.attempts)i>m.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(c)}return n}}});import{z as me}from"zod";function hi(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 Ht,z,Ne,Ie,je,gi=x(()=>{"use strict";ue();Ht=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof $?s=new e:s=e,this.controllerMiddleware.push({middleware:s,only:t?.only,except:t?.except})}handle(e){return async t=>{try{let s=this.controllerMiddleware.filter(r=>!(r.only&&!r.only.includes(e)||r.except&&r.except.includes(e)));if(s.length>0){let r=new H;for(let{middleware:n}of s)r.use(n);let i={event:t,params:t.params,locals:t.locals},a=await r.execute(i,async()=>this.callMethod(e,t));if(a instanceof Response)return a}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 me.ZodObject?t:me.object(t),r,i=e.request.headers.get("content-type")??"";if(i.includes("application/json"))r=await e.request.json();else if(i.includes("multipart/form-data")||i.includes("application/x-www-form-urlencoded")){let n=await e.request.formData();r=Object.fromEntries(n)}else r=Object.fromEntries(e.url.searchParams);let a=s.safeParse(r);if(!a.success)throw new z(a.error);return a.data}validateQuery(e,t){let s=t instanceof me.ZodObject?t:me.object(t),r=Object.fromEntries(e.url.searchParams),i=s.safeParse(r);if(!i.success)throw new z(i.error);return i.data}validateParams(e,t){let r=(t instanceof me.ZodObject?t:me.object(t)).safeParse(e.params);if(!r.success)throw new z(r.error);return r.data}handleError(e,t){return e instanceof z?this.json({message:"Validation failed",errors:e.errors},422):e instanceof Ne?this.json({message:e.message||"Not found"},404):e instanceof Ie?this.json({message:e.message||"Unauthorized"},401):e instanceof je?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)}};z=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)}}},Ne=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},Ie=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},je=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as po,createHmac as fi,timingSafeEqual as ho}from"crypto";import{promises as K}from"fs";import{join as Oe}from"path";var pe,qe,V,zt,Kt,Wt,he,Bs=x(()=>{"use strict";ue();pe=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=qe.get(e);return s instanceof V&&s.markOldSessionId(e),qe.delete(e),t}static generateId(){return po(32).toString("hex")}},qe=new Map,V=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}),qe.set(e,this)}async destroy(e){this.sessions.delete(e),qe.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),qe.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},zt=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(()=>(S(),R));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])}},Dt=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",o=new i.Worker(e,async c=>{let m=c.data,p=t.resolve(m.jobClass,m.payload);p.attempts=c.attemptsMade+1,await p.handle()},{connection:n,prefix:a,concurrency:r?.concurrency??1});return o.on("failed",async(c,m)=>{let p=c?.data;if(p)try{let h=t.resolve(p.jobClass,p.payload);c.attemptsMade>=(c.opts?.attempts??3)&&(h.failed(m),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},m))}catch{console.error("[Queue] Failed to resolve job for failure handler:",m.message)}}),o}},Ms=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(P(),S));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}},Ns=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)}},Is=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new Ns;failedStore=new Ms;_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 At,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 _s(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 Dt){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 m=()=>{this.processing?setTimeout(m,500):o.close().then(c).catch(c)};m()}),0}let i=e?.maxJobs??1/0,n=(e?.sleep??1)*1e3,a=0;for(this.processing=!0;this.processing&&a<i;){let o=await s.pop(r);if(!o){if(i===1/0){await new Promise(c=>setTimeout(c,n));continue}break}o.attempts++,o.job.attempts=o.attempts;try{await o.job.handle(),a++,s instanceof te&&await s.delete(o.id)}catch(c){if(o.attempts<o.maxAttempts){o.job.retrying(o.attempts);let m=o.job.retryDelay??60;s instanceof te?await s.release(o.id,m):(o.availableAt=Date.now()+m*1e3,await s.push(o))}else o.job.failed(c),await this.failedStore.store(o,c),s instanceof te&&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 At;break;case"memory":s=new Ls;break;case"database":s=new te(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Dt(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},_s=class extends se{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()}))})}},js=C("svelar.queue",()=>new Is)});var O,Os=w(()=>{"use strict";P();O=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: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 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: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 l("__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 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 b.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 b.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 b.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 b.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 b.raw(t,s,this.connectionName))[0]?.aggregate??null}async min(e){let{sql:t,bindings:s}=this.buildAggregate(`MIN(${e})`);return(await b.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 b.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName)).map(s=>s[e])}async value(e){return this.selectColumns=[e],this.limitValue=1,(await b.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=b.getDriver(this.connectionName),i=Object.keys(e),n=Object.values(e),a=n.map(()=>"?").join(", "),o=s??i.filter(m=>!t.includes(m)),c;if(r==="postgres"){let m=o.map(p=>`${p} = EXCLUDED.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${m}`}else if(r==="mysql"){let m=o.map(p=>`${p} = VALUES(${p})`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON DUPLICATE KEY UPDATE ${m}`}else{let m=o.map(p=>`${p} = excluded.${p}`).join(", ");c=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${a}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${m}`}return b.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(o=>n[o]);s.push(...a),r.push(`(${a.map(()=>"?").join(", ")})`)}let i=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES ${r.join(", ")}`;return b.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 l(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new l(this.tableName,this.modelClass,this.connectionName).findOrFail(i)}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 i={...e,...t},n=await new l(this.tableName,this.modelClass,this.connectionName).insertGetId(i);return new l(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 l("__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(){b.getDriver(this.connectionName)==="sqlite"?(await b.raw(`DELETE FROM ${this.tableName}`,[],this.connectionName),await b.raw("DELETE FROM sqlite_sequence WHERE name = ?",[this.tableName],this.connectionName)):await b.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 b.raw(i,s,this.connectionName)}async insertGetId(e,t="id"){let s=b.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 b.raw(a,i,this.connectionName))[0]?.[t]):(await b.raw(a,i,this.connectionName),s==="sqlite"?(await b.raw("SELECT last_insert_rowid() as id",[],this.connectionName))[0]?.id:s==="mysql"?(await b.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:i,whereBindings:n}=this.buildWhere(),a=`UPDATE ${this.tableName} SET ${r}${i}`;return await b.raw(a,[...s,...n],this.connectionName),1}async delete(){let{whereSQL:e,whereBindings:t}=this.buildWhere(),s=`DELETE FROM ${this.tableName}${e}`;return await b.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 b.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",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 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 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],i=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(`${i} ${r.column} ${r.operator} ${o}`)}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 ie,ne,ae,oe,le,qs=w(()=>{"use strict";P();ie=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},ne=class extends ie{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 o=a.getAttribute(this.localKey);a.setRelation(s,n.get(o)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},ae=class extends ie{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 o=a.getAttribute(this.foreignKey);n.has(o)||n.set(o,[]),n.get(o).push(a)}for(let a of t){let o=a.getAttribute(this.localKey);a.setRelation(s,n.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}},oe=class extends ie{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 o=a.getAttribute(this.foreignKey);a.setRelation(s,n.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}},le=class extends ie{constructor(t,s,r,i,n,a="id",o="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=i;this.relatedPivotKey=n;this.parentKey=a;this.relatedKey=o}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,n=(await b.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 b.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${i})`,r),a=[...new Set(n.map(p=>p[this.relatedPivotKey]))],o=a.length>0?await this.relatedModel.query().whereIn(this.relatedKey,a).get():[],c=new Map;for(let p of o)c.set(p.getAttribute(this.relatedKey),p);let m=new Map;for(let p of n){let h=p[this.foreignPivotKey],u=p[this.relatedPivotKey],f=c.get(u);f&&(m.has(h)||m.set(h,[]),m.get(h).push(f))}for(let p of t){let h=p.getAttribute(this.parentKey);p.setRelation(s,m.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),o=a.map(()=>"?").join(", ");await b.raw(`INSERT INTO ${this.pivotTable} (${n.join(", ")}) VALUES (${o})`,a)}async detach(t){let s=this.parentModel.getAttribute(this.parentKey);t?await b.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ?`,[s,t]):await b.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 b.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 oi=w(()=>{"use strict"});var Me,Us=w(()=>{"use strict";Me=class{app;constructor(e){this.app=e}boot(){}}});var li=w(()=>{"use strict";Us();_t()});var Ne,ce,_t=w(()=>{"use strict";k();oi();li();Ne=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)}},ce=C("svelar.event",()=>new Ne)});var jt,ci=w(()=>{"use strict";Os();qs();_t();jt=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 O(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 O(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 O(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 O(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 O(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 ne(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new ae(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new oe(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,i,n){return new le(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 l?i.toJSON():i):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 n of r){let a=n[e];typeof a=="function"&&await a.call(n,this)}let i=t.name.toLowerCase();await ce.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=l.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 ce.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 Ot,di=w(()=>{"use strict";Ot=class{async call(e){await new e().run()}}});var Q,ui,Fs=w(()=>{"use strict";k();Q=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}},ui=C("svelar.container",()=>new Q)});var qt,mi=w(()=>{"use strict";Fs();qt=class{container;providers=[];booted=!1;constructor(e){this.container=e??new Q,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 E,K,Ut,de,Ft,ue,me,Bt,pe,he=w(()=>{"use strict";E=class{},K=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],o=i;typeof a.handle=="function"?i=()=>a.handle(e,o):i=()=>a(e,o)}return i()}count(){return this.middleware.length}},Ut=class extends E{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}},de=class extends E{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()}},Ft=class extends E{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,o=n instanceof Response?n.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${i} \u2192 ${o} (${a}ms)`),n}},ue=class extends E{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),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 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}},me=class extends E{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"}})}},Bt=class extends E{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 v=s.url.pathname;if(!this.onlyPaths.some(x=>v.startsWith(x)))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:m}=await import("crypto"),p=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,u=`${i}.${p}.${h}.${c}`,f=m("sha256",this.secret).update(u).digest("hex");return r.length!==f.length||!this.timingSafeCompare(r,f)?new Response(JSON.stringify({message:"Invalid request signature"}),{status:401,headers:{"Content-Type":"application/json"}}):t()}timingSafeCompare(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),i=s.encode(t),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}=Qe("crypto"),a=i??Math.floor(Date.now()/1e3),o=`${a}.${t.toUpperCase()}.${s}.${r}`;return{signature:n("sha256",e).update(o).digest("hex"),timestamp:a}}},pe=class extends E{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 o=Math.ceil((n.blockedUntil-i)/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(n.count>=this.maxAttempts){n.blockedUntil=i+this.decayMinutes*6e4,n.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,m]of this.attempts)i>m.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(c)}return a}}});import{z as ge}from"zod";function pi(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 Ht,W,Ie,_e,je,hi=w(()=>{"use strict";he();Ht=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof E?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 K;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 ge.ZodObject?t:ge.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 W(n.error);return n.data}validateQuery(e,t){let s=t instanceof ge.ZodObject?t:ge.object(t),r=Object.fromEntries(e.url.searchParams),i=s.safeParse(r);if(!i.success)throw new W(i.error);return i.data}validateParams(e,t){let r=(t instanceof ge.ZodObject?t:ge.object(t)).safeParse(e.params);if(!r.success)throw new W(r.error);return r.data}handleError(e,t){return e instanceof W?this.json({message:"Validation failed",errors:e.errors},422):e instanceof Ie?this.json({message:e.message||"Not found"},404):e instanceof _e?this.json({message:e.message||"Unauthorized"},401):e instanceof je?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)}};W=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)}}},Ie=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},_e=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},je=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as po,createHmac as gi,timingSafeEqual as ho}from"crypto";import{promises as J}from"fs";import{join as Oe}from"path";var fe,qe,G,zt,Kt,Wt,be,Bs=w(()=>{"use strict";he();fe=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=qe.get(e);return s instanceof G&&s.markOldSessionId(e),qe.delete(e),t}static generateId(){return po(32).toString("hex")}},qe=new Map,G=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}),qe.set(e,this)}async destroy(e){this.sessions.delete(e),qe.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),qe.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},zt=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(()=>(P(),S));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 ha=Object.defineProperty;var Qe=(o=>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(()=>(
|
|
55
|
-
ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,i,
|
|
56
|
-
ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,i,
|
|
57
|
-
ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,i,
|
|
54
|
+
) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(P(),S)),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(()=>(P(),S)),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(()=>(P(),S));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(P(),S));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},Kt=class{dir;constructor(e){this.dir=e??Oe(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return Oe(this.dir,`${t}.json`)}async ensureDir(){await J.mkdir(this.dir,{recursive:!0})}async read(e){try{let t=await J.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 J.writeFile(this.filePath(e),JSON.stringify(r),"utf-8")}async destroy(e){try{await J.unlink(this.filePath(e))}catch{}}async gc(e){try{let t=await J.readdir(this.dir),s=new Date;for(let r of t)if(r.endsWith(".json"))try{let i=await J.readFile(Oe(this.dir,r),"utf-8"),n=JSON.parse(i);new Date(n.expiresAt)<s&&await J.unlink(Oe(this.dir,r))}catch{await J.unlink(Oe(this.dir,r)).catch(()=>{})}}catch{}}},Wt=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){}},be=class extends E{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 o=this.verifySignedId(r);o?(i=await this.config.store.read(o),r=o):r=null}r||(r=fe.generateId());let n=new fe(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 o=this.signId(n.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,...i]=s.split("=");if(r===this.config.cookieName)return decodeURIComponent(i.join("="))}return null}signId(e){let t=gi("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=gi("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(ho(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 Ue={};M(Ue,{Hash:()=>Ks});import{randomBytes as Hs,scrypt as fi,timingSafeEqual as go}from"crypto";async function fo(l,e=16384){let t=Hs(16),s=64,r=await new Promise((i,n)=>{fi(l,t,s,{N:e,r:8,p:1},(a,o)=>{a?n(a):i(o)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function bo(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"),i=Buffer.from(t[4],"base64"),n=i.length,a=await new Promise((o,c)=>{fi(l,r,n,{N:s,r:8,p:1},(m,p)=>{m?c(m):o(p)})});return go(a,i)}var zs,Ks,ve=w(()=>{"use strict";k();zs=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 fo(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 bo(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 Hs(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return Hs(e).toString("base64url")}},Ks=C("svelar.hash",()=>new zs)});var bi={};M(bi,{EmailTemplates:()=>vo});import{randomUUID as U}from"crypto";var Ws,vo,vi=w(()=>{"use strict";k();Ws=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:U(),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(()=>(P(),S));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:U(),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:
|
|
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:U(),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:
|
|
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:U(),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:
|
|
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:U(),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:
|
|
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:U(),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:
|
|
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:U(),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:
|
|
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:U(),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,27 +104,27 @@ 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:
|
|
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:U(),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,i,a)=>this.getNestedValue(t,i)?a:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,i,a)=>{let n=this.getNestedValue(t,i);return Array.isArray(n)?n.map((l,c)=>{let m={...t,this:l,$index:c};return this.interpolate(a,m)}).join(""):""}),s=s.replace(/\{\{([\w.$]+)\}\}/g,(r,i)=>{let a=this.getNestedValue(t,i);return a!=null?String(a):""}),s}getNestedValue(e,t){return t.split(".").reduce((s,r)=>s?.[r],e)}},yo=P("svelar.emailTemplates",()=>new Ws)});var er={};L(er,{Mailable:()=>Fe,Mailer:()=>Xs});function Zs(o){return typeof o=="string"?o:`${o.name} <${o.address}>`}function M(o){return o?Array.isArray(o)?o:[o]:[]}function wi(o){return Buffer.isBuffer(o)?o.toString("base64"):Buffer.from(o).toString("base64")}var Jt,Js,Vs,Qs,Gs,Fe,Ys,Xs,Vt=x(()=>{"use strict";E();Jt=class{async send(e){let t=M(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:M(e.to),rejected:[]}}},Vs=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?Zs(e.from):void 0,to:M(e.to).join(", "),cc:M(e.cc).join(", ")||void 0,bcc:M(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}}},Qs=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=M(e.to),r=M(e.cc),i=M(e.bcc),a={From:e.from?Zs(e.from):void 0,To:s.join(", "),Subject:e.subject,MessageStream:this.config.messageStream||"outbound"};r.length>0&&(a.Cc=r.join(", ")),i.length>0&&(a.Bcc=i.join(", ")),e.replyTo&&(a.ReplyTo=e.replyTo),e.html&&(a.HtmlBody=e.html),e.text&&(a.TextBody=e.text),!a.HtmlBody&&!a.TextBody&&(a.TextBody=""),e.tags&&(a.Tag=Object.values(e.tags)[0]),e.attachments?.length&&(a.Attachments=e.attachments.map(c=>({Name:c.filename,Content:wi(c.content),ContentType:c.contentType||"application/octet-stream"})));let n=await fetch("https://api.postmarkapp.com/email",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","X-Postmark-Server-Token":t},body:JSON.stringify(a)});if(!n.ok){let c=await n.json().catch(()=>({Message:n.statusText}));throw new Error(`Postmark error ${n.status}: ${c.Message||JSON.stringify(c)}`)}let l=await n.json();return{accepted:s,rejected:[],messageId:l.MessageID}}},Gs=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=M(e.to),r=M(e.cc),i=M(e.bcc),a={from:e.from?Zs(e.from):void 0,to:s,subject:e.subject};r.length>0&&(a.cc=r),i.length>0&&(a.bcc=i),e.replyTo&&(a.reply_to=[e.replyTo]),e.html&&(a.html=e.html),e.text&&(a.text=e.text),e.tags&&(a.tags=Object.entries(e.tags).map(([c,m])=>({name:c,value:m}))),e.attachments?.length&&(a.attachments=e.attachments.map(c=>({filename:c.filename,content:wi(c.content),content_type:c.contentType||"application/octet-stream"})));let n=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(a)});if(!n.ok){let c=await n.json().catch(()=>({message:n.statusText}));throw new Error(`Resend error ${n.status}: ${c.message||JSON.stringify(c)}`)}let l=await n.json();return{accepted:s,rejected:[],messageId:l.id}}},Fe=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}},Ys=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 Jt;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 Vs(s);break;case"postmark":r=new Qs(s);break;case"resend":r=new Gs(s);break;case"log":r=new Jt;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}},Xs=P("svelar.mail",()=>new Ys)});import{createHmac as fe,randomBytes as Be}from"crypto";function Ci(o){return(typeof o=="string"?Buffer.from(o):o).toString("base64url")}function xi(o){return Buffer.from(o,"base64url").toString("utf-8")}function Pi(o,e,t,s){return fe(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${o}.${e}`).digest("base64url")}function tr(o,e,t="HS256"){let s=Ci(JSON.stringify({alg:t,typ:"JWT"})),r=Ci(JSON.stringify(o)),i=Pi(s,r,e,t);return`${s}.${r}.${i}`}function sr(o,e){let t=o.split(".");if(t.length!==3)return null;let[s,r,i]=t,a;try{a=JSON.parse(xi(s))}catch{return null}let n=Pi(s,r,e,a.alg);if(i!==n)return null;try{let l=JSON.parse(xi(r));return l.exp&&Date.now()/1e3>l.exp?null:l}catch{return null}}var Qt,be,Gt,rr=x(()=>{"use strict";ue();Qt=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(ge(),Ue)),r=e[this.config.identifierColumn],i=e[this.config.passwordColumn];if(!r||!i)return null;let a=await this.config.model.where(this.config.identifierColumn,r).first();if(!a)return null;let n=a.getAttribute(this.config.passwordColumn);return await s.verify(i,n)?(this.currentUser=a,t&&(t.set("auth_user_id",a.getAttribute("id")),t.regenerateId()),a):null}async attemptJwt(e){let{Hash:t}=await Promise.resolve().then(()=>(ge(),Ue));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 a=i.getAttribute(this.config.passwordColumn);return await t.verify(r,a)?(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}:{}},a=tr(i,t.secret,t.algorithm),n=new Date((r+s)*1e3),l={user:e,token:a,expiresAt:n};if(t.refreshTokens){let c=t.refreshExpiresIn??604800,m=Be(32).toString("base64url"),p=fe("sha256",t.secret).update(m).digest("hex"),h=new Date((r+c)*1e3),{Connection:u}=await Promise.resolve().then(()=>(S(),R)),b=t.refreshTable??"refresh_tokens";await u.raw(`INSERT INTO ${b} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),p,h.toISOString(),new Date().toISOString()]),l.refreshToken=m,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=fe("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(S(),R)),i=t.refreshTable??"refresh_tokens",a=await r.raw(`SELECT user_id, expires_at, revoked_at FROM ${i} WHERE token = ?`,[s]);if(a.length===0)return null;let n=a[0];if(n.revoked_at||new Date(n.expires_at)<new Date)return null;await r.raw(`UPDATE ${i} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let l=await this.config.model.find(n.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(()=>(S(),R)),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=sr(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(()=>(ge(),Ue));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=Be(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=fe("sha256",r).update(s).digest("hex"),{Connection:a}=await Promise.resolve().then(()=>(S(),R)),n=this.config.token?.table??"personal_access_tokens";return await a.raw(`INSERT INTO ${n} (user_id, name, token, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),t,i,new Date().toISOString()]),s}async resolveFromApiToken(e){let{Connection:t}=await Promise.resolve().then(()=>(S(),R)),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=fe("sha256",r).update(e).digest("hex"),a=await t.raw(`SELECT user_id FROM ${s} WHERE token = ?`,[i]);if(a.length===0)return null;let n=await this.config.model.find(a[0].user_id);return n&&(this.currentUser=n),n}async sendPasswordReset(e){let t=await this.config.model.where(this.config.identifierColumn,e).first();if(!t)return!1;let{Connection:s}=await Promise.resolve().then(()=>(S(),R)),r=this.config.passwordResets?.table??"password_resets",i=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((o,c)=>{let m={...t,this:o,$index:c};return this.interpolate(n,m)}).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)}},vo=C("svelar.emailTemplates",()=>new Ws)});var er={};M(er,{Mailable:()=>Fe,Mailer:()=>Xs});function Zs(l){return typeof l=="string"?l:`${l.name} <${l.address}>`}function _(l){return l?Array.isArray(l)?l:[l]:[]}function yi(l){return Buffer.isBuffer(l)?l.toString("base64"):Buffer.from(l).toString("base64")}var Jt,Js,Vs,Qs,Gs,Fe,Ys,Xs,Vt=w(()=>{"use strict";k();Jt=class{async send(e){let t=_(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:_(e.to),rejected:[]}}},Vs=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?Zs(e.from):void 0,to:_(e.to).join(", "),cc:_(e.cc).join(", ")||void 0,bcc:_(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}}},Qs=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=_(e.to),r=_(e.cc),i=_(e.bcc),n={From:e.from?Zs(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:yi(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 o=await a.json();return{accepted:s,rejected:[],messageId:o.MessageID}}},Gs=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=_(e.to),r=_(e.cc),i=_(e.bcc),n={from:e.from?Zs(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,m])=>({name:c,value:m}))),e.attachments?.length&&(n.attachments=e.attachments.map(c=>({filename:c.filename,content:yi(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 o=await a.json();return{accepted:s,rejected:[],messageId:o.id}}},Fe=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}},Ys=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 Jt;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 Vs(s);break;case"postmark":r=new Qs(s);break;case"resend":r=new Gs(s);break;case"log":r=new Jt;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}},Xs=C("svelar.mail",()=>new Ys)});import{createHmac as ye,randomBytes as Be}from"crypto";function wi(l){return(typeof l=="string"?Buffer.from(l):l).toString("base64url")}function Ci(l){return Buffer.from(l,"base64url").toString("utf-8")}function xi(l,e,t,s){return ye(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${l}.${e}`).digest("base64url")}function tr(l,e,t="HS256"){let s=wi(JSON.stringify({alg:t,typ:"JWT"})),r=wi(JSON.stringify(l)),i=xi(s,r,e,t);return`${s}.${r}.${i}`}function sr(l,e){let t=l.split(".");if(t.length!==3)return null;let[s,r,i]=t,n;try{n=JSON.parse(Ci(s))}catch{return null}let a=xi(s,r,e,n.alg);if(i!==a)return null;try{let o=JSON.parse(Ci(r));return o.exp&&Date.now()/1e3>o.exp?null:o}catch{return null}}var Qt,we,Gt,rr=w(()=>{"use strict";he();Qt=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(ve(),Ue)),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(()=>(ve(),Ue));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=tr(i,t.secret,t.algorithm),a=new Date((r+s)*1e3),o={user:e,token:n,expiresAt:a};if(t.refreshTokens){let c=t.refreshExpiresIn??604800,m=Be(32).toString("base64url"),p=ye("sha256",t.secret).update(m).digest("hex"),h=new Date((r+c)*1e3),{Connection:u}=await Promise.resolve().then(()=>(P(),S)),f=t.refreshTable??"refresh_tokens";await u.raw(`INSERT INTO ${f} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),p,h.toISOString(),new Date().toISOString()]),o.refreshToken=m,o.refreshExpiresAt=h}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=ye("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(P(),S)),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 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(()=>(P(),S)),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=sr(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(()=>(ve(),Ue));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=Be(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=ye("sha256",r).update(s).digest("hex"),{Connection:n}=await Promise.resolve().then(()=>(P(),S)),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(()=>(P(),S)),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=ye("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(()=>(P(),S)),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
|
|
120
|
+
`),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let n=Be(32).toString("base64url"),a=this.hashToken(n),o=new Date(Date.now()+i*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",m=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:m,"user.name":t.getAttribute("name")??e,resetUrl:p}),!0}async resetPassword(e,t,s){let{Connection:r}=await Promise.resolve().then(()=>(P(),S)),{Hash:i}=await Promise.resolve().then(()=>(ve(),Ue)),n=this.config.passwordResets?.table??"password_resets",a=this.hashToken(e),o=await r.raw(`SELECT email, expires_at FROM ${n} 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 ${n} WHERE email = ?`,[t]),!1;let m=await this.config.model.where(this.config.identifierColumn,t).first();if(!m)return!1;let p=await i.make(s);return await this.config.model.where("id",m.getAttribute("id")).update({[this.config.passwordColumn]:p}),await r.raw(`DELETE FROM ${n} WHERE email = ?`,[t]),await this.revokeRefreshTokens(m.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(P(),S)),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
|
|
127
|
+
`),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let n=Be(32).toString("base64url"),a=this.hashToken(n),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 m=`${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:m})}async verifyEmail(e,t){let{Connection:s}=await Promise.resolve().then(()=>(P(),S)),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(()=>(P(),S)),i=this.config.otp?.table??"otp_codes",n=this.config.otp?.expiresIn??600,a=this.config.otp?.length??6;await this.ensureTable(i,`
|
|
128
128
|
CREATE TABLE IF NOT EXISTS ${i} (
|
|
129
129
|
email TEXT NOT NULL,
|
|
130
130
|
code TEXT NOT NULL,
|
|
@@ -133,32 +133,32 @@ 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 ${i} WHERE email = ? AND purpose = ?`,[e,t]);let
|
|
136
|
+
`),await r.raw(`DELETE FROM ${i} WHERE email = ? AND purpose = ?`,[e,t]);let o=this.generateOtpCode(a),c=this.hashToken(o),m=new Date(Date.now()+n*1e3).toISOString();await r.raw(`INSERT INTO ${i} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,c,t,m,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:o,purpose:t,expiresMinutes:String(h)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(P(),S)),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 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 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(()=>(P(),S)),t=new Date().toISOString(),s=0,r=0,i=0,n=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 ${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 ${o} 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 ye("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=Be(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(()=>(P(),S));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(vi(),bi)),{Mailer:i}=await Promise.resolve().then(()=>(Vt(),er)),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)}}},we=class extends E{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()}},Gt=class extends E{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 yo,mkdir as wo}from"fs/promises";import{dirname as Co}from"path";function q(){return new Date().toISOString()}var Yt,He,ir,nr,ar,or,lr,Zt,cr=w(()=>{"use strict";k();Yt={debug:0,info:1,warn:2,error:3,fatal:4},He=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(Yt[e.level]<Yt[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}`)}},ir=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(Yt[e.level]<Yt[this.minLevel])return;this.initialized||(await wo(Co(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
|
|
138
|
+
`}await yo(this.path,t)}},nr=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)}}},ar=class{minLevel="debug";write(){}},or=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 lr(this.resolveChannel(e))}debug(e,t={}){this.writeToDefault({level:"debug",message:e,context:t,timestamp:q()})}info(e,t={}){this.writeToDefault({level:"info",message:e,context:t,timestamp:q()})}warn(e,t={}){this.writeToDefault({level:"warn",message:e,context:t,timestamp:q()})}error(e,t={}){this.writeToDefault({level:"error",message:e,context:t,timestamp:q()})}fatal(e,t={}){this.writeToDefault({level:"fatal",message:e,context:t,timestamp:q()})}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 He({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 He(e);case"file":return new ir(e);case"stack":return new nr(e,t=>this.resolveChannel(t));case"null":return new ar;default:return new He(e)}}},lr=class{constructor(e){this.channel=e}debug(e,t={}){this.channel.write({level:"debug",message:e,context:t,timestamp:q()})}info(e,t={}){this.channel.write({level:"info",message:e,context:t,timestamp:q()})}warn(e,t={}){this.channel.write({level:"warn",message:e,context:t,timestamp:q()})}error(e,t={}){this.channel.write({level:"error",message:e,context:t,timestamp:q()})}fatal(e,t={}){this.channel.write({level:"fatal",message:e,context:t,timestamp:q()})}};Zt=C("svelar.log",()=>new or)});function ss(l,e){throw new j(l,e??xo(l))}function Pi(l,e,t){l&&ss(e,t)}function Si(l,e,t){l||ss(e,t)}function xo(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 j,Xt,dr,ur,es,ts,Ce,mr=w(()=>{"use strict";cr();j=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},Xt=class extends j{constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},dr=class extends j{constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},ur=class extends j{constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},es=class extends j{constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},ts=class extends Xt{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};Ce=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[es,Xt,dr,ur],...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 j?{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 j){let s={message:e.message};return e instanceof es&&(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 Ti(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:a=6e4,csrfPaths:n=["/api/"],csrfExcludePaths:l=["/api/webhooks"],authThrottleAttempts:c=5,authThrottleDecay:m=1,debug:p=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:u={},i18n:b,errorConfig:v={}}=o,y=[new ce,new oe({maxRequests:i,windowMs:a}),new le({onlyPaths:n,excludePaths:l}),new he({store:s??new V,secret:t,lifetime:r})];e&&y.push(new be(e)),y.push(...h);let C={"auth-throttle":new de({maxAttempts:c,decayMinutes:m}),...u},T=new ye({debug:p,...v}),A=pr({middleware:y,namedMiddleware:C,onError:(xe,Pe)=>T.handle(xe,Pe)}),I;if(b){let{paraglideMiddleware:xe,getTextDirection:Pe=()=>"ltr"}=b;I=hr(async({event:_,resolve:We})=>xe(_.request,({request:vs,locale:Je})=>(_.request=vs,We(_,{transformPageChunk:({html:Ve})=>Ve.replace("%lang%",Je).replace("%dir%",Pe(Je))}))),A)}else I=A;return{handle:I,handleError:T.handleSvelteKitError()}}function pr(o={}){let e=new H;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 a=await e.execute(i,async()=>r(s));return a instanceof Response?a:r(s)}catch(a){if(o.onError){let n=await o.onError(a,s);if(n instanceof Response)return n}return console.error("[Svelar] Unhandled error in hooks:",a),new Response(JSON.stringify({message:process.env.NODE_ENV==="production"?"Internal server error":a.message}),{status:500,headers:{"Content-Type":"application/json"}})}}}function hr(...o){return async function({event:t,resolve:s}){let r=s;for(let i=o.length-1;i>=0;i--){let a=o[i],n=r;r=l=>a({event:l,resolve:n})}return r(t)}}var gr=x(()=>{"use strict";ue();Bs();rr();mr()});function ki(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 fr,Ei,$i=x(()=>{"use strict";E();fr=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:a}=await import("fs"),{pathToFileURL:n}=await import("url"),l=t(e);if(!i(l))return[];let c=a(l).filter(p=>(p.endsWith(".ts")||p.endsWith(".js"))&&!p.startsWith(".")),m=[];for(let p of c){let h=s(p,r(p)),u=t(l,p);try{let v=await import(n(u).href),y=v.default??v.config??v;y&&typeof y=="object"&&!Array.isArray(y)&&(this.set(h,y),m.push(h))}catch{}}return m}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 a=1;a<s.length-1;a++)(i[s[a]]===void 0||typeof i[s[a]]!="object")&&(i[s[a]]={}),i=i[s[a]];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}},Ei=P("svelar.config",()=>new fr)});import{z as k}from"zod";function Di(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"],a=s;for(let l=0;l<i.length-1;l++){let c=i[l];c in a||(a[c]={}),a=a[c]}let n=i[i.length-1];a[n]||(a[n]=[]),a[n].push(r.message)}return{success:!1,errors:s}}var Ai,Li=x(()=>{"use strict";Ai={required:()=>k.string().min(1,"This field is required"),email:()=>k.string().email("Must be a valid email address"),string:(o,e)=>{let t=k.string();return o!==void 0&&(t=t.min(o)),e!==void 0&&(t=t.max(e)),t},number:(o,e)=>{let t=k.number();return o!==void 0&&(t=t.min(o)),e!==void 0&&(t=t.max(e)),t},integer:()=>k.number().int(),boolean:()=>k.boolean(),date:()=>k.coerce.date(),url:()=>k.string().url(),uuid:()=>k.string().uuid(),enum:o=>k.enum(o),array:o=>k.array(o),nullable:o=>o.nullable(),optional:o=>o.optional(),confirmed:(o="password")=>k.object({[o]:k.string(),[`${o}_confirmation`]:k.string()}).refine(e=>e[o]===e[`${o}_confirmation`],{message:"Confirmation does not match",path:[`${o}_confirmation`]}),min:o=>k.number().min(o),max:o=>k.number().max(o),between:(o,e)=>k.number().min(o).max(e),regex:(o,e)=>k.string().regex(o,e),ip:()=>k.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:()=>k.string().refine(o=>{try{return JSON.parse(o),!0}catch{return!1}},{message:"Must be valid JSON"})}});var _i={};L(_i,{FormAuthorizationError:()=>G,FormRequest:()=>ve,FormValidationError:()=>Q});var ve,Q,G,rs=x(()=>{"use strict";ve=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new Q(e)}failedAuthorization(){throw new G}async parseBody(e){let t=e.request.headers.get("content-type")??"";if(t.includes("application/json"))return e.request.json();if(t.includes("multipart/form-data")||t.includes("application/x-www-form-urlencoded")){let s=await e.request.formData();return Object.fromEntries(s)}return Object.fromEntries(e.url.searchParams)}static async validate(e){let t=new this;await t.authorize(e)||t.failedAuthorization();let r=await t.parseBody(e),i={...Object.fromEntries(e.url.searchParams),...e.params,...r},n=t.rules().safeParse(i);if(!n.success){let l={},c=t.messages(),m=t.attributes();for(let p of n.error.issues){let h=p.path.join("."),u=m[h]??h;l[u]||(l[u]=[]);let b=`${h}.${p.code}`,v=c[b]??c[h];l[u].push(v??p.message)}t.failedValidation(l)}return t.passedValidation(n.data)}},Q=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"}})}},G=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 Mi,writeFile as Po,unlink as So,mkdir as ze,readdir as br,stat as Ni,copyFile as Ro,rename as To}from"fs/promises";import{existsSync as ko}from"fs";import{join as Eo,dirname as is}from"path";var yr,as,vr,Ii,ji=x(()=>{"use strict";E();yr=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return Eo(this.config.root,e)}async get(e){return Mi(this.resolve(e))}async getText(e){return Mi(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await ze(is(s),{recursive:!0}),await Po(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await ze(is(r),{recursive:!0}),await s(r,t)}async exists(e){return ko(this.resolve(e))}async delete(e){try{return await So(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await ze(is(s),{recursive:!0}),await Ro(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await ze(is(s),{recursive:!0}),await To(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await br(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 br(s,{withFileTypes:!0});for(let i of r){let a=e?`${e}/${i.name}`:i.name;i.isFile()?t.push(a):i.isDirectory()&&t.push(...await this.allFiles(a))}}catch{}return t}async directories(e=""){let t=this.resolve(e);try{return(await br(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await ze(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 Ni(this.resolve(e))).size}async lastModified(e){return(await Ni(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},as=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(a=>a.Key).filter(a=>a!==r).map(a=>{let n=this.config.prefix;return n?a.slice(n.length+1):a})}catch{return[]}}async allFiles(e=""){let t=await this.getS3(),s=await this.getClient(),r=this.key(e?`${e}/`:""),i=[],a;do{let n=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:a}));for(let l of n.Contents??[]){let c=this.config.prefix,m=c?l.Key.slice(c.length+1):l.Key;m&&i.push(m)}a=n.IsTruncated?n.NextContinuationToken:void 0}while(a);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(a=>{let n=this.config.prefix;return(n?a.Prefix.slice(n.length+1):a.Prefix).replace(/\/$/,"")}).filter(a=>a.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(),a=new r.GetObjectCommand({Bucket:this.config.bucket,Key:this.key(e)});return await s.getSignedUrl(i,a,{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}))}}},vr=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 yr(e);case"s3":return new as(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof as))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},Ii=P("svelar.storage",()=>new vr)});import{readFile as $o,writeFile as Ao,unlink as Oi,mkdir as qi}from"fs/promises";import{join as Do,dirname as Lo}from"path";import{createHash as _o}from"crypto";var wr,Cr,xr,Pr,Ui,Fi=x(()=>{"use strict";E();wr=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)}},Cr=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=_o("md5").update(e).digest("hex");return Do(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await $o(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await Oi(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 qi(Lo(r),{recursive:!0}),await Ao(r,JSON.stringify(i))}async forget(e){try{return await Oi(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 qi(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)}},xr=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 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 wr;case"file":return new Cr(e);case"null":return new xr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},Ui=P("svelar.cache",()=>new Pr)});var ns,Sr,Rr,Tr,Bi,Hi=x(()=>{"use strict";E();ns=class{},Sr=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(()=>(Vt(),er));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)}}},Rr=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(()=>(S(),R));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)}}},Tr=class{channels=new Map;constructor(){this.channels.set("mail",new Sr),this.channels.set("database",new Rr)}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
|
|
142
|
-
data: ${JSON.stringify(
|
|
140
|
+
`).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function Ri(l={}){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:o=["/api/webhooks"],authThrottleAttempts:c=5,authThrottleDecay:m=1,debug:p=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:u={},i18n:f,errorConfig:v={}}=l,x=[new me,new de({maxRequests:i,windowMs:n}),new ue({onlyPaths:a,excludePaths:o}),new be({store:s??new G,secret:t,lifetime:r})];e&&x.push(new we(e)),x.push(...h);let L={"auth-throttle":new pe({maxAttempts:c,decayMinutes:m}),...u},$=new Ce({debug:p,...v}),D=pr({middleware:x,namedMiddleware:L,onError:(R,I)=>$.handle(R,I)}),N;if(f){let{paraglideMiddleware:R,getTextDirection:I=()=>"ltr"}=f;N=hr(async({event:A,resolve:We})=>R(A.request,({request:ys,locale:Je})=>(A.request=ys,We(A,{transformPageChunk:({html:Ve})=>Ve.replace("%lang%",Je).replace("%dir%",I(Je))}))),D)}else N=D;return{handle:N,handleError:$.handleSvelteKitError()}}function pr(l={}){let e=new K;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 i={event:s,params:s.params??{},locals:s.locals??{}};try{l.app&&!l.app.isBooted()&&await l.app.bootstrap();let n=await e.execute(i,async()=>r(s));return n instanceof Response?n:r(s)}catch(n){if(l.onError){let a=await l.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 hr(...l){return async function({event:t,resolve:s}){let r=s;for(let i=l.length-1;i>=0;i--){let n=l[i],a=r;r=o=>n({event:o,resolve:a})}return r(t)}}var gr=w(()=>{"use strict";he();Bs();rr();mr()});function Ti(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 fr,ki,Ei=w(()=>{"use strict";k();fr=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"),o=t(e);if(!i(o))return[];let c=n(o).filter(p=>(p.endsWith(".ts")||p.endsWith(".js"))&&!p.startsWith(".")),m=[];for(let p of c){let h=s(p,r(p)),u=t(o,p);try{let v=await import(a(u).href),x=v.default??v.config??v;x&&typeof x=="object"&&!Array.isArray(x)&&(this.set(h,x),m.push(h))}catch{}}return m}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}},ki=C("svelar.config",()=>new fr)});import{z as T}from"zod";function Ai(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 i=r.path.length>0?r.path:["_root"],n=s;for(let o=0;o<i.length-1;o++){let c=i[o];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,Di=w(()=>{"use strict";$i={required:()=>T.string().min(1,"This field is required"),email:()=>T.string().email("Must be a valid email address"),string:(l,e)=>{let t=T.string();return l!==void 0&&(t=t.min(l)),e!==void 0&&(t=t.max(e)),t},number:(l,e)=>{let t=T.number();return l!==void 0&&(t=t.min(l)),e!==void 0&&(t=t.max(e)),t},integer:()=>T.number().int(),boolean:()=>T.boolean(),date:()=>T.coerce.date(),url:()=>T.string().url(),uuid:()=>T.string().uuid(),enum:l=>T.enum(l),array:l=>T.array(l),nullable:l=>l.nullable(),optional:l=>l.optional(),confirmed:(l="password")=>T.object({[l]:T.string(),[`${l}_confirmation`]:T.string()}).refine(e=>e[l]===e[`${l}_confirmation`],{message:"Confirmation does not match",path:[`${l}_confirmation`]}),min:l=>T.number().min(l),max:l=>T.number().max(l),between:(l,e)=>T.number().min(l).max(e),regex:(l,e)=>T.string().regex(l,e),ip:()=>T.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:()=>T.string().refine(l=>{try{return JSON.parse(l),!0}catch{return!1}},{message:"Must be valid JSON"})}});var Li={};M(Li,{FormAuthorizationError:()=>Z,FormRequest:()=>xe,FormValidationError:()=>Y});var xe,Y,Z,rs=w(()=>{"use strict";xe=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new Y(e)}failedAuthorization(){throw new Z}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 o={},c=t.messages(),m=t.attributes();for(let p of a.error.issues){let h=p.path.join("."),u=m[h]??h;o[u]||(o[u]=[]);let f=`${h}.${p.code}`,v=c[f]??c[h];o[u].push(v??p.message)}t.failedValidation(o)}return t.passedValidation(a.data)}},Y=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"}})}},Z=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 Mi,writeFile as Po,unlink as So,mkdir as ze,readdir as br,stat as Ni,copyFile as Ro,rename as To}from"fs/promises";import{existsSync as ko}from"fs";import{join as Eo,dirname as is}from"path";var vr,ns,yr,Ii,_i=w(()=>{"use strict";k();vr=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return Eo(this.config.root,e)}async get(e){return Mi(this.resolve(e))}async getText(e){return Mi(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await ze(is(s),{recursive:!0}),await Po(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await ze(is(r),{recursive:!0}),await s(r,t)}async exists(e){return ko(this.resolve(e))}async delete(e){try{return await So(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await ze(is(s),{recursive:!0}),await Ro(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await ze(is(s),{recursive:!0}),await To(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await br(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 br(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 br(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await ze(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 Ni(this.resolve(e))).size}async lastModified(e){return(await Ni(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},ns=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 o of a.Contents??[]){let c=this.config.prefix,m=c?o.Key.slice(c.length+1):o.Key;m&&i.push(m)}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}))}}},yr=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 vr(e);case"s3":return new ns(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof ns))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},Ii=C("svelar.storage",()=>new yr)});import{readFile as $o,writeFile as Ao,unlink as ji,mkdir as Oi}from"fs/promises";import{join as Do,dirname as Lo}from"path";import{createHash as Mo}from"crypto";var wr,Cr,xr,Pr,qi,Ui=w(()=>{"use strict";k();wr=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)}},Cr=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=Mo("md5").update(e).digest("hex");return Do(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await $o(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await ji(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 Oi(Lo(r),{recursive:!0}),await Ao(r,JSON.stringify(i))}async forget(e){try{return await ji(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 Oi(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)}},xr=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 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 wr;case"file":return new Cr(e);case"null":return new xr;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},qi=C("svelar.cache",()=>new Pr)});var as,Sr,Rr,Tr,Fi,Bi=w(()=>{"use strict";k();as=class{},Sr=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(()=>(Vt(),er));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)}}},Rr=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(()=>(P(),S));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)}}},Tr=class{channels=new Map;constructor(){this.channels.set("mail",new Sr),this.channels.set("database",new Rr)}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(o){console.error(`[Notifications] Channel "${n}" failed:`,o)}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)}}},Fi=C("svelar.notifier",()=>new Tr)});function kr(l){return l.startsWith("private-")?"private":l.startsWith("presence-")?"presence":"public"}var Er,os,$r,Ar,Hi,zi=w(()=>{"use strict";k();Er=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=kr(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
|
-
`;i.enqueue(new TextEncoder().encode(
|
|
145
|
+
`;i.enqueue(new TextEncoder().encode(a));let o={controller:i,userId:e,userInfo:t};s.subscribers.push(o),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},o)},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<
|
|
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
|
-
`,i=new TextEncoder().encode(r);for(let
|
|
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
|
-
`,i=new TextEncoder().encode(r);for(let
|
|
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
|
-
`,i=new TextEncoder().encode(r);for(let
|
|
160
|
-
`),c=await this.hmacSha256(this.config.secret,
|
|
161
|
-
`);ls("warning",e[422]??"Validation Error",n);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){ls("warning",s,"Please sign in to continue.");return}ls(r,s)}function Lr(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 Vi(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,Wi,Dr,we,sm,Qi=x(()=>{"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."},Wi=null;Dr=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},a;s!==void 0&&(i["Content-Type"]||(i["Content-Type"]="application/json"),a=typeof s=="string"?s:JSON.stringify(s)),i.Accept||(i.Accept="application/json");let n=null,l=1+this._retries;for(let c=0;c<l;c++){c>0&&await new Promise(m=>setTimeout(m,this._retryDelay*c));try{let m=new AbortController,p=setTimeout(()=>m.abort(),this._timeout),h=await fetch(r,{method:e,headers:i,body:a,signal:m.signal});if(clearTimeout(p),!h.ok&&h.status<500&&c<l-1,!h.ok&&h.status>=500&&c<l-1){n=new we(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let u=h.headers.get("content-type")??"",b;if(u.includes("application/json")?b=await h.json():b=await h.text(),!h.ok)throw new we(`HTTP ${h.status}: ${typeof b=="string"?b:JSON.stringify(b)}`,h.status,b);return{data:b,status:h.status,headers:h.headers,ok:!0}}catch(m){if(m instanceof we)throw m;if(n=m,m.name==="AbortError"&&(n=new we("Request timed out",0,null)),c>=l-1)break}}throw n??new Error("HTTP request failed")}buildFullUrl(e){let t=this._baseUrl?`${this._baseUrl.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`:e,s=Object.entries(this._query);if(s.length>0){let r=new URL(t);for(let[i,a]of s)r.searchParams.set(i,a);t=r.toString()}return t}},we=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},sm=new Dr});function Gi(o){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=o;return({event:i,resolve:a})=>e(i.request,({request:n,locale:l})=>(i.request=n,a(i,{transformPageChunk:({html:c})=>c.replace(s,l).replace(r,t(l))})))}function Yi(o){return e=>o.deLocalizeUrl(e.url).pathname}var Zi=x(()=>{"use strict"});function Xi(o,e,t={}){return async s=>{let{superValidate:r,fail:i,message:a}=await import("sveltekit-superforms"),{zod:n}=await import("sveltekit-superforms/adapters"),l=await r(s,n(o));if(!l.valid)return i(400,{form:l});try{let c=await e(l.data,s);if(t.redirectTo){let{redirect:m}=await import("@sveltejs/kit");throw m(303,t.redirectTo)}return c??{form:l}}catch(c){if(c?.status>=300&&c?.status<400)throw c;return a(l,t.errorMessage||c.message||"An error occurred",{status:c.status||400})}}}async function ea(o,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(o))}async function ta(o,e){let t=await o.request.formData(),s={};for(let[i,a]of t.entries())s[i]=a;let r=e.safeParse(s);if(!r.success){let{FormValidationError:i}=await Promise.resolve().then(()=>(rs(),_i));throw new i(r.error.flatten().fieldErrors)}return r.data}var sa=x(()=>{"use strict";rs()});var ra={};L(ra,{Application:()=>qt,AuthManager:()=>Qt,AuthenticateMiddleware:()=>be,BelongsTo:()=>ie,BelongsToMany:()=>ae,Broadcast:()=>zi,Cache:()=>Ui,ColumnBuilder:()=>F,Connection:()=>f,Container:()=>J,Controller:()=>Ht,CorsMiddleware:()=>Ut,CsrfMiddleware:()=>le,DatabaseSessionStore:()=>zt,ErrorHandler:()=>ye,Event:()=>ne,EventDispatcher:()=>Me,FileSessionStore:()=>Kt,ForbiddenError:()=>je,FormAuthorizationError:()=>G,FormRequest:()=>ve,FormValidationError:()=>Q,HasMany:()=>re,HasOne:()=>se,Hash:()=>Ks,HttpError:()=>N,Job:()=>X,Log:()=>Zt,LoggingMiddleware:()=>Ft,Mailable:()=>Fe,Mailer:()=>Xs,MemorySessionStore:()=>V,Middleware:()=>$,MiddlewareStack:()=>H,Migration:()=>Te,Migrator:()=>ke,Model:()=>jt,ModelNotFoundError:()=>ts,NotFoundError:()=>Ne,Notification:()=>ns,Notifier:()=>Bi,OriginMiddleware:()=>ce,QueryBuilder:()=>j,Queue:()=>js,RateLimitMiddleware:()=>oe,RedisSessionStore:()=>Wt,RequireAuthMiddleware:()=>Gt,Schema:()=>B,Seeder:()=>Ot,ServiceProvider:()=>_e,Session:()=>pe,SessionMiddleware:()=>he,SignatureMiddleware:()=>Bt,Storage:()=>Ii,TableBuilder:()=>Y,ThrottleMiddleware:()=>de,UnauthorizedError:()=>Ie,ValidationError:()=>z,abort:()=>ss,abortIf:()=>Si,abortUnless:()=>Ri,apiFetch:()=>Ji,buildUrl:()=>Vi,config:()=>Ei,container:()=>mi,createFormAction:()=>Xi,createI18nHandle:()=>Gi,createReroute:()=>Yi,createSvelarApp:()=>Ti,createSvelarHooks:()=>pr,env:()=>ki,getCsrfToken:()=>Lr,loadForm:()=>ea,resource:()=>hi,rules:()=>Ai,schema:()=>ei,sequence:()=>hr,signJwt:()=>tr,validate:()=>Di,validateForm:()=>ta,verifyJwt:()=>sr,z:()=>k});var ia=x(()=>{"use strict";di();Os();qs();S();Ts();ks();ui();Fs();Us();pi();ue();gi();gr();$i();Li();rr();ge();Bs();mr();It();rs();ji();cr();Fi();ee();Vt();Hi();Ki();Qi();Zi();sa();gr()});var Nr={};L(Nr,{PluginRegistry:()=>hs});var Mr,hs,gs=x(()=>{"use strict";E();Mr=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:e}=await import("path"),{existsSync:t,readdirSync:s}=await import("fs"),{readFile:r}=await import("fs/promises"),i=[],a=e(process.cwd(),"node_modules");if(!t(a))return i;let n=async(l,c="")=>{if(t(l))try{let m=s(l,{withFileTypes:!0});for(let p of m){if(!p.isDirectory()||p.name.startsWith("."))continue;if(p.name.startsWith("@")){let v=e(l,p.name);await n(v,p.name+"/");continue}let h=c+p.name,u=p.name.startsWith("svelar-");if(!u)continue;let b=e(l,p.name,"package.json");if(t(b))try{let v=await r(b,"utf-8"),y=JSON.parse(v),C=y.keywords?.includes("svelar-plugin");if(!u&&!C)continue;let T={name:y.name||h,version:y.version||"0.0.0",description:y.description||"",packageName:h,installed:!0,enabled:!1,hasConfig:!!y.svelar?.config,hasMigrations:!!y.svelar?.migrations};i.push(T),this.plugins.set(T.name,T)}catch{}}}catch{}};return await n(a),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)}},hs=P("svelar.pluginRegistry",()=>new Mr)});var oa={};L(oa,{PluginPublisher:()=>jr});var Ir,jr,Or=x(()=>{"use strict";E();Ir=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:i,dirname:a}=await import("path"),{existsSync:n}=await import("fs"),l={configs:[],migrations:[],assets:[]},c=e.publishables?.()||{};for(let[m,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),b=a(u);if(!(n(u)&&!t?.force))try{await s(b,{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(v){console.warn(`Failed to publish ${h.source} to ${u}:`,v)}}return l}async preview(e){let t={configs:[],migrations:[],assets:[]},s=e.publishables?.()||{};for(let[r,i]of Object.entries(s))for(let a of i){let n=Qe("path").join(process.cwd(),a.dest);a.type==="config"?t.configs.push(n):a.type==="migration"?t.migrations.push(n):a.type==="asset"&&t.assets.push(n)}return t}},jr=P("svelar.pluginPublisher",()=>new Ir)});var la={};L(la,{PluginInstaller:()=>Bo});var qr,Bo,ca=x(()=>{"use strict";E();gs();Or();qr=class{async install(e,t){let{spawn:s}=await import("child_process"),{promisify:r}=await import("util"),{join:i}=await import("path"),{readFile:a}=await import("fs/promises"),{existsSync:n}=await import("fs");try{await this.runNpmInstall(e);let l=hs,c=await l.discover(),m;for(let h of c)if(h.packageName===e||h.name===e){m=h;break}if(!m)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(m.name);let p=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(m.packageName);h&&(p=await jr.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:m.name,version:m.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=hs,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}=Qe("child_process"),i=r("npm",["install",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",a=>{a===0?t():s(new Error(`npm install exited with code ${a}`))}),i.on("error",s)})}async runNpmUninstall(e){return new Promise((t,s)=>{let{spawn:r}=Qe("child_process"),i=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",a=>{a===0?t():s(new Error(`npm uninstall exited with code ${a}`))}),i.on("error",s)})}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}},Bo=P("svelar.pluginInstaller",()=>new qr)});import{dirname as ua,join as Ur}from"path";import{fileURLToPath as ma,pathToFileURL as Ho}from"url";import{register as zo}from"module";import{readFileSync as pa,existsSync as Ko}from"fs";var Ge=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:a}=this.parseArgs(s,r);try{await r.handle(i,a)}catch(n){let l=n instanceof Error?n.message:String(n);console.error(`\x1B[31mError:\x1B[0m ${l}`),n?.stack&&console.error(n.stack),process.exit(1)}}parseArgs(e,t){let s=[],r={};for(let i of t.flags)i.default!==void 0&&(r[i.name]=i.default);for(let i=0;i<e.length;i++){let a=e[i];if(a.startsWith("--")){let n=a.slice(2),l=n.indexOf("=");if(l!==-1){let p=n.slice(0,l);r[p]=n.slice(l+1);continue}let c=n;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(a.startsWith("-")&&a.length===2){let n=a.slice(1),l=t.flags.find(c=>c.alias===n);l&&(l.type==="boolean"?r[l.name]=!0:i+1<e.length&&(r[l.name]=e[++i]))}else s.push(a)}return{args:s,flags:r}}showCommandHelp(e){if(console.log(`
|
|
159
|
+
`,i=new TextEncoder().encode(r);for(let n of this.subscribers)if(n.userId!==s)try{n.controller.enqueue(i)}catch{}}},os=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),o=["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,o),m=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=`${m}://${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}`,f=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:i});if(!f.ok){let v=await f.text();throw new Error(`Pusher API error (${f.status}): ${v}`)}}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")}},$r=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)}},Ar=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 os(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new Er(e)),this.sseChannels.get(e)}async authorize(e,t){if(kr(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=kr(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 $r(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 os(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,o=>o==="{"||o==="}"?o:`\\${o}`).replace(/\\\{(\w+)\\\}/g,(o,c)=>(s.push(c),"([^.]+)")).replace(/\{(\w+)\}/g,(o,c)=>(s.push(c),"([^.]+)")),i=new RegExp(`^${r}$`),n=t.match(i);if(!n)return null;let a={};for(let o=0;o<s.length;o++)a[s[o]]=n[o+1];return a}},Hi=C("svelar.broadcast",()=>new Ar)});function ls(l,e,t){Ki&&Ki(l,e,{description:t})}async function Wi(l,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:i={},...n}=e,a=(n.method||"GET").toUpperCase(),o=new Headers(n.headers);if(["POST","PUT","PATCH","DELETE"].includes(a)){let c=Lr(t);c&&o.set(s,c)}n.body&&typeof n.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,{...n,headers:o});return!c.ok&&r&&await Io(c,{...No,...i}),c}catch(c){throw r&&ls("error","Network Error","Unable to connect. Check your internet connection."),c}}async function Io(l,e){let t="";try{if((l.headers.get("content-type")??"").includes("application/json")){let n=await l.clone().json();if(t=n.message??"",l.status===422&&n.errors){let a=Object.entries(n.errors).map(([o,c])=>`${o}: ${c.join(", ")}`).slice(0,3).join(`
|
|
161
|
+
`);ls("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){ls("warning",s,"Please sign in to continue.");return}ls(r,s)}function Lr(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 Ji(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 No,Ki,Dr,Pe,rm,Vi=w(()=>{"use strict";No={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."},Ki=null;Dr=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),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,o=1+this._retries;for(let c=0;c<o;c++){c>0&&await new Promise(m=>setTimeout(m,this._retryDelay*c));try{let m=new AbortController,p=setTimeout(()=>m.abort(),this._timeout),h=await fetch(r,{method:e,headers:i,body:n,signal:m.signal});if(clearTimeout(p),!h.ok&&h.status<500&&c<o-1,!h.ok&&h.status>=500&&c<o-1){a=new Pe(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let u=h.headers.get("content-type")??"",f;if(u.includes("application/json")?f=await h.json():f=await h.text(),!h.ok)throw new Pe(`HTTP ${h.status}: ${typeof f=="string"?f:JSON.stringify(f)}`,h.status,f);return{data:f,status:h.status,headers:h.headers,ok:!0}}catch(m){if(m instanceof Pe)throw m;if(a=m,m.name==="AbortError"&&(a=new Pe("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[i,n]of s)r.searchParams.set(i,n);t=r.toString()}return t}},Pe=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},rm=new Dr});function Qi(l){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=l;return({event:i,resolve:n})=>e(i.request,({request:a,locale:o})=>(i.request=a,n(i,{transformPageChunk:({html:c})=>c.replace(s,o).replace(r,t(o))})))}function Gi(l){return e=>l.deLocalizeUrl(e.url).pathname}var Yi=w(()=>{"use strict"});function Zi(l,e,t={}){return async s=>{let{superValidate:r,fail:i,message:n}=await import("sveltekit-superforms"),{zod:a}=await import("sveltekit-superforms/adapters"),o=await r(s,a(l));if(!o.valid)return i(400,{form:o});try{let c=await e(o.data,s);if(t.redirectTo){let{redirect:m}=await import("@sveltejs/kit");throw m(303,t.redirectTo)}return c??{form:o}}catch(c){if(c?.status>=300&&c?.status<400)throw c;return n(o,t.errorMessage||c.message||"An error occurred",{status:c.status||400})}}}async function Xi(l,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(l))}async function en(l,e){let t=await l.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(()=>(rs(),Li));throw new i(r.error.flatten().fieldErrors)}return r.data}var tn=w(()=>{"use strict";rs()});var sn={};M(sn,{Application:()=>qt,AuthManager:()=>Qt,AuthenticateMiddleware:()=>we,BelongsTo:()=>oe,BelongsToMany:()=>le,Broadcast:()=>Hi,Cache:()=>qi,ColumnBuilder:()=>H,Connection:()=>b,Container:()=>Q,Controller:()=>Ht,CorsMiddleware:()=>Ut,CsrfMiddleware:()=>ue,DatabaseSessionStore:()=>zt,ErrorHandler:()=>Ce,Event:()=>ce,EventDispatcher:()=>Ne,FileSessionStore:()=>Kt,ForbiddenError:()=>je,FormAuthorizationError:()=>Z,FormRequest:()=>xe,FormValidationError:()=>Y,HasMany:()=>ae,HasOne:()=>ne,Hash:()=>Ks,HttpError:()=>j,Job:()=>se,Log:()=>Zt,LoggingMiddleware:()=>Ft,Mailable:()=>Fe,Mailer:()=>Xs,MemorySessionStore:()=>G,Middleware:()=>E,MiddlewareStack:()=>K,Migration:()=>Te,Migrator:()=>ke,Model:()=>jt,ModelNotFoundError:()=>ts,NotFoundError:()=>Ie,Notification:()=>as,Notifier:()=>Fi,OriginMiddleware:()=>me,QueryBuilder:()=>O,Queue:()=>js,RateLimitMiddleware:()=>de,RedisSessionStore:()=>Wt,RequireAuthMiddleware:()=>Gt,Schema:()=>z,Seeder:()=>Ot,ServiceProvider:()=>Me,Session:()=>fe,SessionMiddleware:()=>be,SignatureMiddleware:()=>Bt,Storage:()=>Ii,TableBuilder:()=>ee,ThrottleMiddleware:()=>pe,UnauthorizedError:()=>_e,ValidationError:()=>W,abort:()=>ss,abortIf:()=>Pi,abortUnless:()=>Si,apiFetch:()=>Wi,buildUrl:()=>Ji,config:()=>ki,container:()=>ui,createFormAction:()=>Zi,createI18nHandle:()=>Qi,createReroute:()=>Gi,createSvelarApp:()=>Ri,createSvelarHooks:()=>pr,env:()=>Ti,getCsrfToken:()=>Lr,loadForm:()=>Xi,resource:()=>pi,rules:()=>$i,schema:()=>Xr,sequence:()=>hr,signJwt:()=>tr,validate:()=>Ai,validateForm:()=>en,verifyJwt:()=>sr,z:()=>T});var rn=w(()=>{"use strict";ci();Os();qs();P();Ts();ks();di();Fs();Us();mi();he();hi();gr();Ei();Di();rr();ve();Bs();mr();_t();rs();_i();cr();Ui();re();Vt();Bi();zi();Vi();Yi();tn();gr()});var Ir={};M(Ir,{PluginRegistry:()=>hs});var Nr,hs,gs=w(()=>{"use strict";k();Nr=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;let a=async(o,c="")=>{if(t(o))try{let m=s(o,{withFileTypes:!0});for(let p of m){if(!p.isDirectory()||p.name.startsWith("."))continue;if(p.name.startsWith("@")){let v=e(o,p.name);await a(v,p.name+"/");continue}let h=c+p.name,u=p.name.startsWith("svelar-");if(!u)continue;let f=e(o,p.name,"package.json");if(t(f))try{let v=await r(f,"utf-8"),x=JSON.parse(v),L=x.keywords?.includes("svelar-plugin");if(!u&&!L)continue;let $={name:x.name||h,version:x.version||"0.0.0",description:x.description||"",packageName:h,installed:!0,enabled:!1,hasConfig:!!x.svelar?.config,hasMigrations:!!x.svelar?.migrations};i.push($),this.plugins.set($.name,$)}catch{}}}catch{}};return await a(n),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)}},hs=C("svelar.pluginRegistry",()=>new Nr)});var ln={};M(ln,{PluginPublisher:()=>jr});var _r,jr,Or=w(()=>{"use strict";k();_r=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"),o={configs:[],migrations:[],assets:[]},c=e.publishables?.()||{};for(let[m,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),f=n(u);if(!(a(u)&&!t?.force))try{await s(f,{recursive:!0}),await r(h.source,u),h.type==="config"?o.configs.push(u):h.type==="migration"?o.migrations.push(u):h.type==="asset"&&o.assets.push(u)}catch(v){console.warn(`Failed to publish ${h.source} to ${u}:`,v)}}return o}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=Qe("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}},jr=C("svelar.pluginPublisher",()=>new _r)});var cn={};M(cn,{PluginInstaller:()=>Ho});var qr,Ho,dn=w(()=>{"use strict";k();gs();Or();qr=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 o=hs,c=await o.discover(),m;for(let h of c)if(h.packageName===e||h.name===e){m=h;break}if(!m)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(m.name);let p=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(m.packageName);h&&(p=await jr.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:m.name,version:m.version,published:p}}catch(o){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:o?.message??String(o)}}}async uninstall(e){try{let t=hs,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}=Qe("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}=Qe("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}/plugin`);return t.default||Object.values(t)[0]}catch{try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}}},Ho=C("svelar.pluginInstaller",()=>new qr)});import{dirname as mn,join as Ur}from"path";import{fileURLToPath as pn,pathToFileURL as zo}from"url";import{register as Ko}from"module";import{readFileSync as hn,existsSync as Wo}from"fs";var Ge=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 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 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),o=a.indexOf("=");if(o!==-1){let p=a.slice(0,o);r[p]=a.slice(o+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),o=t.flags.find(c=>c.alias===a);o&&(o.type==="boolean"?r[o.name]=!0:i+1<e.length&&(r[o.name]=e[++i]))}else s.push(n)}return{args:s,flags:r}}showCommandHelp(e){if(console.log(`
|
|
162
162
|
\x1B[33mDescription:\x1B[0m`),console.log(` ${e.description}
|
|
163
163
|
`),console.log("\x1B[33mUsage:\x1B[0m"),console.log(` svelar ${e.name} [options]
|
|
164
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(`
|
|
@@ -172,7 +172,7 @@ id: ${Date.now()}
|
|
|
172
172
|
svelar <command> [arguments] [options]
|
|
173
173
|
|
|
174
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(`
|
|
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()}};import{existsSync as
|
|
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()}};import{existsSync as fn}from"fs";import{join as Se}from"path";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(()=>(P(),S)),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"),m=JSON.parse(c);r.configure(m),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((n,a)=>Math.max(n.length,...t.map(o=>(o[a]??"").length))),r=s.map(n=>"\u2500".repeat(n+2)).join("\u253C"),i=n=>n.map((a,o)=>` ${(a??"").padEnd(s[o])} `).join("\u2502");console.log(i(e)),console.log(r);for(let n of t)console.log(i(n))}newLine(){console.log()}isDDD(){return fn(Se(process.cwd(),"src","lib","modules"))}sharedDir(e){return this.isDDD()?Se(process.cwd(),"src","lib","shared",e):Se(process.cwd(),"src","lib",e)}moduleDir(e,t){return this.isDDD()?Se(process.cwd(),"src","lib","modules",e):Se(process.cwd(),"src","lib",t)}};import{writeFileSync as Cs,mkdirSync as xs,existsSync as bn}from"fs";import{join as Ye}from"path";var Ze=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.isDDD()&&this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let n=this.moduleDir(i,"models");xs(n,{recursive:!0});let a=Ye(n,`${s}.ts`);if(bn(a)){this.warn(`Model ${s} already exists at ${a}`);return}let o=`import { Model } from '@beeblock/svelar/orm';
|
|
176
176
|
|
|
177
177
|
export class ${s} extends Model {
|
|
178
178
|
static table = '${r}';
|
|
@@ -189,7 +189,7 @@ export class ${s} extends Model {
|
|
|
189
189
|
// return this.hasMany(Post, 'user_id');
|
|
190
190
|
// }
|
|
191
191
|
}
|
|
192
|
-
`;Cs(
|
|
192
|
+
`;Cs(a,o);let c=this.isDDD()?`src/lib/modules/${i}`:"src/lib/models";if(this.success(`Model created: ${c}/${s}.ts`),t.migration||t.all){let p=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,h=Ye(process.cwd(),"src","lib","database","migrations");xs(h,{recursive:!0});let u=`import { Migration } from '@beeblock/svelar/database';
|
|
193
193
|
|
|
194
194
|
export default class Create${s}sTable extends Migration {
|
|
195
195
|
async up() {
|
|
@@ -206,7 +206,7 @@ export default class Create${s}sTable extends Migration {
|
|
|
206
206
|
await this.schema.dropTable('${r}');
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
|
-
`;Cs(Ye(h,`${p}.ts`),u),this.success(`Migration created: src/lib/database/migrations/${p}.ts`)}if(t.controller||t.resource||t.all){let m=`${s}Controller`,p=this.moduleDir(i,"controllers");xs(p,{recursive:!0});let h=t.resource||t.all,u=this.isDDD()?`./${s}.js`:`../models/${s}.js`,
|
|
209
|
+
`;Cs(Ye(h,`${p}.ts`),u),this.success(`Migration created: src/lib/database/migrations/${p}.ts`)}if(t.controller||t.resource||t.all){let m=`${s}Controller`,p=this.moduleDir(i,"controllers");xs(p,{recursive:!0});let h=t.resource||t.all,u=this.isDDD()?`./${s}.js`:`../models/${s}.js`,f=h?this.generateResourceController(s,m,u):this.generateBasicController(s,m,u);Cs(Ye(p,`${m}.ts`),f);let v=this.isDDD()?`src/lib/modules/${i}`:"src/lib/controllers";this.success(`Controller created: ${v}/${m}.ts`)}}generateResourceController(e,t,s=`./${e}.js`){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
|
|
210
210
|
import { z } from '@beeblock/svelar/validation';
|
|
211
211
|
import { ${e} } from '${s}';
|
|
212
212
|
|
|
@@ -258,11 +258,11 @@ export class ${t} extends Controller {
|
|
|
258
258
|
return this.json(items);
|
|
259
259
|
}
|
|
260
260
|
}
|
|
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
|
|
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 vn,mkdirSync as yn}from"fs";import{join as Fr}from"path";var Xe=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=Fr(process.cwd(),"src","lib","database","migrations");yn(r,{recursive:!0});let n=`${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"),m;o?m=`import { Migration } from '@beeblock/svelar/database';
|
|
262
262
|
|
|
263
|
-
export default class ${
|
|
263
|
+
export default class ${a} extends Migration {
|
|
264
264
|
async up() {
|
|
265
|
-
await this.schema.createTable('${
|
|
265
|
+
await this.schema.createTable('${o}', (table) => {
|
|
266
266
|
table.increments('id');
|
|
267
267
|
// Add your columns here
|
|
268
268
|
table.timestamps();
|
|
@@ -270,12 +270,12 @@ export default class ${n} extends Migration {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
async down() {
|
|
273
|
-
await this.schema.dropTable('${
|
|
273
|
+
await this.schema.dropTable('${o}');
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
`:c?m=`import { Migration } from '@beeblock/svelar/database';
|
|
277
277
|
|
|
278
|
-
export default class ${
|
|
278
|
+
export default class ${a} extends Migration {
|
|
279
279
|
async up() {
|
|
280
280
|
await this.schema.addColumn('${c}', (table) => {
|
|
281
281
|
// Add new columns here
|
|
@@ -289,7 +289,7 @@ export default class ${n} extends Migration {
|
|
|
289
289
|
}
|
|
290
290
|
`:m=`import { Migration } from '@beeblock/svelar/database';
|
|
291
291
|
|
|
292
|
-
export default class ${
|
|
292
|
+
export default class ${a} extends Migration {
|
|
293
293
|
async up() {
|
|
294
294
|
// Write your migration here
|
|
295
295
|
}
|
|
@@ -298,7 +298,7 @@ export default class ${n} extends Migration {
|
|
|
298
298
|
// Reverse the migration
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
|
-
`,
|
|
301
|
+
`,vn(Fr(r,`${n}.ts`),m),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 wn,mkdirSync as Cn,existsSync as xn}from"fs";import{join as Pn}from"path";var et=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.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=this.moduleDir(n,"controllers");Cn(a,{recursive:!0});let o=Pn(a,`${r}.ts`);if(xn(o)){this.warn(`Controller ${r} already exists.`);return}let c=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,m=t.resource?this.generateResourceController(r,t.model,c):this.generateBasicController(r);wn(o,m);let p=this.isDDD()?`src/lib/modules/${n}`:"src/lib/controllers";this.success(`Controller created: ${p}/${r}.ts`)}generateResourceController(e,t,s){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
|
|
302
302
|
import { z } from '@beeblock/svelar/validation';
|
|
303
303
|
${t&&s?`import { ${t} } from '${s}';
|
|
304
304
|
`:""}
|
|
@@ -344,7 +344,7 @@ export class ${e} extends Controller {
|
|
|
344
344
|
return this.json({ message: 'Hello from ${e}' });
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
|
-
`}};import{writeFileSync as
|
|
347
|
+
`}};import{writeFileSync as Sn,mkdirSync as Rn,existsSync as Tn}from"fs";import{join as kn}from"path";var tt=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=this.sharedDir("middleware");Rn(r,{recursive:!0});let i=kn(r,`${s}.ts`);if(Tn(i)){this.warn(`Middleware ${s} already exists.`);return}let n=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
|
|
348
348
|
|
|
349
349
|
export class ${s} extends Middleware {
|
|
350
350
|
async handle(ctx: MiddlewareContext, next: NextFunction): Promise<Response | void> {
|
|
@@ -357,7 +357,7 @@ export class ${s} extends Middleware {
|
|
|
357
357
|
return response;
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
|
-
`;
|
|
360
|
+
`;Sn(i,n);let a=this.isDDD()?`src/lib/shared/middleware/${s}.ts`:`src/lib/middleware/${s}.ts`;this.success(`Middleware created: ${a}`)}};import{writeFileSync as En,mkdirSync as $n,existsSync as An}from"fs";import{join as Dn}from"path";var st=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=this.sharedDir("providers");$n(r,{recursive:!0});let i=Dn(r,`${s}.ts`);if(An(i)){this.warn(`Provider ${s} already exists.`);return}let n=`import { ServiceProvider } from '@beeblock/svelar/container';
|
|
361
361
|
import type { Container } from '@beeblock/svelar/container';
|
|
362
362
|
|
|
363
363
|
export class ${s} extends ServiceProvider {
|
|
@@ -378,7 +378,7 @@ export class ${s} extends ServiceProvider {
|
|
|
378
378
|
// Initialization logic here
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
|
-
`;
|
|
381
|
+
`;En(i,n);let a=this.isDDD()?`src/lib/shared/providers/${s}.ts`:`src/lib/providers/${s}.ts`;this.success(`Provider created: ${a}`)}};import{writeFileSync as Ln,mkdirSync as Mn,existsSync as Nn}from"fs";import{join as Br}from"path";var rt=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=Br(process.cwd(),"src","lib","database","seeders");Mn(r,{recursive:!0});let i=Br(r,`${s}.ts`);if(Nn(i)){this.warn(`Seeder ${s} already exists.`);return}let n=`import { Seeder } from '@beeblock/svelar/database';
|
|
382
382
|
|
|
383
383
|
export class ${s} extends Seeder {
|
|
384
384
|
async run(): Promise<void> {
|
|
@@ -387,7 +387,7 @@ export class ${s} extends Seeder {
|
|
|
387
387
|
// await User.create({ name: 'Admin', email: 'admin@example.com' });
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
-
`;
|
|
390
|
+
`;Ln(i,n),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as In,mkdirSync as _n,existsSync as jn}from"fs";import{join as On}from"path";var it=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.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=this.moduleDir(n,"services");_n(a,{recursive:!0});let o=On(a,`${r}.ts`);if(jn(o)){this.warn(`Service ${r} already exists.`);return}let c=t.model?this.isDDD()?`./${t.model}.js`:`../models/${t.model}.js`:void 0,m=t.crud?this.generateCrudService(r,t.model,c):this.generateBasicService(r);In(o,m);let p=this.isDDD()?`src/lib/modules/${n}`:"src/lib/services";this.success(`Service created: ${p}/${r}.ts`)}generateCrudService(e,t,s){let r=t||"Model",i=s||`./${r}.js`;return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
|
|
391
391
|
import { ${r} } from '${i}';
|
|
392
392
|
|
|
393
393
|
export class ${e} extends CrudService<${r}> {
|
|
@@ -412,7 +412,7 @@ export class ${e} extends Service {
|
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
|
-
`}};import{writeFileSync as
|
|
415
|
+
`}};import{writeFileSync as qn,mkdirSync as Un,existsSync as Fn}from"fs";import{join as Bn}from"path";var nt=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.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=this.moduleDir(n,"repositories");Un(a,{recursive:!0});let o=Bn(a,`${r}.ts`);if(Fn(o)){this.warn(`Repository ${r} already exists.`);return}let c=t.model||this.inferModelName(r),m=this.isDDD()?`./${c}.js`:`../models/${c}.js`,p=`import { Repository } from '@beeblock/svelar/repositories';
|
|
416
416
|
import { ${c} } from '${m}';
|
|
417
417
|
|
|
418
418
|
export class ${r} extends Repository<${c}> {
|
|
@@ -429,7 +429,7 @@ export class ${r} extends Repository<${c}> {
|
|
|
429
429
|
// return ${c}.where('active', true).orderBy('name').get();
|
|
430
430
|
// }
|
|
431
431
|
}
|
|
432
|
-
`;
|
|
432
|
+
`;qn(o,p);let h=this.isDDD()?`src/lib/modules/${n}`:"src/lib/repositories";this.success(`Repository created: ${h}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as Hn,mkdirSync as zn,existsSync as Kn}from"fs";import{join as Wn}from"path";var at=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.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=this.moduleDir(n,"actions");zn(a,{recursive:!0});let o=Wn(a,`${r}.ts`);if(Kn(o)){this.warn(`Action ${r} already exists.`);return}let c=`import { Action } from '@beeblock/svelar/actions';
|
|
433
433
|
|
|
434
434
|
interface ${r}Input {
|
|
435
435
|
// Define input type
|
|
@@ -445,7 +445,7 @@ export class ${r} extends Action<${r}Input, ${r}Output> {
|
|
|
445
445
|
throw new Error('Not implemented');
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
|
-
`;
|
|
448
|
+
`;Hn(o,c);let m=this.isDDD()?`src/lib/modules/${n}`:"src/lib/actions";this.success(`Action created: ${m}/${r}.ts`)}};import{writeFileSync as Jn,mkdirSync as Vn,existsSync as Qn}from"fs";import{join as Gn}from"path";var ot=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.isDDD()&&this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let a=this.moduleDir(n,"dtos");Vn(a,{recursive:!0});let o=Gn(a,`${r}.ts`);if(Qn(o)){this.warn(`Request ${r} already exists.`);return}let c=`import { FormRequest } from '@beeblock/svelar/routing';
|
|
449
449
|
import { z } from '@beeblock/svelar/validation';
|
|
450
450
|
|
|
451
451
|
export class ${r} extends FormRequest {
|
|
@@ -474,11 +474,11 @@ export class ${r} extends FormRequest {
|
|
|
474
474
|
return data;
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
|
-
`;
|
|
477
|
+
`;Jn(o,c);let m=this.isDDD()?`src/lib/modules/${n}`:"src/lib/dtos";this.success(`Request created: ${m}/${r}.ts`)}};import{writeFileSync as Yn,mkdirSync as Zn,existsSync as Xn}from"fs";import{join as ea}from"path";var lt=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=this.sharedDir("plugins");Zn(r,{recursive:!0});let i=ea(r,`${s}.ts`);if(Xn(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';
|
|
478
478
|
import type { Container } from '@beeblock/svelar/container';
|
|
479
479
|
|
|
480
480
|
export class ${s} extends Plugin {
|
|
481
|
-
readonly name = '${
|
|
481
|
+
readonly name = '${n}';
|
|
482
482
|
readonly version = '1.0.0';
|
|
483
483
|
description = '${s} for Svelar';
|
|
484
484
|
|
|
@@ -496,7 +496,7 @@ export class ${s} extends Plugin {
|
|
|
496
496
|
// Clean up resources
|
|
497
497
|
}
|
|
498
498
|
}
|
|
499
|
-
`;
|
|
499
|
+
`;Yn(i,a);let o=this.isDDD()?`src/lib/shared/plugins/${s}.ts`:`src/lib/plugins/${s}.ts`;this.success(`Plugin created: ${o}`)}};import{writeFileSync as ta,mkdirSync as sa,existsSync as ra}from"fs";import{join as ia}from"path";var ct=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=this.sharedDir("scheduler");sa(r,{recursive:!0});let i=ia(r,`${s}.ts`);if(ra(i)){this.warn(`Task ${s} already exists.`);return}let n=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
|
|
500
500
|
|
|
501
501
|
export class ${s} extends ScheduledTask {
|
|
502
502
|
name = '${this.toKebabCase(s)}';
|
|
@@ -529,7 +529,7 @@ export class ${s} extends ScheduledTask {
|
|
|
529
529
|
console.error('${s} failed:', error.message);
|
|
530
530
|
}
|
|
531
531
|
}
|
|
532
|
-
`;
|
|
532
|
+
`;ta(i,n);let a=this.isDDD()?`src/lib/shared/scheduler/${s}.ts`:`src/lib/scheduler/${s}.ts`;this.success(`Scheduled task created: ${a}`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as na,mkdirSync as aa,existsSync as oa}from"fs";import{join as la}from"path";var dt=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=this.sharedDir("jobs");aa(r,{recursive:!0});let i=la(r,`${s}.ts`);if(oa(i)){this.warn(`Job ${s} already exists.`);return}let n=`import { Job } from '@beeblock/svelar/queue';
|
|
533
533
|
|
|
534
534
|
export class ${s} extends Job {
|
|
535
535
|
maxAttempts = 3; // Retry up to 3 times
|
|
@@ -556,10 +556,10 @@ export class ${s} extends Job {
|
|
|
556
556
|
console.log('${s} retrying, attempt', attempt);
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
|
-
`;
|
|
559
|
+
`;na(i,n);let a=this.isDDD()?`src/lib/shared/jobs/${s}.ts`:`src/lib/jobs/${s}.ts`;this.success(`Job created: ${a}`)}};import{writeFileSync as ca,mkdirSync as da,existsSync as ua}from"fs";import{join as ma}from"path";var ut=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=this.sharedDir("commands");da(i,{recursive:!0});let n=ma(i,`${r}.ts`);if(ua(n)){this.warn(`Command ${r} already exists.`);return}let a=t.command??this.deriveCommandName(r),o=`import { Command } from '@beeblock/svelar/cli';
|
|
560
560
|
|
|
561
561
|
export class ${r} extends Command {
|
|
562
|
-
name = '${
|
|
562
|
+
name = '${a}';
|
|
563
563
|
description = 'TODO: Describe your command';
|
|
564
564
|
arguments = ['name']; // Positional args your command accepts
|
|
565
565
|
flags = [
|
|
@@ -570,7 +570,7 @@ export class ${r} extends Command {
|
|
|
570
570
|
async handle(args: string[], flags: Record<string, any>): Promise<void> {
|
|
571
571
|
const name = args[0];
|
|
572
572
|
|
|
573
|
-
this.info('Running ${
|
|
573
|
+
this.info('Running ${a}...');
|
|
574
574
|
|
|
575
575
|
// Your command logic here
|
|
576
576
|
// Use this.bootstrap() if you need database access
|
|
@@ -579,7 +579,7 @@ export class ${r} extends Command {
|
|
|
579
579
|
this.success('Done!');
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
|
-
`;
|
|
582
|
+
`;ca(n,o);let c=this.isDDD()?`src/lib/shared/commands/${r}.ts`:`src/lib/commands/${r}.ts`;this.success(`Command created: ${c}`),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 pa,mkdirSync as ha,existsSync as ga}from"fs";import{join as Hr}from"path";var mt=class extends g{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
|
|
583
583
|
|
|
584
584
|
export default {
|
|
585
585
|
name: env('APP_NAME', 'Svelar'),
|
|
@@ -788,7 +788,7 @@ export default {
|
|
|
788
788
|
},
|
|
789
789
|
},
|
|
790
790
|
};
|
|
791
|
-
`};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=
|
|
791
|
+
`};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=Hr(process.cwd(),"config");ha(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),i=Hr(s,`${r}.ts`);if(ga(i)){this.warn(`Config file config/${r}.ts already exists.`);return}let n=this.templates[r]??this.blankTemplate(r);pa(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';
|
|
792
792
|
|
|
793
793
|
export default {
|
|
794
794
|
// Add your ${e} configuration here
|
|
@@ -797,7 +797,7 @@ export default {
|
|
|
797
797
|
// env<number>('MY_PORT', 3000)
|
|
798
798
|
// env<boolean>('MY_FLAG', false)
|
|
799
799
|
};
|
|
800
|
-
`}};import{writeFileSync as
|
|
800
|
+
`}};import{writeFileSync as fa,mkdirSync as ba,existsSync as va}from"fs";import{join as ya}from"path";var pt=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=this.sharedDir("channels");ba(i,{recursive:!0});let n=ya(i,`${r}.ts`);if(va(n)){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",m=t.presence,h=`${m?"presence":"private"}-${o}.{${c}}`,u=m?this.presenceTemplate(r,h,c):this.privateTemplate(r,h,c);fa(n,u);let f=this.isDDD()?"src/lib/shared/channels":"src/lib/channels";this.success(`Channel created: ${f}/${r}.ts`),this.info(`Channel pattern: ${h}`),this.newLine(),this.info("Register it in src/app.ts or a service provider:"),this.log(` import { register${r} } from './${f.replace("src/","")}/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
|
|
801
801
|
|
|
802
802
|
/**
|
|
803
803
|
* ${e}
|
|
@@ -840,7 +840,7 @@ export function register${e}(): void {
|
|
|
840
840
|
};
|
|
841
841
|
});
|
|
842
842
|
}
|
|
843
|
-
`}};import{writeFileSync as
|
|
843
|
+
`}};import{writeFileSync as wa,mkdirSync as Ca,existsSync as xa}from"fs";import{join as Re}from"path";var ht=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,o=t.rustfs??!0,c=t.meilisearch??!1,m=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:Re(s,"Dockerfile"),content:this.dockerfileTemplate(),label:"Dockerfile"},{path:Re(s,"docker-compose.yml"),content:this.composeTemplate(r,i,n,a,o,c),label:"docker-compose.yml"},{path:Re(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:Re(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"}],u=0,f=0;for(let v of h){if(xa(v.path)&&!m){this.warn(`${v.label} already exists (use --force to overwrite)`),f++;continue}wa(v.path,v.content),this.success(`Created ${v.label}`),u++}if(r!=="sqlite"){let v=Re(s,"docker");Ca(v,{recursive:!0})}this.newLine(),u>0?this.info(`${u} 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
|
|
844
844
|
# Multi-stage build for a lean production image.
|
|
845
845
|
|
|
846
846
|
# Stage 1: Install dependencies & build
|
|
@@ -893,7 +893,7 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \\
|
|
|
893
893
|
|
|
894
894
|
# Start with PM2
|
|
895
895
|
CMD ["pm2-runtime", "ecosystem.config.cjs"]
|
|
896
|
-
`}composeTemplate(e,t,s,r,i=!0,
|
|
896
|
+
`}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 o=[];if(e==="postgres"&&o.push("postgres"),e==="mysql"&&o.push("mysql"),s&&o.push("redis"),t&&o.push("soketi"),r&&o.push("gotenberg"),i&&o.push("rustfs"),n&&o.push("meilisearch"),o.length>0){a.push(" depends_on:");for(let c of o)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(`
|
|
897
897
|
`)}dockerignoreTemplate(){return`# Dependencies
|
|
898
898
|
node_modules
|
|
899
899
|
|
|
@@ -1016,7 +1016,7 @@ module.exports = {
|
|
|
1016
1016
|
},
|
|
1017
1017
|
],
|
|
1018
1018
|
};
|
|
1019
|
-
`}};import{writeFileSync as
|
|
1019
|
+
`}};import{writeFileSync as Pa,mkdirSync as Sa,existsSync as zr}from"fs";import{join as B}from"path";var gt=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,o=[];(a||n)&&o.push({path:B(s,"src/routes/api/broadcasting/auth/+server.ts"),content:this.pusherAuthRoute(),label:"src/routes/api/broadcasting/auth/+server.ts",dirs:[B(s,"src/routes/api/broadcasting/auth")]}),(a||i)&&o.push({path:B(s,"src/routes/api/broadcasting/[channel]/+server.ts"),content:this.sseRoute(),label:"src/routes/api/broadcasting/[channel]/+server.ts",dirs:[B(s,"src/routes/api/broadcasting/[channel]")]}),o.push({path:B(s,"src/lib/broadcasting.ts"),content:a||n?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[B(s,"src/lib")]});let c=B(s,"config/broadcasting.ts");zr(c)||o.push({path:c,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[B(s,"config")]});let m=0,p=0;for(let h of o){if(zr(h.path)&&!r){this.warn(`${h.label} already exists (use --force to overwrite)`),p++;continue}for(let u of h.dirs)Sa(u,{recursive:!0});Pa(h.path,h.content),this.success(`Created ${h.label}`),m++}this.newLine(),m>0?this.info(`${m} 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`/**
|
|
1020
1020
|
* Pusher/Soketi Channel Authorization Endpoint
|
|
1021
1021
|
*
|
|
1022
1022
|
* This route authenticates channel subscriptions from pusher-js.
|
|
@@ -1170,33 +1170,33 @@ export default {
|
|
|
1170
1170
|
},
|
|
1171
1171
|
},
|
|
1172
1172
|
};
|
|
1173
|
-
`}};import{writeFileSync as
|
|
1173
|
+
`}};import{writeFileSync as Ra,mkdirSync as Ta,existsSync as ka}from"fs";import{join as Kr}from"path";var ft=class extends g{name="make:test";description="Create a new test file";arguments=["name"];flags=[{name:"unit",alias:"u",description:"Create a unit test (default)",type:"boolean",default:!1},{name:"feature",alias:"f",description:"Create a feature test",type:"boolean",default:!1},{name:"e2e",alias:"e",description:"Create an e2e (Playwright) test",type:"boolean",default:!1}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a test name.");return}let r="unit";t.feature&&(r="feature"),t.e2e&&(r="e2e");let i=r==="e2e"?".spec.ts":".test.ts",n=Kr(process.cwd(),"tests",r);Ta(n,{recursive:!0});let a=s.endsWith(i)?s:`${s}${i}`,o=Kr(n,a);if(ka(o)){this.warn(`Test file already exists: tests/${r}/${a}`);return}let c;switch(r){case"unit":c=Ea(s);break;case"feature":c=$a(s);break;case"e2e":c=Aa(s);break}Ra(o,c),this.success(`Test created: tests/${r}/${a}`)}};function Ea(l){return`import { describe, it, expect } from 'vitest';
|
|
1174
1174
|
|
|
1175
|
-
describe('${
|
|
1175
|
+
describe('${l}', () => {
|
|
1176
1176
|
it('should work', () => {
|
|
1177
1177
|
expect(true).toBe(true);
|
|
1178
1178
|
});
|
|
1179
1179
|
});
|
|
1180
|
-
`}function $
|
|
1180
|
+
`}function $a(l){return`import { describe, it, expect } from 'vitest';
|
|
1181
1181
|
import { useSvelarTest, assertDatabaseHas } from '@beeblock/svelar/testing';
|
|
1182
1182
|
|
|
1183
|
-
describe('${
|
|
1183
|
+
describe('${l}', () => {
|
|
1184
1184
|
useSvelarTest({ refreshDatabase: true });
|
|
1185
1185
|
|
|
1186
1186
|
it('should work', async () => {
|
|
1187
1187
|
expect(true).toBe(true);
|
|
1188
1188
|
});
|
|
1189
1189
|
});
|
|
1190
|
-
`}function
|
|
1190
|
+
`}function Aa(l){return`import { test, expect } from '@playwright/test';
|
|
1191
1191
|
|
|
1192
|
-
test.describe('${
|
|
1192
|
+
test.describe('${l}', () => {
|
|
1193
1193
|
test('should load the page', async ({ page }) => {
|
|
1194
1194
|
await page.goto('/');
|
|
1195
1195
|
await expect(page).toHaveTitle(/.*/);
|
|
1196
1196
|
});
|
|
1197
1197
|
});
|
|
1198
|
-
`}import{writeFileSync as
|
|
1199
|
-
import { ${i} } from '${
|
|
1198
|
+
`}import{writeFileSync as Da,mkdirSync as La,existsSync as Ma}from"fs";import{join as Wr}from"path";var bt=class extends g{name="make:factory";description="Create a new model factory for testing";arguments=["name"];flags=[{name:"model",alias:"m",description:"The model class name",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a factory name.");return}let r=s.endsWith("Factory")?s:`${s}Factory`,i=t.model||s.replace(/Factory$/,""),n=Wr(process.cwd(),"src","lib","factories");La(n,{recursive:!0});let a=Wr(n,`${r}.ts`);if(Ma(a)){this.warn(`Factory ${r} already exists.`);return}let o=this.resolveModelImport(i),c=`import { Factory } from '@beeblock/svelar/testing';
|
|
1199
|
+
import { ${i} } from '${o}';
|
|
1200
1200
|
|
|
1201
1201
|
export class ${r} extends Factory<${i}> {
|
|
1202
1202
|
model() {
|
|
@@ -1213,7 +1213,7 @@ export class ${r} extends Factory<${i}> {
|
|
|
1213
1213
|
|
|
1214
1214
|
// Singleton instance for convenience
|
|
1215
1215
|
export default new ${r}();
|
|
1216
|
-
`;
|
|
1216
|
+
`;Da(a,c),this.success(`Factory created: src/lib/factories/${r}.ts`)}resolveModelImport(e){if(this.isDDD()){let t=e.toLowerCase();return`$lib/modules/${{User:"auth",Post:"posts"}[e]||t}/${e}`}return`$lib/models/${e}`}};import{writeFileSync as Jr,mkdirSync as Na,existsSync as Vr}from"fs";import{join as Qr}from"path";var vt=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.isDDD()&&this.warn(`No --module specified, using "${i}". Use --module=<name> to target a specific module.`);let n=this.moduleDir(i,"resources");Na(n,{recursive:!0});let a=Qr(n,`${r}.ts`);if(Vr(a)){this.warn(`Resource ${r} already exists.`);return}let o=t.model||this.inferModelName(r),c=this.isDDD()?`./${o}.js`:`../models/${o}.js`,m=this.generateResource(r,o,c);Jr(a,m);let p=this.isDDD()?`src/lib/modules/${i}`:"src/lib/resources";if(this.success(`Resource created: ${p}/${r}.ts`),t.collection){let h=r.replace("Resource","CollectionResource"),u=Qr(n,`${h}.ts`);if(!Vr(u)){let f=this.isDDD()?`./${o}.js`:`../models/${o}.js`,v=this.generateCollectionResource(h,r,o,f);Jr(u,v);let x=this.isDDD()?`src/lib/modules/${i}`:"src/lib/resources";this.success(`Collection resource created: ${x}/${h}.ts`)}}}generateResource(e,t,s=`./${t}.js`){let r=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
|
|
1217
1217
|
import type { ${t} } from '${s}';
|
|
1218
1218
|
|
|
1219
1219
|
// \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
|
|
@@ -1291,7 +1291,7 @@ export class ${e} {
|
|
|
1291
1291
|
.toObject();
|
|
1292
1292
|
}
|
|
1293
1293
|
}
|
|
1294
|
-
`}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as
|
|
1294
|
+
`}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as Ia,mkdirSync as _a,existsSync as ja}from"fs";import{join as Oa}from"path";var yt=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=this.moduleDir(n,"schemas");_a(a,{recursive:!0});let o=Oa(a,`${i}.ts`);if(ja(o)){let h=this.isDDD()?`src/lib/modules/${n}`:"src/lib/schemas";this.warn(`Schema already exists: ${h}/${i}.ts`);return}let c=this.generateSchema(r);Ia(o,c);let m=this.isDDD()?`src/lib/modules/${n}`:"src/lib/schemas";this.success(`Schema created: ${m}/${i}.ts`),this.info(""),this.info(" Use this schema across your entire stack:"),this.info(""),this.info(` Resource: extends Resource<${r}, ${r}Data>`),this.info(` FormRequest: uses create${r}Schema / update${r}Schema`);let p=this.isDDD()?`$lib/modules/${n}/${i}`:`$lib/schemas/${i}`;this.info(` Frontend: import type { ${r}Data } from '${p}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
|
|
1295
1295
|
|
|
1296
1296
|
// \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
|
|
1297
1297
|
//
|
|
@@ -1326,8 +1326,8 @@ export const update${e}Schema = create${e}Schema.partial();
|
|
|
1326
1326
|
export type ${e}Data = z.infer<typeof ${t}Schema>;
|
|
1327
1327
|
export type Create${e}Input = z.infer<typeof create${e}Schema>;
|
|
1328
1328
|
export type Update${e}Input = z.infer<typeof update${e}Schema>;
|
|
1329
|
-
`}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
|
|
1330
|
-
import type { ${r} } from '${
|
|
1329
|
+
`}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 qa,mkdirSync as Ua,existsSync as Fa}from"fs";import{join as Ba}from"path";var wt=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=this.moduleDir(i,"observers");Ua(n,{recursive:!0});let a=Ba(n,`${s}.ts`);if(Fa(a)){this.warn(`Observer ${s} already exists at ${a}`);return}let o=this.isDDD()?`./${r}.js`:`../models/${r}.js`,c=`import { ModelObserver } from '@beeblock/svelar/orm';
|
|
1330
|
+
import type { ${r} } from '${o}';
|
|
1331
1331
|
|
|
1332
1332
|
export class ${s} extends ModelObserver {
|
|
1333
1333
|
// Fires before a new ${r} is inserted
|
|
@@ -1364,7 +1364,7 @@ export class ${s} extends ModelObserver {
|
|
|
1364
1364
|
// async deleted(${r.toLowerCase()}: ${r}) {
|
|
1365
1365
|
// }
|
|
1366
1366
|
}
|
|
1367
|
-
`;
|
|
1367
|
+
`;qa(a,c);let m=this.isDDD()?`src/lib/modules/${i}`:"src/lib/observers";this.success(`Observer created: ${m}/${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 Ha,mkdirSync as za,existsSync as Ka}from"fs";import{join as Wa}from"path";var Ct=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.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=this.moduleDir(r,"events");za(i,{recursive:!0});let n=Wa(i,`${s}.ts`);if(Ka(n)){this.warn(`Event ${s} already exists at ${n}`);return}let a=`/**
|
|
1368
1368
|
* ${s} Event
|
|
1369
1369
|
*
|
|
1370
1370
|
* Dispatched when ... (describe when this event fires).
|
|
@@ -1382,7 +1382,7 @@ export class ${s} {
|
|
|
1382
1382
|
// public readonly metadata?: Record<string, any>,
|
|
1383
1383
|
) {}
|
|
1384
1384
|
}
|
|
1385
|
-
`;
|
|
1385
|
+
`;Ha(n,a);let o=this.isDDD()?`src/lib/modules/${r}`:"src/lib/events";this.success(`Event created: ${o}/${s}.ts`)}};import{writeFileSync as Ja,mkdirSync as Va,existsSync as Qa}from"fs";import{join as Ga}from"path";var xt=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.isDDD()&&this.warn(`No --module specified. Using "${r}" as module. Consider: --module ${r}`);let i=this.moduleDir(r,"listeners");Va(i,{recursive:!0});let n=Ga(i,`${s}.ts`);if(Qa(n)){this.warn(`Listener ${s} already exists at ${n}`);return}let a=t.event||"any",o=t.event?this.isDDD()?`./${t.event}.js`:`../events/${t.event}.js`:"",c=t.event?`import type { ${t.event} } from '${o}';
|
|
1386
1386
|
|
|
1387
1387
|
`:"",m=t.event||"any",p=`import { Listener } from '@beeblock/svelar/events';
|
|
1388
1388
|
${c}export class ${s} extends Listener<${m}> {
|
|
@@ -1396,16 +1396,16 @@ ${c}export class ${s} extends Listener<${m}> {
|
|
|
1396
1396
|
// return true;
|
|
1397
1397
|
// }
|
|
1398
1398
|
}
|
|
1399
|
-
`;
|
|
1400
|
-
`),c=`import { ${t} } from '${
|
|
1399
|
+
`;Ja(n,p);let h=this.isDDD()?`src/lib/modules/${r}`:"src/lib/listeners";this.success(`Listener created: ${h}/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as Ya,mkdirSync as Za,existsSync as Xa}from"fs";import{join as Gr}from"path";var Pt=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=Gr(process.cwd(),"src","routes",...e.split("/"));Za(i,{recursive:!0});let n=Gr(i,"+server.ts");if(Xa(n)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let a=this.isDDD()?`$lib/modules/${s}/${t}.js`:`$lib/controllers/${t}.js`,o=r.map(m=>`export const ${m.method} = ctrl.handle('${m.handler}');`).join(`
|
|
1400
|
+
`),c=`import { ${t} } from '${a}';
|
|
1401
1401
|
|
|
1402
1402
|
const ctrl = new ${t}();
|
|
1403
|
-
${
|
|
1404
|
-
`;
|
|
1405
|
-
`);let a=Math.max(6,...i.map(m=>m.method.length)),n=Math.max(4,...i.map(m=>m.path.length)),l=Math.max(7,...i.map(m=>m.handler.length)),c=` ${"METHOD".padEnd(a)} ${"PATH".padEnd(n)} ${"HANDLER".padEnd(l)} FILE`;this.log(`\x1B[2m${c}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(a)} ${"\u2500".repeat(n)} ${"\u2500".repeat(l)} ${"\u2500".repeat(20)}\x1B[0m`);for(let m of i){let h=`${this.getMethodColor(m.method)}${m.method.padEnd(a)}\x1B[0m`,u=m.path.padEnd(n),b=`\x1B[2m${m.handler.padEnd(l)}\x1B[0m`,v=`\x1B[2m${m.file}\x1B[0m`;this.log(` ${h} ${u} ${b} ${v}`)}this.log("")}scanRoutes(e,t){let s=[],r=to(e);for(let i of r){let a=Zr(e,i);if(so(a).isDirectory()){s.push(...this.scanRoutes(a,t));continue}i==="+server.ts"||i==="+server.js"?s.push(...this.parseServerFile(a,t)):(i==="+page.server.ts"||i==="+page.server.js")&&s.push(...this.parsePageServerFile(a,t))}return s}parseServerFile(e,t){let s=[],r=Xr(e,"utf-8"),i=this.filePathToUrl(e,t),a=Ps(process.cwd(),e).split(Ss).join("/"),n=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,l;for(;(l=n.exec(r))!==null;){let c=l[1],m=this.extractHandler(r,c);s.push({method:c,path:i,handler:m,file:a})}return s}parsePageServerFile(e,t){let s=[],r=Xr(e,"utf-8"),i=this.filePathToUrl(e,t),a=Ps(process.cwd(),e).split(Ss).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:i,handler:"load()",file:a});let n=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(n){let l=n[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:a})}return s}filePathToUrl(e,t){let s=Ps(t,e).split(Ss).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+)`),a=e.match(i);return a?`${a[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 ro}from"fs";import{join as si}from"path";import{pathToFileURL as io}from"url";var Rt=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(()=>(ks(),ti)),i=new r,a=si(process.cwd(),"src","lib","database","migrations"),n=await this.loadMigrations(a);if(t.status){let c=await i.status(n);this.table(["Migration","Status","Batch"],c.map(m=>[m.name,m.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",m.batch?.toString()??"-"]));return}if(t.rollback){this.info("Rolling back last batch...");let c=await i.rollback(n);if(c.length===0)this.info("Nothing to rollback.");else for(let m of c)this.success(`Rolled back: ${m}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let c=await i.reset(n);if(c.length===0)this.info("Nothing to reset.");else for(let m of c)this.success(`Rolled back: ${m}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let c=await i.refresh(n);for(let m of c.reset)this.success(`Rolled back: ${m}`);for(let m of c.migrated)this.success(`Migrated: ${m}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let c=await i.fresh(n);if(c.dropped.length>0)for(let m of c.dropped)this.success(`Dropped table: ${m}`);this.newLine(),this.info("Re-running all migrations...");for(let m of c.migrated)this.success(`Migrated: ${m}`);return}this.info("Running migrations...");let l=await i.run(n);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=ro(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=si(e,r);try{let a=await import(io(i).href),n=a.default??Object.values(a).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.up=="function");n?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:i,migration:new n}):this.warn(`No migration class found in: ${r}`)}catch(a){let n;try{n=a instanceof Error?a.message:String(a)}catch{n=JSON.stringify(a)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${n}`)}}return s}};import{join as Es}from"path";import{pathToFileURL as ao}from"url";import{existsSync as ri}from"fs";var Tt=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=Es(process.cwd(),"src","lib","database","seeders"),r=t.class?Es(s,`${t.class}.ts`):Es(s,"DatabaseSeeder.ts"),i=r;ri(i)||(i=i.replace(/\.ts$/,".js")),ri(i)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let a=await import(ao(i).href),n=a.default??a.DatabaseSeeder??Object.values(a).find(c=>typeof c=="function"&&c.prototype&&typeof c.prototype.run=="function");(!n||typeof n!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new n().run(),this.success("Database seeded successfully.")}catch(a){let n=a instanceof Error?a.message:String(a);this.error(`Seeding failed: ${n}`),a?.stack&&console.error(a.stack),process.exit(1)}}};import{existsSync as co,readdirSync as uo}from"fs";import{join as Ds}from"path";import{pathToFileURL as mo}from"url";var $t=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(()=>(oi(),ni)),r=new s;r.persistToDatabase();let i=Ds(process.cwd(),"src","lib","shared","scheduler"),a=Ds(process.cwd(),"src","lib","scheduler"),n=co(i)?i:a,l=await this.loadTasks(n);if(l.length===0){this.warn("No scheduled tasks found in src/lib/shared/scheduler/ or src/lib/scheduler/");return}for(let p of l)r.register(p),this.info(`Registered task: ${p.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let p=await r.run();if(p.length===0)this.info("No tasks were due.");else for(let h of p)h.success?this.success(`${h.task}: completed in ${h.duration}ms`):this.error(`${h.task}: failed \u2014 ${h.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let c=async()=>{let p=await r.run();for(let h of p){let u=new Date().toISOString().replace("T"," ").slice(0,19);h.success?this.success(`[${u}] ${h.task}: completed in ${h.duration}ms`):this.error(`[${u}] ${h.task}: failed \u2014 ${h.error}`)}};await c();let m=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(m/1e3)}s.`),await new Promise(p=>setTimeout(p,m)),await c(),setInterval(c,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=uo(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let i=Ds(e,r);try{let a=await import(mo(i).href),n=a.default??Object.values(a).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.handle=="function");if(n){let l=new n;l.schedule(),s.push(l)}}catch(a){this.error(`Failed to load task ${r}: ${a.message??a}`)}}return s}};var Lt=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(()=>(ee(),Le)),r=t.queue??"default",i=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,a=t["max-time"]?parseInt(t["max-time"]):void 0,n=t.sleep?parseInt(t.sleep):1e3;if(this.info(`Processing queue "${r}"...`),i&&this.info(`Will stop after ${i} jobs.`),a&&this.info(`Will stop after ${a} seconds.`),this.newLine(),t.once){let m=await s.work({queue:r,maxJobs:1,sleep:0});m===0?this.info("No jobs to process."):this.success(`Processed ${m} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let l=Date.now(),c=0;for(;;){if(a&&(Date.now()-l)/1e3>=a){this.info(`Max time (${a}s) reached. Stopping.`);break}if(i&&c>=i){this.info(`Max jobs (${i}) reached. Stopping.`);break}let m=await s.work({queue:r,maxJobs:1,sleep:0});if(m>0){c+=m;let p=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${p}] Processed ${m} job(s) (total: ${c})`)}else await new Promise(p=>setTimeout(p,n))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${c}`)}};var _t=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(()=>(ee(),Le)),r=await s.failed();if(r.length===0){this.info("No failed jobs.");return}this.info(`Found ${r.length} failed job(s):
|
|
1406
|
-
`);for(let i of r){let
|
|
1407
|
-
`)[0]}`),this.log("")}}};var
|
|
1408
|
-
`);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(
|
|
1403
|
+
${o}
|
|
1404
|
+
`;Ya(n,c),this.success(`Route created: src/routes/${e}/+server.ts`);for(let m of r)this.info(` ${m.method} /${e} \u2192 ${t}.${m.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 Yr,relative as Ps,sep as Ss}from"path";import{existsSync as eo,readdirSync as to,readFileSync as Zr,statSync as so}from"fs";var St=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=Yr(process.cwd(),"src","routes");if(!eo(s)){this.error("No src/routes/ directory found.");return}let i=this.scanRoutes(s,s);if(t.api&&(i=i.filter(m=>m.path.startsWith("/api"))),t.method){let m=t.method.toUpperCase();i=i.filter(p=>p.method===m)}if(i.sort((m,p)=>m.path.localeCompare(p.path)||m.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)
|
|
1405
|
+
`);let n=Math.max(6,...i.map(m=>m.method.length)),a=Math.max(4,...i.map(m=>m.path.length)),o=Math.max(7,...i.map(m=>m.handler.length)),c=` ${"METHOD".padEnd(n)} ${"PATH".padEnd(a)} ${"HANDLER".padEnd(o)} FILE`;this.log(`\x1B[2m${c}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(n)} ${"\u2500".repeat(a)} ${"\u2500".repeat(o)} ${"\u2500".repeat(20)}\x1B[0m`);for(let m of i){let h=`${this.getMethodColor(m.method)}${m.method.padEnd(n)}\x1B[0m`,u=m.path.padEnd(a),f=`\x1B[2m${m.handler.padEnd(o)}\x1B[0m`,v=`\x1B[2m${m.file}\x1B[0m`;this.log(` ${h} ${u} ${f} ${v}`)}this.log("")}scanRoutes(e,t){let s=[],r=to(e);for(let i of r){let n=Yr(e,i);if(so(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=Zr(e,"utf-8"),i=this.filePathToUrl(e,t),n=Ps(process.cwd(),e).split(Ss).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],m=this.extractHandler(r,c);s.push({method:c,path:i,handler:m,file:n})}return s}parsePageServerFile(e,t){let s=[],r=Zr(e,"utf-8"),i=this.filePathToUrl(e,t),n=Ps(process.cwd(),e).split(Ss).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 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"?i:`${i}?/${c}`,handler:`actions.${c}()`,file:n})}return s}filePathToUrl(e,t){let s=Ps(t,e).split(Ss).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 ro}from"fs";import{join as ti}from"path";import{pathToFileURL as io}from"url";var Rt=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(()=>(ks(),ei)),i=new r,n=ti(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(m=>[m.name,m.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",m.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 m of c)this.success(`Rolled back: ${m}`);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 m of c)this.success(`Rolled back: ${m}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let c=await i.refresh(a);for(let m of c.reset)this.success(`Rolled back: ${m}`);for(let m of c.migrated)this.success(`Migrated: ${m}`);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 m of c.dropped)this.success(`Dropped table: ${m}`);this.newLine(),this.info("Re-running all migrations...");for(let m of c.migrated)this.success(`Migrated: ${m}`);return}this.info("Running migrations...");let o=await i.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=ro(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=ti(e,r);try{let n=await import(io(i).href),a=n.default??Object.values(n).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: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 Es}from"path";import{pathToFileURL as no}from"url";import{existsSync as si}from"fs";var Tt=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=Es(process.cwd(),"src","lib","database","seeders"),r=t.class?Es(s,`${t.class}.ts`):Es(s,"DatabaseSeeder.ts"),i=r;si(i)||(i=i.replace(/\.ts$/,".js")),si(i)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let n=await import(no(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{existsSync as co,readdirSync as uo}from"fs";import{join as Ds}from"path";import{pathToFileURL as mo}from"url";var $t=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(()=>(ai(),ni)),r=new s;r.persistToDatabase();let i=Ds(process.cwd(),"src","lib","shared","scheduler"),n=Ds(process.cwd(),"src","lib","scheduler"),a=co(i)?i:n,o=await this.loadTasks(a);if(o.length===0){this.warn("No scheduled tasks found in src/lib/shared/scheduler/ or src/lib/scheduler/");return}for(let p of o)r.register(p),this.info(`Registered task: ${p.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let p=await r.run();if(p.length===0)this.info("No tasks were due.");else for(let h of p)h.success?this.success(`${h.task}: completed in ${h.duration}ms`):this.error(`${h.task}: failed \u2014 ${h.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let c=async()=>{let p=await r.run();for(let h of p){let u=new Date().toISOString().replace("T"," ").slice(0,19);h.success?this.success(`[${u}] ${h.task}: completed in ${h.duration}ms`):this.error(`[${u}] ${h.task}: failed \u2014 ${h.error}`)}};await c();let m=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(m/1e3)}s.`),await new Promise(p=>setTimeout(p,m)),await c(),setInterval(c,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=uo(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let i=Ds(e,r);try{let n=await import(mo(i).href),a=n.default??Object.values(n).find(o=>typeof o=="function"&&o.prototype&&typeof o.prototype.handle=="function");if(a){let o=new a;o.schedule(),s.push(o)}}catch(n){this.error(`Failed to load task ${r}: ${n.message??n}`)}}return s}};var Lt=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(()=>(re(),Le)),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 m=await s.work({queue:r,maxJobs:1,sleep:0});m===0?this.info("No jobs to process."):this.success(`Processed ${m} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let o=Date.now(),c=0;for(;;){if(n&&(Date.now()-o)/1e3>=n){this.info(`Max time (${n}s) reached. Stopping.`);break}if(i&&c>=i){this.info(`Max jobs (${i}) reached. Stopping.`);break}let m=await s.work({queue:r,maxJobs:1,sleep:0});if(m>0){c+=m;let p=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${p}] Processed ${m} job(s) (total: ${c})`)}else await new Promise(p=>setTimeout(p,a))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${c}`)}};var Mt=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(()=>(re(),Le)),r=await s.failed();if(r.length===0){this.info("No failed jobs.");return}this.info(`Found ${r.length} failed job(s):
|
|
1406
|
+
`);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(`
|
|
1407
|
+
`)[0]}`),this.log("")}}};var Nt=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(()=>(re(),Le));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 It=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(()=>(re(),Le)),r=await s.flushFailed();r===0?this.info("No failed jobs to flush."):this.success(`Flushed ${r} failed job record(s).`)}};var cs=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.
|
|
1408
|
+
`);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(rn(),sn));for(let[r,i]of Object.entries(s))t.context[r]=i;t.context.DB=s.Connection,t.context.Schema=s.Schema,this.log("Available: Model, QueryBuilder, Connection, Schema, Hash, Cache, Event, Log, ..."),this.log("")}catch(s){this.warn(`Could not preload all modules: ${s.message}`)}try{let{readdirSync:s}=await import("fs"),{join:r}=await import("path"),{pathToFileURL:i}=await import("url"),{existsSync:n}=await import("fs"),a=r(process.cwd(),"src","lib","models"),o=r(process.cwd(),"src","lib","modules"),c=[],m=a;if(n(a))m=a,c=s(a).filter(p=>(p.endsWith(".ts")||p.endsWith(".js"))&&!p.startsWith("index"));else if(n(o)){m=o;for(let p of s(o,{withFileTypes:!0})){if(!p.isDirectory())continue;let h=r(o,p.name);for(let u of s(h))(u.endsWith(".ts")||u.endsWith(".js"))&&(u.startsWith("index")||u.includes("Controller")||u.includes("Service")||u.includes("Repository")||u.includes("Request")||u.includes("Resource")||u.includes("schema")||u.includes("gates")||c.push(r(p.name,u)))}}for(let p of c)try{let h=await import(i(r(m,p)).href);for(let[u,f]of Object.entries(h))typeof f=="function"&&(t.context[u]=f)}catch{}c.length>0&&this.log(`Loaded models: ${c.map(p=>p.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var d=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",test:"vitest run","test:watch":"vitest","test:e2e":"playwright test","test:coverage":"vitest run --coverage"},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",vitest:"^2.1.0","@playwright/test":"^1.48.0"},dependencies:{"better-sqlite3":"^11.0.0","drizzle-orm":"^0.38.0","@beeblock/svelar":`^${t}`,"bits-ui":"^1.0.0",clsx:"^2.1.0",exceljs:"^4.4.0","mode-watcher":"^0.5.0",pdfkit:"^0.18.0","sveltekit-superforms":"^2.22.0","tailwind-merge":"^3.0.0","tailwind-variants":"^1.0.0","tw-animate-css":"^1.2.0",zod:"^3.23.0"}},null,2)+`
|
|
1409
1409
|
`}static svelteConfig(){return`import adapter from '@sveltejs/adapter-auto';
|
|
1410
1410
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
1411
1411
|
|
|
@@ -1481,7 +1481,7 @@ export default defineConfig({
|
|
|
1481
1481
|
'@beeblock/svelar/services': resolve(svelarRoot, 'dist/services/index.js'),
|
|
1482
1482
|
'@beeblock/svelar/session': resolve(svelarRoot, 'dist/session/index.js'),
|
|
1483
1483
|
'@beeblock/svelar/storage': resolve(svelarRoot, 'dist/storage/index.js'),
|
|
1484
|
-
|
|
1484
|
+
|
|
1485
1485
|
'@beeblock/svelar/support': resolve(svelarRoot, 'dist/support/index.js'),
|
|
1486
1486
|
'@beeblock/svelar/teams': resolve(svelarRoot, 'dist/teams/index.js'),
|
|
1487
1487
|
'@beeblock/svelar/uploads': resolve(svelarRoot, 'dist/uploads/index.js'),
|
|
@@ -1502,10 +1502,10 @@ export default defineConfig({
|
|
|
1502
1502
|
},
|
|
1503
1503
|
ssr: {
|
|
1504
1504
|
// Process lucide-svelte during SSR (Svelte components must be compiled)
|
|
1505
|
-
noExternal: ['lucide-svelte', '@tabler/icons-svelte'],
|
|
1505
|
+
noExternal: ['lucide-svelte', '@tabler/icons-svelte', 'bits-ui'],
|
|
1506
1506
|
},
|
|
1507
1507
|
optimizeDeps: {
|
|
1508
|
-
exclude: ['lucide-svelte', '@tabler/icons-svelte'],
|
|
1508
|
+
exclude: ['lucide-svelte', '@tabler/icons-svelte', 'bits-ui'],
|
|
1509
1509
|
},
|
|
1510
1510
|
});
|
|
1511
1511
|
`}static tsConfig(){return JSON.stringify({extends:"./.svelte-kit/tsconfig.json",compilerOptions:{allowJs:!0,checkJs:!0,esModuleInterop:!0,forceConsistentCasingInFileNames:!0,resolveJsonModule:!0,skipLibCheck:!0,sourceMap:!0,strict:!0,moduleResolution:"bundler"}},null,2)+`
|
|
@@ -1592,13 +1592,139 @@ export default defineConfig({
|
|
|
1592
1592
|
<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"/>
|
|
1593
1593
|
<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"/>
|
|
1594
1594
|
</svg>`}static appCss(){return`@import "tailwindcss";
|
|
1595
|
+
@import "tw-animate-css";
|
|
1595
1596
|
@source "../node_modules/@beeblock/svelar/src/ui";
|
|
1596
1597
|
|
|
1597
|
-
@
|
|
1598
|
+
@custom-variant dark (&:is(.dark *));
|
|
1599
|
+
|
|
1600
|
+
:root {
|
|
1601
|
+
--radius: 0.625rem;
|
|
1602
|
+
--background: oklch(1 0 0);
|
|
1603
|
+
--foreground: oklch(0.129 0.042 264.695);
|
|
1604
|
+
--card: oklch(1 0 0);
|
|
1605
|
+
--card-foreground: oklch(0.129 0.042 264.695);
|
|
1606
|
+
--popover: oklch(1 0 0);
|
|
1607
|
+
--popover-foreground: oklch(0.129 0.042 264.695);
|
|
1608
|
+
--primary: oklch(0.208 0.042 265.755);
|
|
1609
|
+
--primary-foreground: oklch(0.984 0.003 247.858);
|
|
1610
|
+
--secondary: oklch(0.968 0.007 264.536);
|
|
1611
|
+
--secondary-foreground: oklch(0.208 0.042 265.755);
|
|
1612
|
+
--muted: oklch(0.968 0.007 264.536);
|
|
1613
|
+
--muted-foreground: oklch(0.554 0.023 264.364);
|
|
1614
|
+
--accent: oklch(0.968 0.007 264.536);
|
|
1615
|
+
--accent-foreground: oklch(0.208 0.042 265.755);
|
|
1616
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
1617
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
1618
|
+
--border: oklch(0.929 0.013 264.531);
|
|
1619
|
+
--input: oklch(0.929 0.013 264.531);
|
|
1620
|
+
--ring: oklch(0.869 0.022 264.401);
|
|
1621
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
1622
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
1623
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
1624
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
1625
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
1626
|
+
--sidebar: oklch(0.984 0.003 247.858);
|
|
1627
|
+
--sidebar-foreground: oklch(0.554 0.023 264.364);
|
|
1628
|
+
--sidebar-primary: oklch(0.208 0.042 265.755);
|
|
1629
|
+
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
|
1630
|
+
--sidebar-accent: oklch(0.968 0.007 264.536);
|
|
1631
|
+
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
|
|
1632
|
+
--sidebar-border: oklch(0.929 0.013 264.531);
|
|
1633
|
+
--sidebar-ring: oklch(0.869 0.022 264.401);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.dark {
|
|
1637
|
+
--background: oklch(0.129 0.042 264.695);
|
|
1638
|
+
--foreground: oklch(0.984 0.003 247.858);
|
|
1639
|
+
--card: oklch(0.129 0.042 264.695);
|
|
1640
|
+
--card-foreground: oklch(0.984 0.003 247.858);
|
|
1641
|
+
--popover: oklch(0.129 0.042 264.695);
|
|
1642
|
+
--popover-foreground: oklch(0.984 0.003 247.858);
|
|
1643
|
+
--primary: oklch(0.984 0.003 247.858);
|
|
1644
|
+
--primary-foreground: oklch(0.208 0.042 265.755);
|
|
1645
|
+
--secondary: oklch(0.279 0.041 260.873);
|
|
1646
|
+
--secondary-foreground: oklch(0.984 0.003 247.858);
|
|
1647
|
+
--muted: oklch(0.279 0.041 260.873);
|
|
1648
|
+
--muted-foreground: oklch(0.711 0.019 264.147);
|
|
1649
|
+
--accent: oklch(0.279 0.041 260.873);
|
|
1650
|
+
--accent-foreground: oklch(0.984 0.003 247.858);
|
|
1651
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
1652
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
1653
|
+
--border: oklch(0.279 0.041 260.873);
|
|
1654
|
+
--input: oklch(0.279 0.041 260.873);
|
|
1655
|
+
--ring: oklch(0.442 0.036 264.591);
|
|
1656
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
1657
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
1658
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
1659
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
1660
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
1661
|
+
--sidebar: oklch(0.129 0.042 264.695);
|
|
1662
|
+
--sidebar-foreground: oklch(0.984 0.003 247.858);
|
|
1663
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
1664
|
+
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
|
1665
|
+
--sidebar-accent: oklch(0.279 0.041 260.873);
|
|
1666
|
+
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
|
|
1667
|
+
--sidebar-border: oklch(0.279 0.041 260.873);
|
|
1668
|
+
--sidebar-ring: oklch(0.442 0.036 264.591);
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
@theme inline {
|
|
1672
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
1673
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
1674
|
+
--radius-lg: var(--radius);
|
|
1675
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
1676
|
+
--color-background: var(--background);
|
|
1677
|
+
--color-foreground: var(--foreground);
|
|
1678
|
+
--color-card: var(--card);
|
|
1679
|
+
--color-card-foreground: var(--card-foreground);
|
|
1680
|
+
--color-popover: var(--popover);
|
|
1681
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
1682
|
+
--color-primary: var(--primary);
|
|
1683
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
1684
|
+
--color-secondary: var(--secondary);
|
|
1685
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
1686
|
+
--color-muted: var(--muted);
|
|
1687
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
1688
|
+
--color-accent: var(--accent);
|
|
1689
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
1690
|
+
--color-destructive: var(--destructive);
|
|
1691
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
1692
|
+
--color-border: var(--border);
|
|
1693
|
+
--color-input: var(--input);
|
|
1694
|
+
--color-ring: var(--ring);
|
|
1695
|
+
--color-chart-1: var(--chart-1);
|
|
1696
|
+
--color-chart-2: var(--chart-2);
|
|
1697
|
+
--color-chart-3: var(--chart-3);
|
|
1698
|
+
--color-chart-4: var(--chart-4);
|
|
1699
|
+
--color-chart-5: var(--chart-5);
|
|
1700
|
+
--color-sidebar: var(--sidebar);
|
|
1701
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
1702
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
1703
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
1704
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
1705
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
1706
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
1707
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
1598
1708
|
--color-brand: #ff3e00;
|
|
1599
1709
|
--color-brand-dark: #e03500;
|
|
1600
1710
|
--color-brand-light: #fff5f2;
|
|
1601
1711
|
}
|
|
1712
|
+
|
|
1713
|
+
@layer base {
|
|
1714
|
+
* {
|
|
1715
|
+
@apply border-border;
|
|
1716
|
+
}
|
|
1717
|
+
body {
|
|
1718
|
+
@apply bg-background text-foreground;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
`}static componentsJson(){return JSON.stringify({$schema:"https://shadcn-svelte.com/schema.json",tailwind:{css:"src/app.css",baseColor:"slate"},aliases:{lib:"$lib",utils:"$lib/utils",components:"$lib/components",ui:"$lib/components/ui",hooks:"$lib/hooks"},typescript:!0,registry:"https://shadcn-svelte.com/registry"},null,2)+`
|
|
1722
|
+
`}static utilsCn(){return`import { type ClassValue, clsx } from "clsx";
|
|
1723
|
+
import { twMerge } from "tailwind-merge";
|
|
1724
|
+
|
|
1725
|
+
export function cn(...inputs: ClassValue[]) {
|
|
1726
|
+
return twMerge(clsx(inputs));
|
|
1727
|
+
}
|
|
1602
1728
|
`}static appTs(){return`/**
|
|
1603
1729
|
* Svelar Application Bootstrap
|
|
1604
1730
|
*
|
|
@@ -1705,15 +1831,6 @@ Features.configure({ driver: 'database' });
|
|
|
1705
1831
|
// \u2500\u2500 PDF (PDFKit \u2014 no Docker needed) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1706
1832
|
PDF.configure({ driver: 'pdfkit' });
|
|
1707
1833
|
|
|
1708
|
-
// \u2500\u2500 Stripe (billing \u2014 uncomment and npm install stripe) \u2500\u2500
|
|
1709
|
-
// import { Stripe } from '@beeblock/svelar/stripe';
|
|
1710
|
-
// Stripe.configure({
|
|
1711
|
-
// secretKey: process.env.STRIPE_SECRET_KEY ?? '',
|
|
1712
|
-
// publishableKey: process.env.STRIPE_PUBLISHABLE_KEY ?? '',
|
|
1713
|
-
// webhookSecret: process.env.STRIPE_WEBHOOK_SECRET ?? '',
|
|
1714
|
-
// currency: 'usd',
|
|
1715
|
-
// });
|
|
1716
|
-
|
|
1717
1834
|
// \u2500\u2500 Dashboard \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\u2500
|
|
1718
1835
|
configureDashboard({ enabled: true, prefix: '/admin' });
|
|
1719
1836
|
|
|
@@ -1815,11 +1932,6 @@ DB_PATH=database.db
|
|
|
1815
1932
|
# MEILISEARCH_HOST=http://localhost:7700
|
|
1816
1933
|
# MEILISEARCH_KEY=
|
|
1817
1934
|
|
|
1818
|
-
# Stripe (billing and subscriptions \u2014 npm install stripe)
|
|
1819
|
-
# STRIPE_SECRET_KEY=sk_test_...
|
|
1820
|
-
# STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
1821
|
-
# STRIPE_WEBHOOK_SECRET=whsec_...
|
|
1822
|
-
|
|
1823
1935
|
# PDF (default driver is pdfkit \u2014 no config needed)
|
|
1824
1936
|
# Switch to Gotenberg for pixel-perfect HTML rendering:
|
|
1825
1937
|
# PDF_DRIVER=gotenberg
|
|
@@ -1829,6 +1941,12 @@ DB_PATH=database.db
|
|
|
1829
1941
|
AUTH_OTP_ENABLED=true
|
|
1830
1942
|
AUTH_EMAIL_VERIFICATION_REQUIRED=false
|
|
1831
1943
|
|
|
1944
|
+
# Stripe (optional \u2014 install @beeblock/svelar-stripe plugin)
|
|
1945
|
+
# STRIPE_SECRET_KEY=sk_test_...
|
|
1946
|
+
# STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
1947
|
+
# STRIPE_WEBHOOK_SECRET=whsec_...
|
|
1948
|
+
# STRIPE_CURRENCY=usd
|
|
1949
|
+
|
|
1832
1950
|
# Broadcasting (optional \u2014 Pusher/Soketi WebSocket)
|
|
1833
1951
|
# PUSHER_KEY=app-key
|
|
1834
1952
|
# PUSHER_SECRET=app-secret
|
|
@@ -3442,19 +3560,19 @@ export const actions: Actions = {
|
|
|
3442
3560
|
</div>
|
|
3443
3561
|
|
|
3444
3562
|
<div class="text-center">
|
|
3445
|
-
<a href="/forgot-password" class="text-sm text-
|
|
3563
|
+
<a href="/forgot-password" class="text-sm text-muted-foreground hover:text-brand hover:underline">Forgot your password?</a>
|
|
3446
3564
|
</div>
|
|
3447
3565
|
|
|
3448
3566
|
{#if data.otpEnabled}
|
|
3449
3567
|
<div class="text-center">
|
|
3450
|
-
<a href="/otp-login" class="text-sm text-
|
|
3568
|
+
<a href="/otp-login" class="text-sm text-muted-foreground hover:text-brand hover:underline">Sign in with a code instead</a>
|
|
3451
3569
|
</div>
|
|
3452
3570
|
{/if}
|
|
3453
3571
|
</form>
|
|
3454
3572
|
</CardContent>
|
|
3455
3573
|
|
|
3456
3574
|
<CardFooter class="border-t pt-6">
|
|
3457
|
-
<p class="text-sm text-center w-full text-
|
|
3575
|
+
<p class="text-sm text-center w-full text-muted-foreground">
|
|
3458
3576
|
Don't have an account?
|
|
3459
3577
|
<a href="/register" class="font-medium text-brand hover:underline">Create one</a>
|
|
3460
3578
|
</p>
|
|
@@ -3610,7 +3728,7 @@ export const actions: Actions = {
|
|
|
3610
3728
|
</CardContent>
|
|
3611
3729
|
|
|
3612
3730
|
<CardFooter class="border-t pt-6">
|
|
3613
|
-
<p class="text-sm text-center w-full text-
|
|
3731
|
+
<p class="text-sm text-center w-full text-muted-foreground">
|
|
3614
3732
|
Already have an account?
|
|
3615
3733
|
<a href="/login" class="font-medium text-brand hover:underline">Sign in</a>
|
|
3616
3734
|
</p>
|
|
@@ -3708,7 +3826,7 @@ export const actions: Actions = {
|
|
|
3708
3826
|
</CardContent>
|
|
3709
3827
|
|
|
3710
3828
|
<CardFooter class="border-t pt-6">
|
|
3711
|
-
<p class="text-sm text-center w-full text-
|
|
3829
|
+
<p class="text-sm text-center w-full text-muted-foreground">
|
|
3712
3830
|
Remember your password?
|
|
3713
3831
|
<a href="/login" class="font-medium text-brand hover:underline">Sign in</a>
|
|
3714
3832
|
</p>
|
|
@@ -3965,7 +4083,7 @@ export const actions: Actions = {
|
|
|
3965
4083
|
|
|
3966
4084
|
<button
|
|
3967
4085
|
type="button"
|
|
3968
|
-
class="w-full text-sm text-
|
|
4086
|
+
class="w-full text-sm text-muted-foreground hover:text-brand hover:underline"
|
|
3969
4087
|
onclick={() => { codeSent = false; }}
|
|
3970
4088
|
>
|
|
3971
4089
|
Use a different email
|
|
@@ -3975,7 +4093,7 @@ export const actions: Actions = {
|
|
|
3975
4093
|
</CardContent>
|
|
3976
4094
|
|
|
3977
4095
|
<CardFooter class="border-t pt-6">
|
|
3978
|
-
<p class="text-sm text-center w-full text-
|
|
4096
|
+
<p class="text-sm text-center w-full text-muted-foreground">
|
|
3979
4097
|
Prefer a password?
|
|
3980
4098
|
<a href="/login" class="font-medium text-brand hover:underline">Sign in with password</a>
|
|
3981
4099
|
</p>
|
|
@@ -4054,7 +4172,6 @@ export const load = guardAuth();
|
|
|
4054
4172
|
import LayoutDashboard from 'lucide-svelte/icons/layout-dashboard';
|
|
4055
4173
|
import KeyRound from 'lucide-svelte/icons/key-round';
|
|
4056
4174
|
import Users from 'lucide-svelte/icons/users';
|
|
4057
|
-
import CreditCard from 'lucide-svelte/icons/credit-card';
|
|
4058
4175
|
import Settings from 'lucide-svelte/icons/settings';
|
|
4059
4176
|
|
|
4060
4177
|
interface Props {
|
|
@@ -4068,7 +4185,6 @@ export const load = guardAuth();
|
|
|
4068
4185
|
{ href: '/dashboard', label: 'Overview', exact: true, icon: LayoutDashboard },
|
|
4069
4186
|
{ href: '/dashboard/api-keys', label: 'API Keys', exact: false, icon: KeyRound },
|
|
4070
4187
|
{ href: '/dashboard/team', label: 'Team', exact: false, icon: Users },
|
|
4071
|
-
{ href: '/dashboard/billing', label: 'Billing', exact: false, icon: CreditCard },
|
|
4072
4188
|
];
|
|
4073
4189
|
|
|
4074
4190
|
function isActive(href: string, exact: boolean, pathname: string): boolean {
|
|
@@ -4077,28 +4193,28 @@ export const load = guardAuth();
|
|
|
4077
4193
|
</script>
|
|
4078
4194
|
|
|
4079
4195
|
<div class="flex min-h-[calc(100vh-130px)]">
|
|
4080
|
-
<aside class="w-64 border-r border-
|
|
4196
|
+
<aside class="w-64 border-r border-border bg-muted/50 hidden md:block">
|
|
4081
4197
|
<nav class="p-4 space-y-1">
|
|
4082
4198
|
{#each navItems as item}
|
|
4083
4199
|
{@const active = isActive(item.href, item.exact, $page.url.pathname)}
|
|
4084
4200
|
<a
|
|
4085
4201
|
href={item.href}
|
|
4086
|
-
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-
|
|
4202
|
+
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-foreground hover:bg-muted hover:text-foreground'}"
|
|
4087
4203
|
>
|
|
4088
|
-
<Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-
|
|
4204
|
+
<Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-muted-foreground/70'} />
|
|
4089
4205
|
{item.label}
|
|
4090
4206
|
</a>
|
|
4091
4207
|
{/each}
|
|
4092
4208
|
</nav>
|
|
4093
4209
|
|
|
4094
4210
|
{#if data.user?.role === 'admin'}
|
|
4095
|
-
<div class="border-t border-
|
|
4211
|
+
<div class="border-t border-border mx-4 my-2"></div>
|
|
4096
4212
|
<div class="p-4 pt-0">
|
|
4097
4213
|
<a
|
|
4098
4214
|
href="/admin"
|
|
4099
|
-
class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-
|
|
4215
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-foreground hover:bg-muted hover:text-foreground transition-colors"
|
|
4100
4216
|
>
|
|
4101
|
-
<Icon icon={Settings} size={20} class="text-
|
|
4217
|
+
<Icon icon={Settings} size={20} class="text-muted-foreground/70" />
|
|
4102
4218
|
Admin Panel
|
|
4103
4219
|
</a>
|
|
4104
4220
|
</div>
|
|
@@ -4154,14 +4270,14 @@ export const load: PageServerLoad = async ({ locals }) => {
|
|
|
4154
4270
|
|
|
4155
4271
|
<div class="space-y-8">
|
|
4156
4272
|
<div>
|
|
4157
|
-
<h1 class="text-3xl font-bold text-
|
|
4158
|
-
<p class="text-
|
|
4273
|
+
<h1 class="text-3xl font-bold text-foreground mb-2">Dashboard</h1>
|
|
4274
|
+
<p class="text-muted-foreground">Welcome back, {data.user.name}</p>
|
|
4159
4275
|
</div>
|
|
4160
4276
|
|
|
4161
4277
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
4162
4278
|
<Card>
|
|
4163
4279
|
<CardContent class="pt-6">
|
|
4164
|
-
<p class="text-sm text-
|
|
4280
|
+
<p class="text-sm text-muted-foreground">API Keys</p>
|
|
4165
4281
|
<p class="text-3xl font-bold text-brand mt-2">{data.stats.apiKeyCount}</p>
|
|
4166
4282
|
<a href="/dashboard/api-keys" class="text-sm text-brand hover:underline mt-2 inline-block">Manage keys</a>
|
|
4167
4283
|
</CardContent>
|
|
@@ -4169,7 +4285,7 @@ export const load: PageServerLoad = async ({ locals }) => {
|
|
|
4169
4285
|
|
|
4170
4286
|
<Card>
|
|
4171
4287
|
<CardContent class="pt-6">
|
|
4172
|
-
<p class="text-sm text-
|
|
4288
|
+
<p class="text-sm text-muted-foreground">Teams</p>
|
|
4173
4289
|
<p class="text-3xl font-bold text-brand mt-2">{data.stats.teamCount}</p>
|
|
4174
4290
|
<a href="/dashboard/team" class="text-sm text-brand hover:underline mt-2 inline-block">Manage team</a>
|
|
4175
4291
|
</CardContent>
|
|
@@ -4177,7 +4293,7 @@ export const load: PageServerLoad = async ({ locals }) => {
|
|
|
4177
4293
|
|
|
4178
4294
|
<Card>
|
|
4179
4295
|
<CardContent class="pt-6">
|
|
4180
|
-
<p class="text-sm text-
|
|
4296
|
+
<p class="text-sm text-muted-foreground">Account</p>
|
|
4181
4297
|
<Badge variant="default" class="mt-2">{data.user.role}</Badge>
|
|
4182
4298
|
</CardContent>
|
|
4183
4299
|
</Card>
|
|
@@ -4302,8 +4418,8 @@ export const actions: Actions = {
|
|
|
4302
4418
|
|
|
4303
4419
|
<div class="space-y-8">
|
|
4304
4420
|
<div>
|
|
4305
|
-
<h1 class="text-3xl font-bold text-
|
|
4306
|
-
<p class="text-
|
|
4421
|
+
<h1 class="text-3xl font-bold text-foreground">API Keys</h1>
|
|
4422
|
+
<p class="text-muted-foreground mt-1">Manage your API keys for programmatic access</p>
|
|
4307
4423
|
</div>
|
|
4308
4424
|
|
|
4309
4425
|
{#if showCopyAlert}
|
|
@@ -4320,7 +4436,7 @@ export const actions: Actions = {
|
|
|
4320
4436
|
<p class="font-medium">API Key Created</p>
|
|
4321
4437
|
<p class="text-sm">Copy this key now. You won't be able to see it again.</p>
|
|
4322
4438
|
<div class="flex gap-2 mt-3">
|
|
4323
|
-
<code class="flex-1 bg-
|
|
4439
|
+
<code class="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono break-all">{generatedKey}</code>
|
|
4324
4440
|
<Button size="sm" variant="outline" onclick={() => copyToClipboard(generatedKey)}>Copy</Button>
|
|
4325
4441
|
</div>
|
|
4326
4442
|
</div>
|
|
@@ -4339,7 +4455,7 @@ export const actions: Actions = {
|
|
|
4339
4455
|
<div class="space-y-2">
|
|
4340
4456
|
<Label for="permissions">Permissions</Label>
|
|
4341
4457
|
<Input id="permissions" name="permissions" placeholder="read,write" bind:value={newKeyPermissions} />
|
|
4342
|
-
<p class="text-xs text-
|
|
4458
|
+
<p class="text-xs text-muted-foreground">Comma-separated: read, write, admin</p>
|
|
4343
4459
|
</div>
|
|
4344
4460
|
<div class="flex gap-2">
|
|
4345
4461
|
<Button type="submit">Create Key</Button>
|
|
@@ -4353,12 +4469,12 @@ export const actions: Actions = {
|
|
|
4353
4469
|
{/if}
|
|
4354
4470
|
|
|
4355
4471
|
<div class="space-y-4">
|
|
4356
|
-
<h2 class="text-xl font-bold text-
|
|
4472
|
+
<h2 class="text-xl font-bold text-foreground">Your Keys ({apiKeys.length})</h2>
|
|
4357
4473
|
|
|
4358
4474
|
{#if apiKeys.length === 0}
|
|
4359
4475
|
<Card>
|
|
4360
4476
|
<CardContent class="pt-8 text-center">
|
|
4361
|
-
<p class="text-
|
|
4477
|
+
<p class="text-muted-foreground text-sm">No API keys yet. Create one to get started.</p>
|
|
4362
4478
|
</CardContent>
|
|
4363
4479
|
</Card>
|
|
4364
4480
|
{:else}
|
|
@@ -4369,11 +4485,11 @@ export const actions: Actions = {
|
|
|
4369
4485
|
<div class="flex items-start justify-between gap-4">
|
|
4370
4486
|
<div class="flex-1">
|
|
4371
4487
|
<div class="flex items-center gap-2 mb-2">
|
|
4372
|
-
<h3 class="font-semibold text-
|
|
4488
|
+
<h3 class="font-semibold text-foreground">{key.name}</h3>
|
|
4373
4489
|
<Badge variant="default">Active</Badge>
|
|
4374
4490
|
</div>
|
|
4375
|
-
<p class="font-mono text-xs bg-
|
|
4376
|
-
<div class="flex gap-4 text-xs text-
|
|
4491
|
+
<p class="font-mono text-xs bg-muted px-2 py-1 rounded inline-block mb-2">{key.prefix}........</p>
|
|
4492
|
+
<div class="flex gap-4 text-xs text-muted-foreground">
|
|
4377
4493
|
<span>Created {new Date(key.createdAt).toLocaleDateString()}</span>
|
|
4378
4494
|
<span>{key.lastUsedAt ? 'Last used ' + new Date(key.lastUsedAt).toLocaleDateString() : 'Never used'}</span>
|
|
4379
4495
|
</div>
|
|
@@ -4403,8 +4519,8 @@ export const actions: Actions = {
|
|
|
4403
4519
|
<Card>
|
|
4404
4520
|
<CardHeader><CardTitle>Usage</CardTitle></CardHeader>
|
|
4405
4521
|
<CardContent>
|
|
4406
|
-
<h4 class="font-medium text-
|
|
4407
|
-
<code class="block bg-
|
|
4522
|
+
<h4 class="font-medium text-foreground mb-2">Include your API key in the Authorization header</h4>
|
|
4523
|
+
<code class="block bg-muted px-4 py-3 rounded text-sm font-mono overflow-x-auto">
|
|
4408
4524
|
curl -H "Authorization: Bearer sk_your_key_here" https://your-app.com/api/v1/data
|
|
4409
4525
|
</code>
|
|
4410
4526
|
</CardContent>
|
|
@@ -4545,8 +4661,8 @@ export const actions: Actions = {
|
|
|
4545
4661
|
|
|
4546
4662
|
<div class="space-y-8">
|
|
4547
4663
|
<div>
|
|
4548
|
-
<h1 class="text-3xl font-bold text-
|
|
4549
|
-
<p class="text-
|
|
4664
|
+
<h1 class="text-3xl font-bold text-foreground">Team</h1>
|
|
4665
|
+
<p class="text-muted-foreground mt-1">Manage your team members and invitations</p>
|
|
4550
4666
|
</div>
|
|
4551
4667
|
|
|
4552
4668
|
{#if alertMessage}
|
|
@@ -4587,7 +4703,7 @@ export const actions: Actions = {
|
|
|
4587
4703
|
</div>
|
|
4588
4704
|
<div>
|
|
4589
4705
|
<Label for="role">Role</Label>
|
|
4590
|
-
<select id="role" name="role" class="mt-2 w-full px-3 py-2 border border-
|
|
4706
|
+
<select id="role" name="role" class="mt-2 w-full px-3 py-2 border border-border rounded-md text-sm">
|
|
4591
4707
|
<option value="member">Member</option>
|
|
4592
4708
|
<option value="admin">Admin</option>
|
|
4593
4709
|
</select>
|
|
@@ -4612,12 +4728,12 @@ export const actions: Actions = {
|
|
|
4612
4728
|
{#if members.length > 0}
|
|
4613
4729
|
<div class="space-y-3">
|
|
4614
4730
|
{#each members as member (member.id)}
|
|
4615
|
-
<div class="flex items-center justify-between p-3 border border-
|
|
4731
|
+
<div class="flex items-center justify-between p-3 border border-border rounded-lg">
|
|
4616
4732
|
<div>
|
|
4617
|
-
<p class="font-medium text-
|
|
4733
|
+
<p class="font-medium text-foreground">
|
|
4618
4734
|
{member.userId == data.user.id ? data.user.name + ' (you)' : 'User #' + member.userId}
|
|
4619
4735
|
</p>
|
|
4620
|
-
<p class="text-xs text-
|
|
4736
|
+
<p class="text-xs text-muted-foreground">Joined {new Date(member.joinedAt).toLocaleDateString()}</p>
|
|
4621
4737
|
</div>
|
|
4622
4738
|
<div class="flex items-center gap-2">
|
|
4623
4739
|
<Badge variant={member.role === 'owner' ? 'destructive' : 'default'}>
|
|
@@ -4638,7 +4754,7 @@ export const actions: Actions = {
|
|
|
4638
4754
|
{/each}
|
|
4639
4755
|
</div>
|
|
4640
4756
|
{:else}
|
|
4641
|
-
<p class="text-sm text-
|
|
4757
|
+
<p class="text-sm text-muted-foreground text-center py-4">No members yet</p>
|
|
4642
4758
|
{/if}
|
|
4643
4759
|
</CardContent>
|
|
4644
4760
|
</Card>
|
|
@@ -4652,10 +4768,10 @@ export const actions: Actions = {
|
|
|
4652
4768
|
<CardContent>
|
|
4653
4769
|
<div class="space-y-2">
|
|
4654
4770
|
{#each invitations as inv (inv.id)}
|
|
4655
|
-
<div class="flex items-center justify-between p-3 border border-
|
|
4771
|
+
<div class="flex items-center justify-between p-3 border border-border rounded-lg bg-muted/50">
|
|
4656
4772
|
<div>
|
|
4657
|
-
<p class="font-medium text-
|
|
4658
|
-
<p class="text-xs text-
|
|
4773
|
+
<p class="font-medium text-foreground">{inv.email}</p>
|
|
4774
|
+
<p class="text-xs text-muted-foreground">Expires {new Date(inv.expiresAt).toLocaleDateString()}</p>
|
|
4659
4775
|
</div>
|
|
4660
4776
|
<div class="flex items-center gap-2">
|
|
4661
4777
|
<Badge variant="secondary">{inv.role}</Badge>
|
|
@@ -4673,7 +4789,7 @@ export const actions: Actions = {
|
|
|
4673
4789
|
{:else}
|
|
4674
4790
|
<Card>
|
|
4675
4791
|
<CardContent class="pt-8 text-center">
|
|
4676
|
-
<p class="text-
|
|
4792
|
+
<p class="text-muted-foreground">Could not load team data. Try refreshing the page.</p>
|
|
4677
4793
|
</CardContent>
|
|
4678
4794
|
</Card>
|
|
4679
4795
|
{/if}
|
|
@@ -4692,7 +4808,6 @@ export const load = guardAuth('/dashboard', { role: 'admin' });
|
|
|
4692
4808
|
import ListTodo from 'lucide-svelte/icons/list-todo';
|
|
4693
4809
|
import Clock from 'lucide-svelte/icons/clock';
|
|
4694
4810
|
import FileText from 'lucide-svelte/icons/file-text';
|
|
4695
|
-
import CreditCard from 'lucide-svelte/icons/credit-card';
|
|
4696
4811
|
import ArrowLeft from 'lucide-svelte/icons/arrow-left';
|
|
4697
4812
|
|
|
4698
4813
|
interface Props {
|
|
@@ -4707,7 +4822,6 @@ export const load = guardAuth('/dashboard', { role: 'admin' });
|
|
|
4707
4822
|
{ tab: 'users', label: 'Users', icon: Users },
|
|
4708
4823
|
{ tab: 'roles', label: 'Roles', icon: ShieldCheck },
|
|
4709
4824
|
{ tab: 'permissions', label: 'Permissions', icon: Lock },
|
|
4710
|
-
{ tab: 'billing', label: 'Billing', icon: CreditCard },
|
|
4711
4825
|
{ tab: 'queue', label: 'Queue', icon: ListTodo },
|
|
4712
4826
|
{ tab: 'scheduler', label: 'Scheduler', icon: Clock },
|
|
4713
4827
|
{ tab: 'logs', label: 'Logs', icon: FileText },
|
|
@@ -4720,30 +4834,30 @@ export const load = guardAuth('/dashboard', { role: 'admin' });
|
|
|
4720
4834
|
</script>
|
|
4721
4835
|
|
|
4722
4836
|
<div class="flex min-h-[calc(100vh-130px)]">
|
|
4723
|
-
<aside class="w-64 border-r border-
|
|
4724
|
-
<div class="p-4 border-b border-
|
|
4725
|
-
<p class="text-xs font-semibold text-
|
|
4837
|
+
<aside class="w-64 border-r border-border bg-muted/50 hidden md:block">
|
|
4838
|
+
<div class="p-4 border-b border-border">
|
|
4839
|
+
<p class="text-xs font-semibold text-muted-foreground/70 uppercase tracking-wider">Administration</p>
|
|
4726
4840
|
</div>
|
|
4727
4841
|
<nav class="p-4 space-y-1">
|
|
4728
4842
|
{#each navItems as item}
|
|
4729
4843
|
{@const active = isActive(item.tab, $page.url)}
|
|
4730
4844
|
<a
|
|
4731
4845
|
href="/admin?tab={item.tab}"
|
|
4732
|
-
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-
|
|
4846
|
+
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-foreground hover:bg-muted hover:text-foreground'}"
|
|
4733
4847
|
>
|
|
4734
|
-
<Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-
|
|
4848
|
+
<Icon icon={item.icon} size={20} class={active ? 'text-brand' : 'text-muted-foreground/70'} />
|
|
4735
4849
|
{item.label}
|
|
4736
4850
|
</a>
|
|
4737
4851
|
{/each}
|
|
4738
4852
|
</nav>
|
|
4739
4853
|
|
|
4740
|
-
<div class="border-t border-
|
|
4854
|
+
<div class="border-t border-border mx-4 my-2"></div>
|
|
4741
4855
|
<div class="p-4 pt-0">
|
|
4742
4856
|
<a
|
|
4743
4857
|
href="/dashboard"
|
|
4744
|
-
class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-
|
|
4858
|
+
class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium text-foreground hover:bg-muted hover:text-foreground transition-colors"
|
|
4745
4859
|
>
|
|
4746
|
-
<Icon icon={ArrowLeft} size={20} class="text-
|
|
4860
|
+
<Icon icon={ArrowLeft} size={20} class="text-muted-foreground/70" />
|
|
4747
4861
|
Back to Dashboard
|
|
4748
4862
|
</a>
|
|
4749
4863
|
</div>
|
|
@@ -4760,8 +4874,6 @@ import { JobMonitor } from '@beeblock/svelar/queue/JobMonitor';
|
|
|
4760
4874
|
import { ScheduleMonitor } from '@beeblock/svelar/scheduler/ScheduleMonitor';
|
|
4761
4875
|
import { LogViewer } from '@beeblock/svelar/logging/LogViewer';
|
|
4762
4876
|
import { Permissions } from '@beeblock/svelar/permissions';
|
|
4763
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
4764
|
-
|
|
4765
4877
|
export async function load(event: ServerLoadEvent) {
|
|
4766
4878
|
const user = event.locals.user;
|
|
4767
4879
|
|
|
@@ -4830,33 +4942,6 @@ export async function load(event: ServerLoadEvent) {
|
|
|
4830
4942
|
}
|
|
4831
4943
|
} catch { /* permissions tables may not exist yet */ }
|
|
4832
4944
|
|
|
4833
|
-
// Billing / Stripe subscriptions
|
|
4834
|
-
let billingSubscriptions: any[] = [];
|
|
4835
|
-
try {
|
|
4836
|
-
const client = await Stripe.service().getClient();
|
|
4837
|
-
const subs = await client.subscriptions.list({
|
|
4838
|
-
limit: 25,
|
|
4839
|
-
expand: ['data.customer'],
|
|
4840
|
-
});
|
|
4841
|
-
billingSubscriptions = subs.data.map((sub: any) => ({
|
|
4842
|
-
id: sub.id,
|
|
4843
|
-
status: sub.status,
|
|
4844
|
-
cancelAtPeriodEnd: sub.cancel_at_period_end,
|
|
4845
|
-
customer: {
|
|
4846
|
-
id: typeof sub.customer === 'string' ? sub.customer : sub.customer?.id,
|
|
4847
|
-
email: typeof sub.customer === 'object' ? sub.customer?.email : null,
|
|
4848
|
-
name: typeof sub.customer === 'object' ? sub.customer?.name : null,
|
|
4849
|
-
},
|
|
4850
|
-
plan: {
|
|
4851
|
-
nickname: sub.items?.data?.[0]?.price?.nickname ?? 'Plan',
|
|
4852
|
-
amount: sub.items?.data?.[0]?.price?.unit_amount ?? 0,
|
|
4853
|
-
currency: sub.items?.data?.[0]?.price?.currency ?? 'usd',
|
|
4854
|
-
interval: sub.items?.data?.[0]?.price?.recurring?.interval ?? 'month',
|
|
4855
|
-
},
|
|
4856
|
-
created: sub.created,
|
|
4857
|
-
}));
|
|
4858
|
-
} catch { /* stripe not configured or no subscriptions */ }
|
|
4859
|
-
|
|
4860
4945
|
return {
|
|
4861
4946
|
user: {
|
|
4862
4947
|
id: user.id,
|
|
@@ -4922,7 +5007,6 @@ export async function load(event: ServerLoadEvent) {
|
|
|
4922
5007
|
perms.map((p: any) => ({ id: p.id, name: p.name })),
|
|
4923
5008
|
]),
|
|
4924
5009
|
),
|
|
4925
|
-
billingSubscriptions,
|
|
4926
5010
|
};
|
|
4927
5011
|
}
|
|
4928
5012
|
`}static adminPageSvelte(){return`<script lang="ts">
|
|
@@ -4956,12 +5040,6 @@ export async function load(event: ServerLoadEvent) {
|
|
|
4956
5040
|
let showRoleForm = $state(false);
|
|
4957
5041
|
let showPermForm = $state(false);
|
|
4958
5042
|
|
|
4959
|
-
// Billing state
|
|
4960
|
-
let billingSubscriptions = $state<any[]>(data.billingSubscriptions ?? []);
|
|
4961
|
-
let billingLoading = $state(false);
|
|
4962
|
-
let billingMessage = $state('');
|
|
4963
|
-
let billingMessageType = $state<'success' | 'error'>('success');
|
|
4964
|
-
|
|
4965
5043
|
let logFilter = $state<'all' | 'info' | 'warn' | 'error'>('all');
|
|
4966
5044
|
|
|
4967
5045
|
const activeTab = $derived($page.url.searchParams.get('tab') ?? 'overview');
|
|
@@ -5340,74 +5418,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5340
5418
|
return level === 'error' || level === 'fatal' ? 'destructive' : level === 'warn' ? 'secondary' : 'default';
|
|
5341
5419
|
}
|
|
5342
5420
|
|
|
5343
|
-
function billingFlash(msg: string, type: 'success' | 'error' = 'success') {
|
|
5344
|
-
billingMessage = msg;
|
|
5345
|
-
billingMessageType = type;
|
|
5346
|
-
}
|
|
5347
|
-
|
|
5348
|
-
function formatCurrency(amount: number, currency: string): string {
|
|
5349
|
-
return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency.toUpperCase() }).format(amount / 100);
|
|
5350
|
-
}
|
|
5351
|
-
|
|
5352
|
-
function billingStatusVariant(status: string): 'default' | 'secondary' | 'destructive' {
|
|
5353
|
-
if (status === 'active' || status === 'trialing') return 'default';
|
|
5354
|
-
if (status === 'past_due' || status === 'incomplete') return 'secondary';
|
|
5355
|
-
return 'destructive';
|
|
5356
|
-
}
|
|
5357
|
-
|
|
5358
|
-
async function refreshBilling() {
|
|
5359
|
-
billingLoading = true;
|
|
5360
|
-
try {
|
|
5361
|
-
const res = await fetch('/api/admin/billing/subscriptions?limit=50');
|
|
5362
|
-
if (res.ok) {
|
|
5363
|
-
const data = await res.json();
|
|
5364
|
-
billingSubscriptions = data.subscriptions;
|
|
5365
|
-
}
|
|
5366
|
-
} catch { /* ignore */ }
|
|
5367
|
-
billingLoading = false;
|
|
5368
|
-
}
|
|
5369
|
-
|
|
5370
|
-
async function cancelSubscription(subscriptionId: string, customerEmail: string, immediately: boolean) {
|
|
5371
|
-
const mode = immediately ? 'immediately' : 'at end of billing period';
|
|
5372
|
-
if (!confirm(\`Cancel subscription for \${customerEmail} \${mode}?\`)) return;
|
|
5373
|
-
try {
|
|
5374
|
-
const res = await fetch('/api/admin/billing/cancel', {
|
|
5375
|
-
method: 'POST',
|
|
5376
|
-
headers: { 'Content-Type': 'application/json' },
|
|
5377
|
-
body: JSON.stringify({ subscriptionId, immediately }),
|
|
5378
|
-
});
|
|
5379
|
-
if (res.ok) {
|
|
5380
|
-
billingFlash(\`Subscription \${immediately ? 'canceled' : 'set to cancel at period end'}\`);
|
|
5381
|
-
await refreshBilling();
|
|
5382
|
-
} else {
|
|
5383
|
-
const err = await res.json();
|
|
5384
|
-
billingFlash(err.error || 'Failed to cancel', 'error');
|
|
5385
|
-
}
|
|
5386
|
-
} catch {
|
|
5387
|
-
billingFlash('Network error', 'error');
|
|
5388
|
-
}
|
|
5389
|
-
}
|
|
5390
5421
|
|
|
5391
|
-
async function refundSubscription(subscriptionId: string, customerEmail: string) {
|
|
5392
|
-
const invoiceId = prompt(\`Enter the Stripe Invoice ID to refund for \${customerEmail}:\`);
|
|
5393
|
-
if (!invoiceId) return;
|
|
5394
|
-
try {
|
|
5395
|
-
const res = await fetch('/api/admin/billing/refund', {
|
|
5396
|
-
method: 'POST',
|
|
5397
|
-
headers: { 'Content-Type': 'application/json' },
|
|
5398
|
-
body: JSON.stringify({ invoiceId }),
|
|
5399
|
-
});
|
|
5400
|
-
if (res.ok) {
|
|
5401
|
-
const data = await res.json();
|
|
5402
|
-
billingFlash(\`Refund issued: \${data.refund.id} (\${data.refund.status})\`);
|
|
5403
|
-
} else {
|
|
5404
|
-
const err = await res.json();
|
|
5405
|
-
billingFlash(err.error || 'Refund failed', 'error');
|
|
5406
|
-
}
|
|
5407
|
-
} catch {
|
|
5408
|
-
billingFlash('Network error', 'error');
|
|
5409
|
-
}
|
|
5410
|
-
}
|
|
5411
5422
|
</script>
|
|
5412
5423
|
|
|
5413
5424
|
<svelte:head>
|
|
@@ -5417,8 +5428,8 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5417
5428
|
<div class="space-y-8">
|
|
5418
5429
|
<div class="flex justify-between items-center">
|
|
5419
5430
|
<div>
|
|
5420
|
-
<h1 class="text-3xl font-bold text-
|
|
5421
|
-
<p class="text-
|
|
5431
|
+
<h1 class="text-3xl font-bold text-foreground">Admin Dashboard</h1>
|
|
5432
|
+
<p class="text-muted-foreground mt-1">System health, queue monitoring, and task management</p>
|
|
5422
5433
|
</div>
|
|
5423
5434
|
<Button variant="outline" onclick={refreshDashboard}>Refresh</Button>
|
|
5424
5435
|
</div>
|
|
@@ -5436,7 +5447,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5436
5447
|
<Card>
|
|
5437
5448
|
<CardContent class="pt-6">
|
|
5438
5449
|
<div>
|
|
5439
|
-
<p class="text-sm text-
|
|
5450
|
+
<p class="text-sm text-muted-foreground">Total Users</p>
|
|
5440
5451
|
<p class="text-3xl font-bold text-[var(--color-brand)] mt-2">{data.stats.userCount}</p>
|
|
5441
5452
|
</div>
|
|
5442
5453
|
</CardContent>
|
|
@@ -5445,7 +5456,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5445
5456
|
<Card>
|
|
5446
5457
|
<CardContent class="pt-6">
|
|
5447
5458
|
<div>
|
|
5448
|
-
<p class="text-sm text-
|
|
5459
|
+
<p class="text-sm text-muted-foreground">Total Posts</p>
|
|
5449
5460
|
<p class="text-3xl font-bold text-[var(--color-brand)] mt-2">{data.stats.postCount}</p>
|
|
5450
5461
|
</div>
|
|
5451
5462
|
</CardContent>
|
|
@@ -5454,7 +5465,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5454
5465
|
<Card>
|
|
5455
5466
|
<CardContent class="pt-6">
|
|
5456
5467
|
<div>
|
|
5457
|
-
<p class="text-sm text-
|
|
5468
|
+
<p class="text-sm text-muted-foreground">Queue Pending</p>
|
|
5458
5469
|
<p class="text-3xl font-bold text-yellow-600 mt-2">{queueCounts.waiting}</p>
|
|
5459
5470
|
</div>
|
|
5460
5471
|
</CardContent>
|
|
@@ -5463,7 +5474,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5463
5474
|
<Card>
|
|
5464
5475
|
<CardContent class="pt-6">
|
|
5465
5476
|
<div>
|
|
5466
|
-
<p class="text-sm text-
|
|
5477
|
+
<p class="text-sm text-muted-foreground">Failed Jobs</p>
|
|
5467
5478
|
<p class="text-3xl font-bold text-red-600 mt-2">{queueCounts.failed}</p>
|
|
5468
5479
|
</div>
|
|
5469
5480
|
</CardContent>
|
|
@@ -5490,7 +5501,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5490
5501
|
{health.memoryUsedMB} MB / {health.memoryTotalMB} MB ({health.memoryPercent}%)
|
|
5491
5502
|
</Badge>
|
|
5492
5503
|
</div>
|
|
5493
|
-
<div class="h-2 bg-
|
|
5504
|
+
<div class="h-2 bg-muted rounded-full overflow-hidden">
|
|
5494
5505
|
<div
|
|
5495
5506
|
class="h-full transition-all"
|
|
5496
5507
|
class:bg-green-500={health.memoryPercent <= 70}
|
|
@@ -5524,20 +5535,20 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5524
5535
|
<div class="overflow-x-auto">
|
|
5525
5536
|
<table class="w-full text-sm">
|
|
5526
5537
|
<thead>
|
|
5527
|
-
<tr class="border-b border-
|
|
5528
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5529
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5530
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5531
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5532
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5533
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5538
|
+
<tr class="border-b border-border">
|
|
5539
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Name</th>
|
|
5540
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Email</th>
|
|
5541
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Column Role</th>
|
|
5542
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Assigned Roles</th>
|
|
5543
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Direct Permissions</th>
|
|
5544
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Actions</th>
|
|
5534
5545
|
</tr>
|
|
5535
5546
|
</thead>
|
|
5536
5547
|
<tbody>
|
|
5537
5548
|
{#each users as user (user.id)}
|
|
5538
|
-
<tr class="border-b border-
|
|
5539
|
-
<td class="py-3 px-4 font-medium text-
|
|
5540
|
-
<td class="py-3 px-4 text-
|
|
5549
|
+
<tr class="border-b border-border hover:bg-muted/50">
|
|
5550
|
+
<td class="py-3 px-4 font-medium text-foreground">{user.name}</td>
|
|
5551
|
+
<td class="py-3 px-4 text-muted-foreground">{user.email}</td>
|
|
5541
5552
|
<td class="py-3 px-4">
|
|
5542
5553
|
<Badge variant={user.role === 'admin' ? 'default' : 'secondary'}>
|
|
5543
5554
|
{user.role}
|
|
@@ -5557,7 +5568,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5557
5568
|
{/each}
|
|
5558
5569
|
{#if roles.length > 0}
|
|
5559
5570
|
<select
|
|
5560
|
-
class="text-xs border border-
|
|
5571
|
+
class="text-xs border border-border rounded px-1 py-0.5"
|
|
5561
5572
|
onchange={(e) => {
|
|
5562
5573
|
const val = Number((e.target as HTMLSelectElement).value);
|
|
5563
5574
|
if (val) { assignRoleToUser(user.id, val); (e.target as HTMLSelectElement).value = ''; }
|
|
@@ -5585,7 +5596,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5585
5596
|
{/each}
|
|
5586
5597
|
{#if permissions.length > 0}
|
|
5587
5598
|
<select
|
|
5588
|
-
class="text-xs border border-
|
|
5599
|
+
class="text-xs border border-border rounded px-1 py-0.5"
|
|
5589
5600
|
onchange={(e) => {
|
|
5590
5601
|
const val = Number((e.target as HTMLSelectElement).value);
|
|
5591
5602
|
if (val) { grantPermToUser(user.id, val); (e.target as HTMLSelectElement).value = ''; }
|
|
@@ -5644,7 +5655,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5644
5655
|
{#if showRoleForm}
|
|
5645
5656
|
<CardContent>
|
|
5646
5657
|
<form
|
|
5647
|
-
class="flex flex-wrap gap-3 items-end border-b border-
|
|
5658
|
+
class="flex flex-wrap gap-3 items-end border-b border-border pb-4 mb-4"
|
|
5648
5659
|
onsubmit={(e) => { e.preventDefault(); createRole(); }}
|
|
5649
5660
|
>
|
|
5650
5661
|
<div class="flex-1 min-w-[200px]">
|
|
@@ -5663,19 +5674,19 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5663
5674
|
{#if roles.length > 0}
|
|
5664
5675
|
<div class="space-y-4">
|
|
5665
5676
|
{#each roles as role (role.id)}
|
|
5666
|
-
<div class="border border-
|
|
5677
|
+
<div class="border border-border rounded-lg p-4">
|
|
5667
5678
|
<div class="flex items-center justify-between mb-3">
|
|
5668
5679
|
<div>
|
|
5669
|
-
<span class="font-medium text-
|
|
5680
|
+
<span class="font-medium text-foreground">{role.name}</span>
|
|
5670
5681
|
<Badge variant="secondary" class="ml-2">{role.guard}</Badge>
|
|
5671
5682
|
{#if role.description}
|
|
5672
|
-
<p class="text-xs text-
|
|
5683
|
+
<p class="text-xs text-muted-foreground mt-1">{role.description}</p>
|
|
5673
5684
|
{/if}
|
|
5674
5685
|
</div>
|
|
5675
5686
|
<Button size="sm" variant="destructive" onclick={() => deleteRole(role.name)}>Delete</Button>
|
|
5676
5687
|
</div>
|
|
5677
5688
|
<div>
|
|
5678
|
-
<p class="text-xs font-semibold text-
|
|
5689
|
+
<p class="text-xs font-semibold text-muted-foreground uppercase mb-2">Permissions</p>
|
|
5679
5690
|
<div class="flex flex-wrap gap-2">
|
|
5680
5691
|
{#each permissions as perm (perm.id)}
|
|
5681
5692
|
{@const has = (rolePermissionsMap[role.id] ?? []).includes(perm.id)}
|
|
@@ -5683,14 +5694,14 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5683
5694
|
type="button"
|
|
5684
5695
|
class="px-2 py-1 rounded text-xs border transition-colors {has
|
|
5685
5696
|
? 'bg-[var(--color-brand)] text-white border-[var(--color-brand)]'
|
|
5686
|
-
: 'bg-
|
|
5697
|
+
: 'bg-background text-muted-foreground border-border hover:border-foreground/30'}"
|
|
5687
5698
|
onclick={() => toggleRolePermission(role.id, perm.id)}
|
|
5688
5699
|
>
|
|
5689
5700
|
{perm.name}
|
|
5690
5701
|
</button>
|
|
5691
5702
|
{/each}
|
|
5692
5703
|
{#if permissions.length === 0}
|
|
5693
|
-
<span class="text-xs text-
|
|
5704
|
+
<span class="text-xs text-muted-foreground/70">No permissions defined yet</span>
|
|
5694
5705
|
{/if}
|
|
5695
5706
|
</div>
|
|
5696
5707
|
</div>
|
|
@@ -5698,7 +5709,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5698
5709
|
{/each}
|
|
5699
5710
|
</div>
|
|
5700
5711
|
{:else}
|
|
5701
|
-
<p class="text-sm text-
|
|
5712
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
5702
5713
|
No roles defined. Create one to start assigning permissions.
|
|
5703
5714
|
</p>
|
|
5704
5715
|
{/if}
|
|
@@ -5725,7 +5736,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5725
5736
|
{#if showPermForm}
|
|
5726
5737
|
<CardContent>
|
|
5727
5738
|
<form
|
|
5728
|
-
class="flex flex-wrap gap-3 items-end border-b border-
|
|
5739
|
+
class="flex flex-wrap gap-3 items-end border-b border-border pb-4 mb-4"
|
|
5729
5740
|
onsubmit={(e) => { e.preventDefault(); createPermission(); }}
|
|
5730
5741
|
>
|
|
5731
5742
|
<div class="flex-1 min-w-[200px]">
|
|
@@ -5745,30 +5756,30 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5745
5756
|
<div class="overflow-x-auto">
|
|
5746
5757
|
<table class="w-full text-sm">
|
|
5747
5758
|
<thead>
|
|
5748
|
-
<tr class="border-b border-
|
|
5749
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5750
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5751
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5752
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5753
|
-
<th class="text-left py-3 px-4 font-semibold text-
|
|
5759
|
+
<tr class="border-b border-border">
|
|
5760
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Name</th>
|
|
5761
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Guard</th>
|
|
5762
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Description</th>
|
|
5763
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Used by Roles</th>
|
|
5764
|
+
<th class="text-left py-3 px-4 font-semibold text-foreground">Actions</th>
|
|
5754
5765
|
</tr>
|
|
5755
5766
|
</thead>
|
|
5756
5767
|
<tbody>
|
|
5757
5768
|
{#each permissions as perm (perm.id)}
|
|
5758
5769
|
{@const usedBy = roles.filter((r) => (rolePermissionsMap[r.id] ?? []).includes(perm.id))}
|
|
5759
|
-
<tr class="border-b border-
|
|
5760
|
-
<td class="py-3 px-4 font-medium text-
|
|
5770
|
+
<tr class="border-b border-border hover:bg-muted/50">
|
|
5771
|
+
<td class="py-3 px-4 font-medium text-foreground">{perm.name}</td>
|
|
5761
5772
|
<td class="py-3 px-4">
|
|
5762
5773
|
<Badge variant="secondary">{perm.guard}</Badge>
|
|
5763
5774
|
</td>
|
|
5764
|
-
<td class="py-3 px-4 text-
|
|
5775
|
+
<td class="py-3 px-4 text-muted-foreground">{perm.description || '---'}</td>
|
|
5765
5776
|
<td class="py-3 px-4">
|
|
5766
5777
|
<div class="flex flex-wrap gap-1">
|
|
5767
5778
|
{#each usedBy as role (role.id)}
|
|
5768
5779
|
<Badge variant="outline">{role.name}</Badge>
|
|
5769
5780
|
{/each}
|
|
5770
5781
|
{#if usedBy.length === 0}
|
|
5771
|
-
<span class="text-xs text-
|
|
5782
|
+
<span class="text-xs text-muted-foreground/70">None</span>
|
|
5772
5783
|
{/if}
|
|
5773
5784
|
</div>
|
|
5774
5785
|
</td>
|
|
@@ -5781,7 +5792,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5781
5792
|
</table>
|
|
5782
5793
|
</div>
|
|
5783
5794
|
{:else}
|
|
5784
|
-
<p class="text-sm text-
|
|
5795
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
5785
5796
|
No permissions defined. Create one to start building your authorization system.
|
|
5786
5797
|
</p>
|
|
5787
5798
|
{/if}
|
|
@@ -5790,89 +5801,6 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5790
5801
|
</div>
|
|
5791
5802
|
{/if}
|
|
5792
5803
|
|
|
5793
|
-
<!-- Billing -->
|
|
5794
|
-
{#if activeTab === 'billing'}
|
|
5795
|
-
<Card>
|
|
5796
|
-
<CardHeader>
|
|
5797
|
-
<div class="flex items-center justify-between">
|
|
5798
|
-
<div>
|
|
5799
|
-
<CardTitle>Subscriptions</CardTitle>
|
|
5800
|
-
<CardDescription>Manage user subscriptions, issue refunds, and cancel plans</CardDescription>
|
|
5801
|
-
</div>
|
|
5802
|
-
<Button variant="outline" size="sm" onclick={refreshBilling} disabled={billingLoading}>
|
|
5803
|
-
{billingLoading ? 'Loading...' : 'Refresh'}
|
|
5804
|
-
</Button>
|
|
5805
|
-
</div>
|
|
5806
|
-
</CardHeader>
|
|
5807
|
-
<CardContent>
|
|
5808
|
-
{#if billingMessage}
|
|
5809
|
-
<Alert variant={billingMessageType === 'error' ? 'destructive' : 'default'} class="mb-4">
|
|
5810
|
-
<span class="text-sm">{billingMessage}</span>
|
|
5811
|
-
</Alert>
|
|
5812
|
-
{/if}
|
|
5813
|
-
|
|
5814
|
-
{#if billingSubscriptions.length === 0}
|
|
5815
|
-
<p class="text-sm text-gray-500 py-8 text-center">
|
|
5816
|
-
No subscriptions found. Subscriptions will appear here when users subscribe via Stripe.
|
|
5817
|
-
</p>
|
|
5818
|
-
{:else}
|
|
5819
|
-
<div class="border rounded-lg overflow-hidden">
|
|
5820
|
-
<table class="w-full text-sm">
|
|
5821
|
-
<thead class="bg-gray-50 text-left">
|
|
5822
|
-
<tr>
|
|
5823
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Customer</th>
|
|
5824
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Plan</th>
|
|
5825
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Price</th>
|
|
5826
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Status</th>
|
|
5827
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Created</th>
|
|
5828
|
-
<th class="px-4 py-3 text-gray-600 font-medium text-right">Actions</th>
|
|
5829
|
-
</tr>
|
|
5830
|
-
</thead>
|
|
5831
|
-
<tbody class="divide-y">
|
|
5832
|
-
{#each billingSubscriptions as sub (sub.id)}
|
|
5833
|
-
<tr class="hover:bg-gray-50">
|
|
5834
|
-
<td class="px-4 py-3">
|
|
5835
|
-
<div>
|
|
5836
|
-
<p class="font-medium text-gray-900">{sub.customer.name ?? 'Unknown'}</p>
|
|
5837
|
-
<p class="text-xs text-gray-500">{sub.customer.email ?? sub.customer.id}</p>
|
|
5838
|
-
</div>
|
|
5839
|
-
</td>
|
|
5840
|
-
<td class="px-4 py-3 text-gray-700">{sub.plan.nickname}</td>
|
|
5841
|
-
<td class="px-4 py-3 text-gray-700">{formatCurrency(sub.plan.amount, sub.plan.currency)}/{sub.plan.interval}</td>
|
|
5842
|
-
<td class="px-4 py-3">
|
|
5843
|
-
<Badge variant={billingStatusVariant(sub.status)}>{sub.status}</Badge>
|
|
5844
|
-
{#if sub.cancelAtPeriodEnd}
|
|
5845
|
-
<Badge variant="secondary" class="ml-1">canceling</Badge>
|
|
5846
|
-
{/if}
|
|
5847
|
-
</td>
|
|
5848
|
-
<td class="px-4 py-3 text-gray-500">{formatDate(new Date(sub.created * 1000).toISOString())}</td>
|
|
5849
|
-
<td class="px-4 py-3 text-right">
|
|
5850
|
-
<div class="flex gap-1 justify-end">
|
|
5851
|
-
<Button size="sm" variant="outline" onclick={() => refundSubscription(sub.id, sub.customer.email ?? sub.customer.id)}>
|
|
5852
|
-
Refund
|
|
5853
|
-
</Button>
|
|
5854
|
-
{#if sub.status === 'active' || sub.status === 'trialing'}
|
|
5855
|
-
{#if !sub.cancelAtPeriodEnd}
|
|
5856
|
-
<Button size="sm" variant="outline" onclick={() => cancelSubscription(sub.id, sub.customer.email ?? sub.customer.id, false)}>
|
|
5857
|
-
Cancel
|
|
5858
|
-
</Button>
|
|
5859
|
-
{/if}
|
|
5860
|
-
<Button size="sm" variant="destructive" onclick={() => cancelSubscription(sub.id, sub.customer.email ?? sub.customer.id, true)}>
|
|
5861
|
-
Cancel Now
|
|
5862
|
-
</Button>
|
|
5863
|
-
{/if}
|
|
5864
|
-
</div>
|
|
5865
|
-
</td>
|
|
5866
|
-
</tr>
|
|
5867
|
-
{/each}
|
|
5868
|
-
</tbody>
|
|
5869
|
-
</table>
|
|
5870
|
-
</div>
|
|
5871
|
-
{/if}
|
|
5872
|
-
</CardContent>
|
|
5873
|
-
</Card>
|
|
5874
|
-
{/if}
|
|
5875
|
-
|
|
5876
5804
|
<!-- Queue -->
|
|
5877
5805
|
{#if activeTab === 'queue'}
|
|
5878
5806
|
<div class="space-y-6">
|
|
@@ -5880,7 +5808,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5880
5808
|
<Card>
|
|
5881
5809
|
<CardContent class="pt-6">
|
|
5882
5810
|
<div>
|
|
5883
|
-
<p class="text-sm text-
|
|
5811
|
+
<p class="text-sm text-muted-foreground">Waiting</p>
|
|
5884
5812
|
<p class="text-3xl font-bold text-yellow-600 mt-2">{queueCounts.waiting}</p>
|
|
5885
5813
|
</div>
|
|
5886
5814
|
</CardContent>
|
|
@@ -5888,7 +5816,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5888
5816
|
<Card>
|
|
5889
5817
|
<CardContent class="pt-6">
|
|
5890
5818
|
<div>
|
|
5891
|
-
<p class="text-sm text-
|
|
5819
|
+
<p class="text-sm text-muted-foreground">Active</p>
|
|
5892
5820
|
<p class="text-3xl font-bold text-blue-600 mt-2">{queueCounts.active}</p>
|
|
5893
5821
|
</div>
|
|
5894
5822
|
</CardContent>
|
|
@@ -5896,7 +5824,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5896
5824
|
<Card>
|
|
5897
5825
|
<CardContent class="pt-6">
|
|
5898
5826
|
<div>
|
|
5899
|
-
<p class="text-sm text-
|
|
5827
|
+
<p class="text-sm text-muted-foreground">Failed</p>
|
|
5900
5828
|
<p class="text-3xl font-bold text-red-600 mt-2">{queueCounts.failed}</p>
|
|
5901
5829
|
</div>
|
|
5902
5830
|
</CardContent>
|
|
@@ -5904,7 +5832,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5904
5832
|
<Card>
|
|
5905
5833
|
<CardContent class="pt-6">
|
|
5906
5834
|
<div>
|
|
5907
|
-
<p class="text-sm text-
|
|
5835
|
+
<p class="text-sm text-muted-foreground">Completed</p>
|
|
5908
5836
|
<p class="text-3xl font-bold text-green-600 mt-2">{queueCounts.completed}</p>
|
|
5909
5837
|
</div>
|
|
5910
5838
|
</CardContent>
|
|
@@ -5912,8 +5840,8 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5912
5840
|
<Card>
|
|
5913
5841
|
<CardContent class="pt-6">
|
|
5914
5842
|
<div>
|
|
5915
|
-
<p class="text-sm text-
|
|
5916
|
-
<p class="text-3xl font-bold text-
|
|
5843
|
+
<p class="text-sm text-muted-foreground">Delayed</p>
|
|
5844
|
+
<p class="text-3xl font-bold text-muted-foreground mt-2">{queueCounts.delayed}</p>
|
|
5917
5845
|
</div>
|
|
5918
5846
|
</CardContent>
|
|
5919
5847
|
</Card>
|
|
@@ -5945,12 +5873,12 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5945
5873
|
{#if scheduledTasks.length > 0}
|
|
5946
5874
|
<div class="space-y-3">
|
|
5947
5875
|
{#each scheduledTasks as task (task.name)}
|
|
5948
|
-
<div class="flex items-center justify-between p-4 border border-
|
|
5876
|
+
<div class="flex items-center justify-between p-4 border border-border rounded-lg hover:bg-muted/50">
|
|
5949
5877
|
<div class="flex-1">
|
|
5950
|
-
<p class="font-medium text-
|
|
5951
|
-
<p class="text-sm text-
|
|
5952
|
-
<p class="text-xs text-
|
|
5953
|
-
<p class="text-xs text-
|
|
5878
|
+
<p class="font-medium text-foreground">{task.name}</p>
|
|
5879
|
+
<p class="text-sm text-muted-foreground">Schedule: {task.humanReadable}</p>
|
|
5880
|
+
<p class="text-xs text-muted-foreground mt-1">Last run: {formatDate(task.lastRun)}</p>
|
|
5881
|
+
<p class="text-xs text-muted-foreground">Next run: {formatDate(task.nextRun)}</p>
|
|
5954
5882
|
</div>
|
|
5955
5883
|
<div class="flex items-center gap-3">
|
|
5956
5884
|
{#if task.lastStatus}
|
|
@@ -5970,7 +5898,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
5970
5898
|
{/each}
|
|
5971
5899
|
</div>
|
|
5972
5900
|
{:else}
|
|
5973
|
-
<p class="text-sm text-
|
|
5901
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
5974
5902
|
No scheduled tasks found. Configure the Scheduler in your app.ts to register tasks.
|
|
5975
5903
|
</p>
|
|
5976
5904
|
{/if}
|
|
@@ -6009,16 +5937,16 @@ export async function load(event: ServerLoadEvent) {
|
|
|
6009
5937
|
{#if filteredLogs.length > 0}
|
|
6010
5938
|
<div class="space-y-2 max-h-96 overflow-y-auto">
|
|
6011
5939
|
{#each filteredLogs as log, i (i)}
|
|
6012
|
-
<div class="flex items-start gap-3 p-3 border border-
|
|
5940
|
+
<div class="flex items-start gap-3 p-3 border border-border rounded bg-muted/50 text-sm">
|
|
6013
5941
|
<Badge variant={getLogBadgeVariant(log.level)} class="mt-0.5">
|
|
6014
5942
|
{log.level.toUpperCase()}
|
|
6015
5943
|
</Badge>
|
|
6016
5944
|
<div class="flex-1">
|
|
6017
|
-
<p class="text-
|
|
6018
|
-
<p class="text-xs text-
|
|
5945
|
+
<p class="text-foreground">{log.message}</p>
|
|
5946
|
+
<p class="text-xs text-muted-foreground mt-1">
|
|
6019
5947
|
{formatDate(log.timestamp)}
|
|
6020
5948
|
{#if log.channel && log.channel !== 'default'}
|
|
6021
|
-
<span class="ml-2 text-
|
|
5949
|
+
<span class="ml-2 text-muted-foreground/70">[{log.channel}]</span>
|
|
6022
5950
|
{/if}
|
|
6023
5951
|
</p>
|
|
6024
5952
|
</div>
|
|
@@ -6026,7 +5954,7 @@ export async function load(event: ServerLoadEvent) {
|
|
|
6026
5954
|
{/each}
|
|
6027
5955
|
</div>
|
|
6028
5956
|
{:else}
|
|
6029
|
-
<p class="text-sm text-
|
|
5957
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
6030
5958
|
No log entries found. Logs appear here as your application runs.
|
|
6031
5959
|
</p>
|
|
6032
5960
|
{/if}
|
|
@@ -6675,7 +6603,8 @@ export default class QueueHealthCheck extends ScheduledTask {
|
|
|
6675
6603
|
}
|
|
6676
6604
|
`}static rootLayoutSvelte(e){return`<script lang="ts">
|
|
6677
6605
|
import '../app.css';
|
|
6678
|
-
import {
|
|
6606
|
+
import { ModeWatcher } from 'mode-watcher';
|
|
6607
|
+
import { Button, Toaster, toast, Seo } from '@beeblock/svelar/ui';
|
|
6679
6608
|
import { registerToast } from '@beeblock/svelar/http';
|
|
6680
6609
|
|
|
6681
6610
|
// Wire apiFetch error handling to the toast UI
|
|
@@ -6688,14 +6617,22 @@ export default class QueueHealthCheck extends ScheduledTask {
|
|
|
6688
6617
|
const year = new Date().getFullYear();
|
|
6689
6618
|
</script>
|
|
6690
6619
|
|
|
6620
|
+
<!-- Site-wide SEO defaults \u2014 override per page with another <Seo> -->
|
|
6621
|
+
<Seo
|
|
6622
|
+
title="${e}"
|
|
6623
|
+
description="${e} \u2014 built with Svelar, the Laravel of SvelteKit."
|
|
6624
|
+
ogSiteName="${e}"
|
|
6625
|
+
ogType="website"
|
|
6626
|
+
/>
|
|
6627
|
+
|
|
6691
6628
|
<svelte:head>
|
|
6692
6629
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
6693
6630
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
|
|
6694
6631
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
6695
6632
|
</svelte:head>
|
|
6696
6633
|
|
|
6697
|
-
<div class="flex flex-col min-h-screen">
|
|
6698
|
-
<nav class="border-b border-
|
|
6634
|
+
<div class="flex flex-col min-h-screen bg-background text-foreground">
|
|
6635
|
+
<nav class="border-b border-border bg-card shadow-sm sticky top-0 z-50">
|
|
6699
6636
|
<div class="px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
|
|
6700
6637
|
<div class="flex items-center gap-6">
|
|
6701
6638
|
<a href="/" class="flex items-center gap-2">
|
|
@@ -6705,16 +6642,16 @@ export default class QueueHealthCheck extends ScheduledTask {
|
|
|
6705
6642
|
<span class="font-bold text-lg">${e}</span>
|
|
6706
6643
|
</a>
|
|
6707
6644
|
{#if data.user}
|
|
6708
|
-
<a href="/dashboard" class="text-
|
|
6645
|
+
<a href="/dashboard" class="text-muted-foreground hover:text-foreground text-sm font-medium">Dashboard</a>
|
|
6709
6646
|
{#if data.user.role === 'admin'}
|
|
6710
|
-
<a href="/admin" class="text-
|
|
6647
|
+
<a href="/admin" class="text-muted-foreground hover:text-foreground text-sm font-medium">Admin</a>
|
|
6711
6648
|
{/if}
|
|
6712
6649
|
{/if}
|
|
6713
6650
|
</div>
|
|
6714
6651
|
|
|
6715
6652
|
<div class="flex items-center gap-3">
|
|
6716
6653
|
{#if data.user}
|
|
6717
|
-
<span class="text-sm text-
|
|
6654
|
+
<span class="text-sm text-muted-foreground hidden sm:inline">{data.user.name}</span>
|
|
6718
6655
|
<form method="POST" action="/logout">
|
|
6719
6656
|
<Button type="submit" variant="ghost" size="sm">Logout</Button>
|
|
6720
6657
|
</form>
|
|
@@ -6730,11 +6667,12 @@ export default class QueueHealthCheck extends ScheduledTask {
|
|
|
6730
6667
|
{@render children()}
|
|
6731
6668
|
</main>
|
|
6732
6669
|
|
|
6733
|
-
<footer class="border-t border-
|
|
6670
|
+
<footer class="border-t border-border bg-card py-8 text-center text-sm text-muted-foreground">
|
|
6734
6671
|
<p>© {year} ${e}. All rights reserved.</p>
|
|
6735
6672
|
</footer>
|
|
6736
6673
|
</div>
|
|
6737
6674
|
|
|
6675
|
+
<ModeWatcher defaultMode="light" />
|
|
6738
6676
|
<Toaster position="bottom-right" />
|
|
6739
6677
|
|
|
6740
6678
|
<style>
|
|
@@ -6771,11 +6709,11 @@ export async function load(event: ServerLoadEvent) {
|
|
|
6771
6709
|
|
|
6772
6710
|
<div class="flex items-center justify-center min-h-[calc(100vh-200px)] px-4">
|
|
6773
6711
|
<div class="text-center max-w-md">
|
|
6774
|
-
<h1 class="text-7xl font-bold text-
|
|
6775
|
-
<p class="text-xl font-semibold text-
|
|
6712
|
+
<h1 class="text-7xl font-bold text-muted mb-4">{page.status}</h1>
|
|
6713
|
+
<p class="text-xl font-semibold text-foreground mb-2">
|
|
6776
6714
|
{page.status === 404 ? 'Page Not Found' : page.status === 403 ? 'Forbidden' : page.status === 401 ? 'Unauthorized' : 'Something Went Wrong'}
|
|
6777
6715
|
</p>
|
|
6778
|
-
<p class="text-
|
|
6716
|
+
<p class="text-muted-foreground mb-8">
|
|
6779
6717
|
{page.error?.message || 'An unexpected error occurred. Please try again.'}
|
|
6780
6718
|
</p>
|
|
6781
6719
|
<div class="flex gap-3 justify-center">
|
|
@@ -6843,14 +6781,15 @@ export class EventServiceProvider extends BaseProvider {
|
|
|
6843
6781
|
protected subscribe = [];
|
|
6844
6782
|
}
|
|
6845
6783
|
`}static homePage(e){return`<script lang="ts">
|
|
6846
|
-
import { Button, Card, Badge, Separator } from '@beeblock/svelar/ui';
|
|
6784
|
+
import { Button, Card, Badge, Separator, Seo } from '@beeblock/svelar/ui';
|
|
6847
6785
|
</script>
|
|
6848
6786
|
|
|
6849
|
-
<
|
|
6850
|
-
|
|
6851
|
-
|
|
6787
|
+
<Seo
|
|
6788
|
+
title="${e} \u2014 Powered by Svelar"
|
|
6789
|
+
description="Welcome to ${e}. A modern SaaS application built with Svelar and SvelteKit."
|
|
6790
|
+
/>
|
|
6852
6791
|
|
|
6853
|
-
<div class="min-h-screen
|
|
6792
|
+
<div class="min-h-screen flex flex-col items-center justify-center px-4">
|
|
6854
6793
|
<div class="text-center max-w-lg">
|
|
6855
6794
|
<div class="w-16 h-16 bg-brand rounded-2xl flex items-center justify-center mx-auto mb-6">
|
|
6856
6795
|
<span class="text-white font-bold text-2xl"></></span>
|
|
@@ -6858,13 +6797,13 @@ export class EventServiceProvider extends BaseProvider {
|
|
|
6858
6797
|
|
|
6859
6798
|
<Badge variant="outline" class="mb-4">Svelar + SvelteKit</Badge>
|
|
6860
6799
|
|
|
6861
|
-
<h1 class="text-4xl font-extrabold
|
|
6800
|
+
<h1 class="text-4xl font-extrabold mb-4">
|
|
6862
6801
|
Welcome to <span class="text-brand">${e}</span>
|
|
6863
6802
|
</h1>
|
|
6864
6803
|
|
|
6865
|
-
<p class="text-
|
|
6804
|
+
<p class="text-muted-foreground mb-8 leading-relaxed">
|
|
6866
6805
|
Your new Svelar project is ready. Edit
|
|
6867
|
-
<code class="bg-
|
|
6806
|
+
<code class="bg-muted px-1.5 py-0.5 rounded text-sm text-brand">src/routes/+page.svelte</code>
|
|
6868
6807
|
to get started.
|
|
6869
6808
|
</p>
|
|
6870
6809
|
|
|
@@ -6878,435 +6817,19 @@ export class EventServiceProvider extends BaseProvider {
|
|
|
6878
6817
|
|
|
6879
6818
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 max-w-2xl w-full">
|
|
6880
6819
|
<Card class="p-5 text-center">
|
|
6881
|
-
<h3 class="font-semibold
|
|
6882
|
-
<p class="text-sm text-
|
|
6820
|
+
<h3 class="font-semibold mb-1">ORM</h3>
|
|
6821
|
+
<p class="text-sm text-muted-foreground">Eloquent-style models with Drizzle</p>
|
|
6883
6822
|
</Card>
|
|
6884
6823
|
<Card class="p-5 text-center">
|
|
6885
|
-
<h3 class="font-semibold
|
|
6886
|
-
<p class="text-sm text-
|
|
6824
|
+
<h3 class="font-semibold mb-1">Auth</h3>
|
|
6825
|
+
<p class="text-sm text-muted-foreground">Sessions, JWT, API tokens</p>
|
|
6887
6826
|
</Card>
|
|
6888
6827
|
<Card class="p-5 text-center">
|
|
6889
|
-
<h3 class="font-semibold
|
|
6890
|
-
<p class="text-sm text-
|
|
6828
|
+
<h3 class="font-semibold mb-1">Middleware</h3>
|
|
6829
|
+
<p class="text-sm text-muted-foreground">CORS, CSRF, rate limiting</p>
|
|
6891
6830
|
</Card>
|
|
6892
6831
|
</div>
|
|
6893
6832
|
</div>
|
|
6894
|
-
`}static addStripeToUsers(){return`import { Migration } from '@beeblock/svelar/database';
|
|
6895
|
-
|
|
6896
|
-
export default class AddStripeToUsers extends Migration {
|
|
6897
|
-
async up() {
|
|
6898
|
-
await this.schema.addColumn('users', (table) => {
|
|
6899
|
-
table.string('stripe_customer_id').nullable();
|
|
6900
|
-
});
|
|
6901
|
-
}
|
|
6902
|
-
|
|
6903
|
-
async down() {
|
|
6904
|
-
await this.schema.dropColumn('users', 'stripe_customer_id');
|
|
6905
|
-
}
|
|
6906
|
-
}
|
|
6907
|
-
`}static createSubscriptionPlansTable(){return`import { Migration } from '@beeblock/svelar/database';
|
|
6908
|
-
|
|
6909
|
-
export default class CreateSubscriptionPlansTable extends Migration {
|
|
6910
|
-
async up() {
|
|
6911
|
-
await this.schema.createTable('subscription_plans', (table) => {
|
|
6912
|
-
table.increments('id').primary();
|
|
6913
|
-
table.string('name');
|
|
6914
|
-
table.string('stripe_price_id').unique();
|
|
6915
|
-
table.string('stripe_product_id');
|
|
6916
|
-
table.integer('price');
|
|
6917
|
-
table.string('currency').default('usd');
|
|
6918
|
-
table.string('interval').default('month');
|
|
6919
|
-
table.integer('interval_count').default(1);
|
|
6920
|
-
table.integer('trial_days').default(0);
|
|
6921
|
-
table.text('features').default('[]');
|
|
6922
|
-
table.integer('sort_order').default(0);
|
|
6923
|
-
table.integer('active').default(1);
|
|
6924
|
-
table.string('created_at');
|
|
6925
|
-
table.string('updated_at');
|
|
6926
|
-
});
|
|
6927
|
-
}
|
|
6928
|
-
|
|
6929
|
-
async down() {
|
|
6930
|
-
await this.schema.dropTable('subscription_plans');
|
|
6931
|
-
}
|
|
6932
|
-
}
|
|
6933
|
-
`}static createSubscriptionsTable(){return`import { Migration } from '@beeblock/svelar/database';
|
|
6934
|
-
|
|
6935
|
-
export default class CreateSubscriptionsTable extends Migration {
|
|
6936
|
-
async up() {
|
|
6937
|
-
await this.schema.createTable('subscriptions', (table) => {
|
|
6938
|
-
table.increments('id').primary();
|
|
6939
|
-
table.integer('user_id');
|
|
6940
|
-
table.string('stripe_subscription_id').unique();
|
|
6941
|
-
table.string('stripe_customer_id');
|
|
6942
|
-
table.integer('plan_id');
|
|
6943
|
-
table.string('status').default('active');
|
|
6944
|
-
table.string('current_period_start');
|
|
6945
|
-
table.string('current_period_end');
|
|
6946
|
-
table.integer('cancel_at_period_end').default(0);
|
|
6947
|
-
table.string('trial_ends_at').nullable();
|
|
6948
|
-
table.string('canceled_at').nullable();
|
|
6949
|
-
table.string('created_at');
|
|
6950
|
-
table.string('updated_at');
|
|
6951
|
-
});
|
|
6952
|
-
}
|
|
6953
|
-
|
|
6954
|
-
async down() {
|
|
6955
|
-
await this.schema.dropTable('subscriptions');
|
|
6956
|
-
}
|
|
6957
|
-
}
|
|
6958
|
-
`}static createInvoicesTable(){return`import { Migration } from '@beeblock/svelar/database';
|
|
6959
|
-
|
|
6960
|
-
export default class CreateInvoicesTable extends Migration {
|
|
6961
|
-
async up() {
|
|
6962
|
-
await this.schema.createTable('invoices', (table) => {
|
|
6963
|
-
table.increments('id').primary();
|
|
6964
|
-
table.integer('user_id');
|
|
6965
|
-
table.integer('subscription_id').nullable();
|
|
6966
|
-
table.string('stripe_invoice_id').unique();
|
|
6967
|
-
table.integer('amount_due');
|
|
6968
|
-
table.integer('amount_paid');
|
|
6969
|
-
table.string('currency').default('usd');
|
|
6970
|
-
table.string('status').default('open');
|
|
6971
|
-
table.string('paid_at').nullable();
|
|
6972
|
-
table.string('due_date').nullable();
|
|
6973
|
-
table.text('invoice_pdf').nullable();
|
|
6974
|
-
table.string('created_at');
|
|
6975
|
-
table.string('updated_at').nullable();
|
|
6976
|
-
});
|
|
6977
|
-
}
|
|
6978
|
-
|
|
6979
|
-
async down() {
|
|
6980
|
-
await this.schema.dropTable('invoices');
|
|
6981
|
-
}
|
|
6982
|
-
}
|
|
6983
|
-
`}static billingPageServer(){return`import type { Actions, PageServerLoad } from './$types';
|
|
6984
|
-
import { fail, redirect } from '@sveltejs/kit';
|
|
6985
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
6986
|
-
|
|
6987
|
-
export const load: PageServerLoad = async ({ locals }) => {
|
|
6988
|
-
const user = locals.user as any;
|
|
6989
|
-
let subscription: any = null;
|
|
6990
|
-
let invoices: any[] = [];
|
|
6991
|
-
const plans: any[] = [];
|
|
6992
|
-
|
|
6993
|
-
try {
|
|
6994
|
-
const service = Stripe.service();
|
|
6995
|
-
if (user.stripe_customer_id) {
|
|
6996
|
-
const client = await service.getClient();
|
|
6997
|
-
const subs = await client.subscriptions.list({
|
|
6998
|
-
customer: user.stripe_customer_id,
|
|
6999
|
-
limit: 1,
|
|
7000
|
-
expand: ['data.default_payment_method'],
|
|
7001
|
-
});
|
|
7002
|
-
if (subs.data.length > 0) {
|
|
7003
|
-
const sub = subs.data[0] as any;
|
|
7004
|
-
subscription = {
|
|
7005
|
-
id: sub.id,
|
|
7006
|
-
status: sub.status,
|
|
7007
|
-
cancelAtPeriodEnd: sub.cancel_at_period_end,
|
|
7008
|
-
currentPeriodEnd: sub.current_period_end
|
|
7009
|
-
? new Date(typeof sub.current_period_end === 'number' ? sub.current_period_end * 1000 : sub.current_period_end).toISOString()
|
|
7010
|
-
: null,
|
|
7011
|
-
trialEnd: sub.trial_end
|
|
7012
|
-
? new Date(typeof sub.trial_end === 'number' ? sub.trial_end * 1000 : sub.trial_end).toISOString()
|
|
7013
|
-
: null,
|
|
7014
|
-
plan: {
|
|
7015
|
-
nickname: sub.items?.data?.[0]?.price?.nickname ?? 'Plan',
|
|
7016
|
-
amount: sub.items?.data?.[0]?.price?.unit_amount ?? 0,
|
|
7017
|
-
currency: sub.items?.data?.[0]?.price?.currency ?? 'usd',
|
|
7018
|
-
interval: sub.items?.data?.[0]?.price?.recurring?.interval ?? 'month',
|
|
7019
|
-
},
|
|
7020
|
-
};
|
|
7021
|
-
}
|
|
7022
|
-
|
|
7023
|
-
const invResponse = await service.getInvoices(user.stripe_customer_id, 10);
|
|
7024
|
-
invoices = invResponse.map((inv: any) => ({
|
|
7025
|
-
id: inv.id,
|
|
7026
|
-
amountDue: inv.amount_due,
|
|
7027
|
-
amountPaid: inv.amount_paid,
|
|
7028
|
-
currency: inv.currency,
|
|
7029
|
-
status: inv.status,
|
|
7030
|
-
created: new Date(typeof inv.created === 'number' ? inv.created * 1000 : inv.created).toISOString(),
|
|
7031
|
-
invoicePdf: inv.invoice_pdf ?? null,
|
|
7032
|
-
hostedUrl: inv.hosted_invoice_url ?? null,
|
|
7033
|
-
}));
|
|
7034
|
-
}
|
|
7035
|
-
} catch {}
|
|
7036
|
-
|
|
7037
|
-
return { user: { id: user.id, name: user.name, email: user.email, stripeCustomerId: user.stripe_customer_id }, subscription, invoices, plans };
|
|
7038
|
-
};
|
|
7039
|
-
|
|
7040
|
-
export const actions: Actions = {
|
|
7041
|
-
portal: async ({ locals }) => {
|
|
7042
|
-
const user = locals.user as any;
|
|
7043
|
-
if (!user?.stripe_customer_id) return fail(400, { error: 'No billing account' });
|
|
7044
|
-
|
|
7045
|
-
try {
|
|
7046
|
-
const session = await Stripe.service().createPortalSession(
|
|
7047
|
-
user.stripe_customer_id,
|
|
7048
|
-
'/dashboard/billing',
|
|
7049
|
-
);
|
|
7050
|
-
throw redirect(303, session.url);
|
|
7051
|
-
} catch (e: any) {
|
|
7052
|
-
if (e.status === 303) throw e;
|
|
7053
|
-
return fail(500, { error: e.message ?? 'Failed to open portal' });
|
|
7054
|
-
}
|
|
7055
|
-
},
|
|
7056
|
-
|
|
7057
|
-
cancel: async ({ locals }) => {
|
|
7058
|
-
const user = locals.user as any;
|
|
7059
|
-
if (!user?.stripe_customer_id) return fail(400, { error: 'No billing account' });
|
|
7060
|
-
|
|
7061
|
-
try {
|
|
7062
|
-
const client = await Stripe.service().getClient();
|
|
7063
|
-
const subs = await client.subscriptions.list({ customer: user.stripe_customer_id, status: 'active', limit: 1 });
|
|
7064
|
-
if (subs.data.length === 0) return fail(400, { error: 'No active subscription' });
|
|
7065
|
-
await Stripe.service().cancelSubscription(subs.data[0].id, false);
|
|
7066
|
-
return { success: true, canceled: true };
|
|
7067
|
-
} catch (e: any) {
|
|
7068
|
-
return fail(500, { error: e.message ?? 'Failed to cancel' });
|
|
7069
|
-
}
|
|
7070
|
-
},
|
|
7071
|
-
|
|
7072
|
-
resume: async ({ locals }) => {
|
|
7073
|
-
const user = locals.user as any;
|
|
7074
|
-
if (!user?.stripe_customer_id) return fail(400, { error: 'No billing account' });
|
|
7075
|
-
|
|
7076
|
-
try {
|
|
7077
|
-
const client = await Stripe.service().getClient();
|
|
7078
|
-
const subs = await client.subscriptions.list({ customer: user.stripe_customer_id, limit: 1 });
|
|
7079
|
-
if (subs.data.length === 0) return fail(400, { error: 'No subscription found' });
|
|
7080
|
-
await Stripe.service().resumeSubscription(subs.data[0].id);
|
|
7081
|
-
return { success: true, resumed: true };
|
|
7082
|
-
} catch (e: any) {
|
|
7083
|
-
return fail(500, { error: e.message ?? 'Failed to resume' });
|
|
7084
|
-
}
|
|
7085
|
-
},
|
|
7086
|
-
};
|
|
7087
|
-
`}static billingPageSvelte(){return`<script lang="ts">
|
|
7088
|
-
import { enhance } from '$app/forms';
|
|
7089
|
-
import { Button, Badge, Card, CardHeader, CardTitle, CardContent, Alert } from '@beeblock/svelar/ui';
|
|
7090
|
-
|
|
7091
|
-
let { data, form: actionData } = $props();
|
|
7092
|
-
|
|
7093
|
-
function formatCurrency(amount: number, currency: string): string {
|
|
7094
|
-
return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency.toUpperCase() }).format(amount / 100);
|
|
7095
|
-
}
|
|
7096
|
-
|
|
7097
|
-
function statusColor(status: string): 'default' | 'secondary' | 'destructive' {
|
|
7098
|
-
if (status === 'active' || status === 'trialing' || status === 'paid') return 'default';
|
|
7099
|
-
if (status === 'past_due' || status === 'incomplete') return 'secondary';
|
|
7100
|
-
return 'destructive';
|
|
7101
|
-
}
|
|
7102
|
-
</script>
|
|
7103
|
-
|
|
7104
|
-
<svelte:head>
|
|
7105
|
-
<title>Billing</title>
|
|
7106
|
-
</svelte:head>
|
|
7107
|
-
|
|
7108
|
-
<div class="space-y-8">
|
|
7109
|
-
<div>
|
|
7110
|
-
<h1 class="text-3xl font-bold text-gray-900">Billing</h1>
|
|
7111
|
-
<p class="text-gray-600 mt-1">Manage your subscription and billing</p>
|
|
7112
|
-
</div>
|
|
7113
|
-
|
|
7114
|
-
{#if actionData?.error}
|
|
7115
|
-
<Alert variant="destructive"><span class="text-sm">{actionData.error}</span></Alert>
|
|
7116
|
-
{/if}
|
|
7117
|
-
{#if actionData?.canceled}
|
|
7118
|
-
<Alert variant="default"><span class="text-sm">Subscription will cancel at end of billing period.</span></Alert>
|
|
7119
|
-
{/if}
|
|
7120
|
-
{#if actionData?.resumed}
|
|
7121
|
-
<Alert variant="default"><span class="text-sm">Subscription resumed successfully.</span></Alert>
|
|
7122
|
-
{/if}
|
|
7123
|
-
|
|
7124
|
-
<Card>
|
|
7125
|
-
<CardHeader>
|
|
7126
|
-
<CardTitle>Current Plan</CardTitle>
|
|
7127
|
-
</CardHeader>
|
|
7128
|
-
<CardContent>
|
|
7129
|
-
{#if data.subscription}
|
|
7130
|
-
<div class="flex items-start justify-between">
|
|
7131
|
-
<div>
|
|
7132
|
-
<div class="flex items-center gap-2 mb-2">
|
|
7133
|
-
<h3 class="text-xl font-semibold text-gray-900">{data.subscription.plan.nickname}</h3>
|
|
7134
|
-
<Badge variant={statusColor(data.subscription.status)}>{data.subscription.status}</Badge>
|
|
7135
|
-
</div>
|
|
7136
|
-
<p class="text-2xl font-bold text-brand">
|
|
7137
|
-
{formatCurrency(data.subscription.plan.amount, data.subscription.plan.currency)}/{data.subscription.plan.interval}
|
|
7138
|
-
</p>
|
|
7139
|
-
{#if data.subscription.trialEnd}
|
|
7140
|
-
<p class="text-sm text-gray-500 mt-1">Trial ends {new Date(data.subscription.trialEnd).toLocaleDateString()}</p>
|
|
7141
|
-
{/if}
|
|
7142
|
-
{#if data.subscription.cancelAtPeriodEnd}
|
|
7143
|
-
<p class="text-sm text-orange-600 mt-1">Cancels on {new Date(data.subscription.currentPeriodEnd).toLocaleDateString()}</p>
|
|
7144
|
-
{:else if data.subscription.currentPeriodEnd}
|
|
7145
|
-
<p class="text-sm text-gray-500 mt-1">Renews {new Date(data.subscription.currentPeriodEnd).toLocaleDateString()}</p>
|
|
7146
|
-
{/if}
|
|
7147
|
-
</div>
|
|
7148
|
-
<div class="flex flex-col gap-2">
|
|
7149
|
-
<form method="POST" action="?/portal" use:enhance>
|
|
7150
|
-
<Button type="submit" variant="outline" size="sm">Manage Payment</Button>
|
|
7151
|
-
</form>
|
|
7152
|
-
{#if data.subscription.cancelAtPeriodEnd}
|
|
7153
|
-
<form method="POST" action="?/resume" use:enhance>
|
|
7154
|
-
<Button type="submit" size="sm">Resume</Button>
|
|
7155
|
-
</form>
|
|
7156
|
-
{:else if data.subscription.status === 'active' || data.subscription.status === 'trialing'}
|
|
7157
|
-
<form method="POST" action="?/cancel" use:enhance>
|
|
7158
|
-
<Button type="submit" variant="destructive" size="sm"
|
|
7159
|
-
onclick={(e) => { if (!confirm('Cancel your subscription? You will retain access until the end of the billing period.')) e.preventDefault(); }}>
|
|
7160
|
-
Cancel Plan
|
|
7161
|
-
</Button>
|
|
7162
|
-
</form>
|
|
7163
|
-
{/if}
|
|
7164
|
-
</div>
|
|
7165
|
-
</div>
|
|
7166
|
-
{:else}
|
|
7167
|
-
<div class="text-center py-6">
|
|
7168
|
-
<p class="text-gray-500 mb-4">No active subscription</p>
|
|
7169
|
-
<p class="text-sm text-gray-400">Contact us or visit the pricing page to get started.</p>
|
|
7170
|
-
</div>
|
|
7171
|
-
{/if}
|
|
7172
|
-
</CardContent>
|
|
7173
|
-
</Card>
|
|
7174
|
-
|
|
7175
|
-
<div>
|
|
7176
|
-
<h2 class="text-xl font-bold text-gray-900 mb-4">Invoice History</h2>
|
|
7177
|
-
{#if data.invoices.length === 0}
|
|
7178
|
-
<Card>
|
|
7179
|
-
<CardContent class="pt-8 text-center">
|
|
7180
|
-
<p class="text-gray-500 text-sm">No invoices yet.</p>
|
|
7181
|
-
</CardContent>
|
|
7182
|
-
</Card>
|
|
7183
|
-
{:else}
|
|
7184
|
-
<div class="border rounded-lg overflow-hidden">
|
|
7185
|
-
<table class="w-full text-sm">
|
|
7186
|
-
<thead class="bg-gray-50 text-left">
|
|
7187
|
-
<tr>
|
|
7188
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Date</th>
|
|
7189
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Amount</th>
|
|
7190
|
-
<th class="px-4 py-3 text-gray-600 font-medium">Status</th>
|
|
7191
|
-
<th class="px-4 py-3 text-gray-600 font-medium text-right">Invoice</th>
|
|
7192
|
-
</tr>
|
|
7193
|
-
</thead>
|
|
7194
|
-
<tbody class="divide-y">
|
|
7195
|
-
{#each data.invoices as inv (inv.id)}
|
|
7196
|
-
<tr class="hover:bg-gray-50">
|
|
7197
|
-
<td class="px-4 py-3">{new Date(inv.created).toLocaleDateString()}</td>
|
|
7198
|
-
<td class="px-4 py-3 font-medium">{formatCurrency(inv.amountDue, inv.currency)}</td>
|
|
7199
|
-
<td class="px-4 py-3"><Badge variant={statusColor(inv.status)}>{inv.status}</Badge></td>
|
|
7200
|
-
<td class="px-4 py-3 text-right">
|
|
7201
|
-
{#if inv.invoicePdf}
|
|
7202
|
-
<a href={inv.invoicePdf} target="_blank" rel="noopener" class="text-brand hover:underline text-xs">PDF</a>
|
|
7203
|
-
{/if}
|
|
7204
|
-
{#if inv.hostedUrl}
|
|
7205
|
-
<a href={inv.hostedUrl} target="_blank" rel="noopener" class="text-brand hover:underline text-xs ml-2">View</a>
|
|
7206
|
-
{/if}
|
|
7207
|
-
</td>
|
|
7208
|
-
</tr>
|
|
7209
|
-
{/each}
|
|
7210
|
-
</tbody>
|
|
7211
|
-
</table>
|
|
7212
|
-
</div>
|
|
7213
|
-
{/if}
|
|
7214
|
-
</div>
|
|
7215
|
-
</div>
|
|
7216
|
-
`}static stripeWebhookRoute(){return`import type { RequestHandler } from './$types';
|
|
7217
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
7218
|
-
|
|
7219
|
-
export const POST: RequestHandler = async ({ request }) => {
|
|
7220
|
-
const signature = request.headers.get('stripe-signature');
|
|
7221
|
-
if (!signature) {
|
|
7222
|
-
return new Response(JSON.stringify({ error: 'Missing signature' }), { status: 400 });
|
|
7223
|
-
}
|
|
7224
|
-
|
|
7225
|
-
try {
|
|
7226
|
-
const body = await request.text();
|
|
7227
|
-
const event = await Stripe.service().constructWebhookEvent(body, signature);
|
|
7228
|
-
await Stripe.webhooks().handle(event);
|
|
7229
|
-
return new Response(JSON.stringify({ received: true }), { status: 200 });
|
|
7230
|
-
} catch (err: any) {
|
|
7231
|
-
console.error('Stripe webhook error:', err.message);
|
|
7232
|
-
return new Response(JSON.stringify({ error: 'Webhook failed' }), { status: 400 });
|
|
7233
|
-
}
|
|
7234
|
-
};
|
|
7235
|
-
`}static apiAdminBillingSubscriptions(){return`import type { RequestHandler } from './$types';
|
|
7236
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
7237
|
-
|
|
7238
|
-
export const GET: RequestHandler = async ({ url }) => {
|
|
7239
|
-
try {
|
|
7240
|
-
const limit = Number(url.searchParams.get('limit') ?? '25');
|
|
7241
|
-
const startingAfter = url.searchParams.get('starting_after') ?? undefined;
|
|
7242
|
-
const client = await Stripe.service().getClient();
|
|
7243
|
-
const subs = await client.subscriptions.list({
|
|
7244
|
-
limit,
|
|
7245
|
-
starting_after: startingAfter,
|
|
7246
|
-
expand: ['data.customer'],
|
|
7247
|
-
});
|
|
7248
|
-
|
|
7249
|
-
const data = subs.data.map((sub: any) => ({
|
|
7250
|
-
id: sub.id,
|
|
7251
|
-
status: sub.status,
|
|
7252
|
-
cancelAtPeriodEnd: sub.cancel_at_period_end,
|
|
7253
|
-
customer: {
|
|
7254
|
-
id: typeof sub.customer === 'string' ? sub.customer : sub.customer?.id,
|
|
7255
|
-
email: typeof sub.customer === 'object' ? sub.customer?.email : null,
|
|
7256
|
-
name: typeof sub.customer === 'object' ? sub.customer?.name : null,
|
|
7257
|
-
},
|
|
7258
|
-
plan: {
|
|
7259
|
-
nickname: sub.items?.data?.[0]?.price?.nickname ?? 'Plan',
|
|
7260
|
-
amount: sub.items?.data?.[0]?.price?.unit_amount ?? 0,
|
|
7261
|
-
currency: sub.items?.data?.[0]?.price?.currency ?? 'usd',
|
|
7262
|
-
interval: sub.items?.data?.[0]?.price?.recurring?.interval ?? 'month',
|
|
7263
|
-
},
|
|
7264
|
-
created: sub.created,
|
|
7265
|
-
}));
|
|
7266
|
-
|
|
7267
|
-
return new Response(JSON.stringify({ subscriptions: data, hasMore: subs.has_more }), {
|
|
7268
|
-
headers: { 'Content-Type': 'application/json' },
|
|
7269
|
-
});
|
|
7270
|
-
} catch (err: any) {
|
|
7271
|
-
return new Response(JSON.stringify({ error: err.message }), { status: 500 });
|
|
7272
|
-
}
|
|
7273
|
-
};
|
|
7274
|
-
`}static apiAdminBillingRefund(){return`import type { RequestHandler } from './$types';
|
|
7275
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
7276
|
-
|
|
7277
|
-
export const POST: RequestHandler = async ({ request }) => {
|
|
7278
|
-
try {
|
|
7279
|
-
const { invoiceId } = await request.json();
|
|
7280
|
-
if (!invoiceId) {
|
|
7281
|
-
return new Response(JSON.stringify({ error: 'invoiceId is required' }), { status: 400 });
|
|
7282
|
-
}
|
|
7283
|
-
|
|
7284
|
-
const refund = await Stripe.service().refundInvoice(invoiceId);
|
|
7285
|
-
return new Response(JSON.stringify({ refund: { id: refund.id, amount: refund.amount, status: refund.status } }), {
|
|
7286
|
-
headers: { 'Content-Type': 'application/json' },
|
|
7287
|
-
});
|
|
7288
|
-
} catch (err: any) {
|
|
7289
|
-
return new Response(JSON.stringify({ error: err.message }), { status: 500 });
|
|
7290
|
-
}
|
|
7291
|
-
};
|
|
7292
|
-
`}static apiAdminBillingCancel(){return`import type { RequestHandler } from './$types';
|
|
7293
|
-
import { Stripe } from '@beeblock/svelar/stripe';
|
|
7294
|
-
|
|
7295
|
-
export const POST: RequestHandler = async ({ request }) => {
|
|
7296
|
-
try {
|
|
7297
|
-
const { subscriptionId, immediately } = await request.json();
|
|
7298
|
-
if (!subscriptionId) {
|
|
7299
|
-
return new Response(JSON.stringify({ error: 'subscriptionId is required' }), { status: 400 });
|
|
7300
|
-
}
|
|
7301
|
-
|
|
7302
|
-
const sub = await Stripe.service().cancelSubscription(subscriptionId, immediately ?? false);
|
|
7303
|
-
return new Response(JSON.stringify({ subscription: { id: sub.id, status: sub.status, cancel_at_period_end: sub.cancel_at_period_end } }), {
|
|
7304
|
-
headers: { 'Content-Type': 'application/json' },
|
|
7305
|
-
});
|
|
7306
|
-
} catch (err: any) {
|
|
7307
|
-
return new Response(JSON.stringify({ error: err.message }), { status: 500 });
|
|
7308
|
-
}
|
|
7309
|
-
};
|
|
7310
6833
|
`}static vitestConfig(){return`import { defineConfig } from 'vitest/config';
|
|
7311
6834
|
import { createRequire } from 'module';
|
|
7312
6835
|
import { dirname, resolve } from 'path';
|
|
@@ -7407,15 +6930,20 @@ export class UserFactory extends Factory<User> {
|
|
|
7407
6930
|
|
|
7408
6931
|
// Singleton instance for convenience
|
|
7409
6932
|
export default new UserFactory();
|
|
7410
|
-
`}};var ds=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:
|
|
7411
|
-
`);let u=(_,We)=>{let vs=p?jo(_):_,Je=p?Oo(We,_):We,Ve=s(m,vs);a(s(Ve,".."),{recursive:!0}),n(Ve,Je)};this.info("Creating project structure...");let b=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","tests/unit","tests/feature","tests/e2e","src/lib/factories"]:["","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","tests/unit","tests/feature","tests/e2e","src/lib/factories"];for(let _ of b)a(s(m,_),{recursive:!0});this.info("Writing config files...");let{dirname:v}=await import("path"),{fileURLToPath:y}=await import("url"),C=s(v(v(v(y(import.meta.url)))),"package.json"),A=JSON.parse((await import("fs")).readFileSync(C,"utf-8")).version??"0.4.0";u("package.json",d.packageJson(c,A)),u("svelte.config.js",d.svelteConfig()),u("vite.config.ts",d.viteConfig()),u("tsconfig.json",d.tsConfig()),u("src/app.html",d.appHtml()),u("static/favicon.svg",d.faviconSvg()),u("src/app.css",d.appCss()),u("src/app.ts",d.appTs()),u("src/hooks.server.ts",d.hooksServerTs()),u(".env.example",d.envExample());let{randomBytes:I}=await import("crypto"),xe=I(32).toString("hex"),Pe=I(16).toString("hex"),Fr=d.envExample().replace("APP_KEY=change-me-to-a-random-string",`APP_KEY=${xe}`).replace("INTERNAL_SECRET=change-me-to-a-random-string",`INTERNAL_SECRET=${Pe}`);u(".env",Fr),u(".gitignore",d.gitignore()),u("svelar.database.json",d.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",d.userModel()),u("src/lib/modules/auth/UserRepository.ts",d.userRepository()),u("src/lib/modules/auth/AuthService.ts",d.authService()),u("src/lib/modules/auth/AuthController.ts",d.authController()),u("src/lib/modules/auth/RegisterUserAction.ts",d.registerUserAction()),u("src/lib/modules/auth/RegisterRequest.ts",d.registerRequest()),u("src/lib/modules/auth/LoginRequest.ts",d.loginRequest()),u("src/lib/modules/auth/ForgotPasswordRequest.ts",d.forgotPasswordRequest()),u("src/lib/modules/auth/ResetPasswordRequest.ts",d.resetPasswordRequest()),u("src/lib/modules/auth/OtpSendRequest.ts",d.otpSendRequest()),u("src/lib/modules/auth/OtpVerifyRequest.ts",d.otpVerifyRequest()),u("src/lib/modules/auth/UserResource.ts",d.userResource()),u("src/lib/modules/auth/gates.ts",d.gates()),u("src/lib/modules/auth/schemas.ts",d.authSchema()),u("src/lib/modules/auth/UserRegistered.ts",d.userRegisteredEvent()),u("src/lib/modules/auth/SendWelcomeEmailListener.ts",d.sendWelcomeEmailListener()),u("src/lib/modules/auth/WelcomeNotification.ts",d.welcomeNotification()),u("src/lib/modules/posts/Post.ts",d.postModel()),u("src/lib/modules/posts/PostRepository.ts",d.postRepository()),u("src/lib/modules/posts/PostService.ts",d.postService()),u("src/lib/modules/posts/PostController.ts",d.postController()),u("src/lib/modules/posts/CreatePostAction.ts",d.createPostAction()),u("src/lib/modules/posts/CreatePostRequest.ts",d.createPostRequest()),u("src/lib/modules/posts/UpdatePostRequest.ts",d.updatePostRequest()),u("src/lib/modules/posts/PostResource.ts",d.postResource()),u("src/lib/modules/posts/schemas.ts",d.postSchema()),u("src/lib/modules/admin/AdminService.ts",d.adminService()),u("src/lib/modules/admin/AdminController.ts",d.adminController()),u("src/lib/modules/admin/UpdateUserRoleRequest.ts",d.updateUserRoleRequest()),u("src/lib/modules/admin/DeleteUserRequest.ts",d.deleteUserRequest()),u("src/lib/modules/admin/CreateRoleRequest.ts",d.createRoleRequest()),u("src/lib/modules/admin/DeleteRoleRequest.ts",d.deleteRoleRequest()),u("src/lib/modules/admin/CreatePermissionRequest.ts",d.createPermissionRequest()),u("src/lib/modules/admin/DeletePermissionRequest.ts",d.deletePermissionRequest()),u("src/lib/modules/admin/RolePermissionRequest.ts",d.rolePermissionRequest()),u("src/lib/modules/admin/UserRoleRequest.ts",d.userRoleRequest()),u("src/lib/modules/admin/UserPermissionRequest.ts",d.userPermissionRequest()),u("src/lib/modules/admin/ExportDataRequest.ts",d.exportDataRequest()),u("src/lib/modules/admin/RoleResource.ts",d.roleResource()),u("src/lib/modules/admin/PermissionResource.ts",d.permissionResource()),u("src/lib/modules/admin/schemas.ts",d.adminSchema()),u("src/lib/shared/providers/EventServiceProvider.ts",d.eventServiceProvider()),this.info("Creating migrations..."),u("src/lib/database/migrations/00000001_create_users_table.ts",d.createUsersTable()),u("src/lib/database/migrations/00000002_create_posts_table.ts",d.createPostsTable()),u("src/lib/database/migrations/00000003_create_permissions_tables.ts",d.createPermissionsTables()),u("src/lib/database/migrations/00000004_add_role_to_users.ts",d.addRoleToUsers()),u("src/lib/database/migrations/00000005_create_sessions_table.ts",d.createSessionsTable()),u("src/lib/database/migrations/00000006_create_audit_logs_table.ts",d.createAuditLogsTable()),u("src/lib/database/migrations/00000007_create_notifications_table.ts",d.createNotificationsTable()),u("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",d.createFailedJobsTable()),u("src/lib/database/migrations/00000009_add_stripe_to_users.ts",d.addStripeToUsers()),u("src/lib/database/migrations/00000010_create_subscription_plans.ts",d.createSubscriptionPlansTable()),u("src/lib/database/migrations/00000011_create_subscriptions.ts",d.createSubscriptionsTable()),u("src/lib/database/migrations/00000012_create_invoices.ts",d.createInvoicesTable()),u("src/lib/database/seeders/DatabaseSeeder.ts",d.databaseSeeder()),this.info("Creating auth pages..."),u("src/routes/login/+page.server.ts",d.loginPageServer()),u("src/routes/login/+page.svelte",d.loginPageSvelte()),u("src/routes/register/+page.server.ts",d.registerPageServer()),u("src/routes/register/+page.svelte",d.registerPageSvelte()),u("src/routes/logout/+page.server.ts",d.logoutPageServer()),u("src/routes/forgot-password/+page.server.ts",d.forgotPasswordPageServer()),u("src/routes/forgot-password/+page.svelte",d.forgotPasswordPageSvelte()),u("src/routes/reset-password/+page.server.ts",d.resetPasswordPageServer()),u("src/routes/reset-password/+page.svelte",d.resetPasswordPageSvelte()),u("src/routes/otp-login/+page.server.ts",d.otpLoginPageServer()),u("src/routes/otp-login/+page.svelte",d.otpLoginPageSvelte()),u("src/routes/verify-email/+page.server.ts",d.verifyEmailPageServer()),u("src/routes/verify-email/+page.svelte",d.verifyEmailPageSvelte()),this.info("Creating dashboard..."),u("src/routes/dashboard/+layout.server.ts",d.dashboardLayoutServer()),u("src/routes/dashboard/+layout.svelte",d.dashboardLayoutSvelte()),u("src/routes/dashboard/+page.server.ts",d.dashboardPageServer()),u("src/routes/dashboard/+page.svelte",d.dashboardPageSvelte()),u("src/routes/dashboard/api-keys/+page.server.ts",d.apiKeysPageServer()),u("src/routes/dashboard/api-keys/+page.svelte",d.apiKeysPageSvelte()),u("src/routes/dashboard/team/+page.server.ts",d.teamPageServer()),u("src/routes/dashboard/team/+page.svelte",d.teamPageSvelte()),u("src/routes/dashboard/billing/+page.server.ts",d.billingPageServer()),u("src/routes/dashboard/billing/+page.svelte",d.billingPageSvelte()),this.info("Creating admin panel..."),u("src/routes/admin/+layout.server.ts",d.adminLayoutServer()),u("src/routes/admin/+layout.svelte",d.adminLayoutSvelte()),u("src/routes/admin/+page.server.ts",d.adminPageServer()),u("src/routes/admin/+page.svelte",d.adminPageSvelte()),this.info("Creating API routes..."),u("src/routes/api/health/+server.ts",d.apiHealth()),u("src/routes/api/auth/register/+server.ts",d.apiAuthRegister()),u("src/routes/api/auth/login/+server.ts",d.apiAuthLogin()),u("src/routes/api/auth/logout/+server.ts",d.apiAuthLogout()),u("src/routes/api/auth/me/+server.ts",d.apiAuthMe()),u("src/routes/api/auth/forgot-password/+server.ts",d.apiAuthForgotPassword()),u("src/routes/api/auth/reset-password/+server.ts",d.apiAuthResetPassword()),u("src/routes/api/auth/otp/send/+server.ts",d.apiAuthOtpSend()),u("src/routes/api/auth/otp/verify/+server.ts",d.apiAuthOtpVerify()),u("src/routes/api/auth/verify-email/+server.ts",d.apiAuthVerifyEmail()),u("src/routes/api/posts/+server.ts",d.apiPosts()),u("src/routes/api/posts/[id]/+server.ts",d.apiPostsSingle()),u("src/routes/api/posts/mine/+server.ts",d.apiPostsMine()),u("src/routes/api/broadcasting/[channel]/+server.ts",d.apiBroadcasting()),u("src/routes/api/internal/broadcast/+server.ts",d.apiInternalBroadcast()),u("src/routes/api/admin/users/+server.ts",d.apiAdminUsers()),u("src/routes/api/admin/roles/+server.ts",d.apiAdminRoles()),u("src/routes/api/admin/permissions/+server.ts",d.apiAdminPermissions()),u("src/routes/api/admin/role-permissions/+server.ts",d.apiAdminRolePermissions()),u("src/routes/api/admin/user-roles/+server.ts",d.apiAdminUserRoles()),u("src/routes/api/admin/user-permissions/+server.ts",d.apiAdminUserPermissions()),u("src/routes/api/admin/export/+server.ts",d.apiAdminExport()),u("src/routes/api/admin/health/+server.ts",d.apiAdminHealth()),u("src/routes/api/admin/queue/+server.ts",d.apiAdminQueue()),u("src/routes/api/admin/queue/[id]/retry/+server.ts",d.apiAdminQueueRetry()),u("src/routes/api/admin/queue/[id]/+server.ts",d.apiAdminQueueDelete()),u("src/routes/api/admin/scheduler/+server.ts",d.apiAdminScheduler()),u("src/routes/api/admin/scheduler/[name]/run/+server.ts",d.apiAdminSchedulerRun()),u("src/routes/api/admin/scheduler/[name]/toggle/+server.ts",d.apiAdminSchedulerToggle()),u("src/routes/api/admin/logs/+server.ts",d.apiAdminLogs()),u("src/routes/api/admin/stats/+server.ts",d.apiAdminStats()),u("src/routes/api/admin/billing/subscriptions/+server.ts",d.apiAdminBillingSubscriptions()),u("src/routes/api/admin/billing/refund/+server.ts",d.apiAdminBillingRefund()),u("src/routes/api/admin/billing/cancel/+server.ts",d.apiAdminBillingCancel()),u("src/routes/api/webhooks/stripe/+server.ts",d.stripeWebhookRoute()),this.info("Creating background jobs..."),u("src/lib/shared/jobs/SendWelcomeEmail.ts",d.sendWelcomeEmail()),u("src/lib/shared/jobs/DailyDigestJob.ts",d.dailyDigestJob()),u("src/lib/shared/jobs/ExportDataJob.ts",d.exportDataJob()),this.info("Creating scheduled tasks..."),u("src/lib/shared/scheduler/CleanupExpiredTokens.ts",d.cleanupExpiredTokens()),u("src/lib/shared/scheduler/CleanExpiredSessions.ts",d.cleanExpiredSessions()),u("src/lib/shared/scheduler/DailyDigestEmail.ts",d.dailyDigestEmail()),u("src/lib/shared/scheduler/PruneAuditLogs.ts",d.pruneAuditLogs()),u("src/lib/shared/scheduler/QueueHealthCheck.ts",d.queueHealthCheck()),this.info("Creating layouts..."),u("src/routes/+layout.svelte",d.rootLayoutSvelte(c)),u("src/routes/+layout.server.ts",d.rootLayoutServer()),u("src/routes/+error.svelte",d.errorSvelte()),u("src/routes/+page.svelte",d.homePage(c)),this.info("Setting up testing..."),u("vitest.config.ts",d.vitestConfig()),u("playwright.config.ts",d.playwrightConfig()),u("tests/unit/example.test.ts",d.exampleUnitTest()),u("tests/feature/auth.test.ts",d.exampleFeatureTest()),u("src/lib/factories/UserFactory.ts",d.scaffoldUserFactory()),this.success(`Project structure created (${h})`),!t["no-install"]){this.info("Installing dependencies...");try{l("npm install",{cwd:m,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:m,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:m,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!
|
|
6933
|
+
`}};var ds=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: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 m=r(process.cwd(),c);i(m)&&(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})
|
|
6934
|
+
`);let u=(A,We)=>{let ys=p?jo(A):A,Je=p?Oo(We,A):We,Ve=s(m,ys);n(s(Ve,".."),{recursive:!0}),a(Ve,Je)};this.info("Creating project structure...");let f=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/components/ui","src/lib/hooks","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","tests/unit","tests/feature","tests/e2e","src/lib/factories"]:["","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/components/ui","src/lib/hooks","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","tests/unit","tests/feature","tests/e2e","src/lib/factories"];for(let A of f)n(s(m,A),{recursive:!0});this.info("Writing config files...");let{dirname:v}=await import("path"),{fileURLToPath:x}=await import("url"),L=s(v(v(v(x(import.meta.url)))),"package.json"),D=JSON.parse((await import("fs")).readFileSync(L,"utf-8")).version??"0.4.0";u("package.json",d.packageJson(c,D)),u("svelte.config.js",d.svelteConfig()),u("vite.config.ts",d.viteConfig()),u("tsconfig.json",d.tsConfig()),u("src/app.html",d.appHtml()),u("static/favicon.svg",d.faviconSvg()),u("src/app.css",d.appCss()),u("src/app.ts",d.appTs()),u("src/hooks.server.ts",d.hooksServerTs()),u(".env.example",d.envExample());let{randomBytes:N}=await import("crypto"),R=N(32).toString("hex"),I=N(16).toString("hex"),X=d.envExample().replace("APP_KEY=change-me-to-a-random-string",`APP_KEY=${R}`).replace("INTERNAL_SECRET=change-me-to-a-random-string",`INTERNAL_SECRET=${I}`);u(".env",X),u(".gitignore",d.gitignore()),u("svelar.database.json",d.svelarDatabaseJson()),u("components.json",d.componentsJson()),u("src/lib/utils.ts",d.utilsCn());for(let A of["storage/logs","storage/cache","storage/uploads","storage/sessions"])u(`${A}/.gitkeep`,"");if(this.info("Scaffolding domain layer..."),u("src/lib/modules/auth/User.ts",d.userModel()),u("src/lib/modules/auth/UserRepository.ts",d.userRepository()),u("src/lib/modules/auth/AuthService.ts",d.authService()),u("src/lib/modules/auth/AuthController.ts",d.authController()),u("src/lib/modules/auth/RegisterUserAction.ts",d.registerUserAction()),u("src/lib/modules/auth/RegisterRequest.ts",d.registerRequest()),u("src/lib/modules/auth/LoginRequest.ts",d.loginRequest()),u("src/lib/modules/auth/ForgotPasswordRequest.ts",d.forgotPasswordRequest()),u("src/lib/modules/auth/ResetPasswordRequest.ts",d.resetPasswordRequest()),u("src/lib/modules/auth/OtpSendRequest.ts",d.otpSendRequest()),u("src/lib/modules/auth/OtpVerifyRequest.ts",d.otpVerifyRequest()),u("src/lib/modules/auth/UserResource.ts",d.userResource()),u("src/lib/modules/auth/gates.ts",d.gates()),u("src/lib/modules/auth/schemas.ts",d.authSchema()),u("src/lib/modules/auth/UserRegistered.ts",d.userRegisteredEvent()),u("src/lib/modules/auth/SendWelcomeEmailListener.ts",d.sendWelcomeEmailListener()),u("src/lib/modules/auth/WelcomeNotification.ts",d.welcomeNotification()),u("src/lib/modules/posts/Post.ts",d.postModel()),u("src/lib/modules/posts/PostRepository.ts",d.postRepository()),u("src/lib/modules/posts/PostService.ts",d.postService()),u("src/lib/modules/posts/PostController.ts",d.postController()),u("src/lib/modules/posts/CreatePostAction.ts",d.createPostAction()),u("src/lib/modules/posts/CreatePostRequest.ts",d.createPostRequest()),u("src/lib/modules/posts/UpdatePostRequest.ts",d.updatePostRequest()),u("src/lib/modules/posts/PostResource.ts",d.postResource()),u("src/lib/modules/posts/schemas.ts",d.postSchema()),u("src/lib/modules/admin/AdminService.ts",d.adminService()),u("src/lib/modules/admin/AdminController.ts",d.adminController()),u("src/lib/modules/admin/UpdateUserRoleRequest.ts",d.updateUserRoleRequest()),u("src/lib/modules/admin/DeleteUserRequest.ts",d.deleteUserRequest()),u("src/lib/modules/admin/CreateRoleRequest.ts",d.createRoleRequest()),u("src/lib/modules/admin/DeleteRoleRequest.ts",d.deleteRoleRequest()),u("src/lib/modules/admin/CreatePermissionRequest.ts",d.createPermissionRequest()),u("src/lib/modules/admin/DeletePermissionRequest.ts",d.deletePermissionRequest()),u("src/lib/modules/admin/RolePermissionRequest.ts",d.rolePermissionRequest()),u("src/lib/modules/admin/UserRoleRequest.ts",d.userRoleRequest()),u("src/lib/modules/admin/UserPermissionRequest.ts",d.userPermissionRequest()),u("src/lib/modules/admin/ExportDataRequest.ts",d.exportDataRequest()),u("src/lib/modules/admin/RoleResource.ts",d.roleResource()),u("src/lib/modules/admin/PermissionResource.ts",d.permissionResource()),u("src/lib/modules/admin/schemas.ts",d.adminSchema()),u("src/lib/shared/providers/EventServiceProvider.ts",d.eventServiceProvider()),this.info("Creating migrations..."),u("src/lib/database/migrations/00000001_create_users_table.ts",d.createUsersTable()),u("src/lib/database/migrations/00000002_create_posts_table.ts",d.createPostsTable()),u("src/lib/database/migrations/00000003_create_permissions_tables.ts",d.createPermissionsTables()),u("src/lib/database/migrations/00000004_add_role_to_users.ts",d.addRoleToUsers()),u("src/lib/database/migrations/00000005_create_sessions_table.ts",d.createSessionsTable()),u("src/lib/database/migrations/00000006_create_audit_logs_table.ts",d.createAuditLogsTable()),u("src/lib/database/migrations/00000007_create_notifications_table.ts",d.createNotificationsTable()),u("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",d.createFailedJobsTable()),u("src/lib/database/seeders/DatabaseSeeder.ts",d.databaseSeeder()),this.info("Creating auth pages..."),u("src/routes/login/+page.server.ts",d.loginPageServer()),u("src/routes/login/+page.svelte",d.loginPageSvelte()),u("src/routes/register/+page.server.ts",d.registerPageServer()),u("src/routes/register/+page.svelte",d.registerPageSvelte()),u("src/routes/logout/+page.server.ts",d.logoutPageServer()),u("src/routes/forgot-password/+page.server.ts",d.forgotPasswordPageServer()),u("src/routes/forgot-password/+page.svelte",d.forgotPasswordPageSvelte()),u("src/routes/reset-password/+page.server.ts",d.resetPasswordPageServer()),u("src/routes/reset-password/+page.svelte",d.resetPasswordPageSvelte()),u("src/routes/otp-login/+page.server.ts",d.otpLoginPageServer()),u("src/routes/otp-login/+page.svelte",d.otpLoginPageSvelte()),u("src/routes/verify-email/+page.server.ts",d.verifyEmailPageServer()),u("src/routes/verify-email/+page.svelte",d.verifyEmailPageSvelte()),this.info("Creating dashboard..."),u("src/routes/dashboard/+layout.server.ts",d.dashboardLayoutServer()),u("src/routes/dashboard/+layout.svelte",d.dashboardLayoutSvelte()),u("src/routes/dashboard/+page.server.ts",d.dashboardPageServer()),u("src/routes/dashboard/+page.svelte",d.dashboardPageSvelte()),u("src/routes/dashboard/api-keys/+page.server.ts",d.apiKeysPageServer()),u("src/routes/dashboard/api-keys/+page.svelte",d.apiKeysPageSvelte()),u("src/routes/dashboard/team/+page.server.ts",d.teamPageServer()),u("src/routes/dashboard/team/+page.svelte",d.teamPageSvelte()),this.info("Creating admin panel..."),u("src/routes/admin/+layout.server.ts",d.adminLayoutServer()),u("src/routes/admin/+layout.svelte",d.adminLayoutSvelte()),u("src/routes/admin/+page.server.ts",d.adminPageServer()),u("src/routes/admin/+page.svelte",d.adminPageSvelte()),this.info("Creating API routes..."),u("src/routes/api/health/+server.ts",d.apiHealth()),u("src/routes/api/auth/register/+server.ts",d.apiAuthRegister()),u("src/routes/api/auth/login/+server.ts",d.apiAuthLogin()),u("src/routes/api/auth/logout/+server.ts",d.apiAuthLogout()),u("src/routes/api/auth/me/+server.ts",d.apiAuthMe()),u("src/routes/api/auth/forgot-password/+server.ts",d.apiAuthForgotPassword()),u("src/routes/api/auth/reset-password/+server.ts",d.apiAuthResetPassword()),u("src/routes/api/auth/otp/send/+server.ts",d.apiAuthOtpSend()),u("src/routes/api/auth/otp/verify/+server.ts",d.apiAuthOtpVerify()),u("src/routes/api/auth/verify-email/+server.ts",d.apiAuthVerifyEmail()),u("src/routes/api/posts/+server.ts",d.apiPosts()),u("src/routes/api/posts/[id]/+server.ts",d.apiPostsSingle()),u("src/routes/api/posts/mine/+server.ts",d.apiPostsMine()),u("src/routes/api/broadcasting/[channel]/+server.ts",d.apiBroadcasting()),u("src/routes/api/internal/broadcast/+server.ts",d.apiInternalBroadcast()),u("src/routes/api/admin/users/+server.ts",d.apiAdminUsers()),u("src/routes/api/admin/roles/+server.ts",d.apiAdminRoles()),u("src/routes/api/admin/permissions/+server.ts",d.apiAdminPermissions()),u("src/routes/api/admin/role-permissions/+server.ts",d.apiAdminRolePermissions()),u("src/routes/api/admin/user-roles/+server.ts",d.apiAdminUserRoles()),u("src/routes/api/admin/user-permissions/+server.ts",d.apiAdminUserPermissions()),u("src/routes/api/admin/export/+server.ts",d.apiAdminExport()),u("src/routes/api/admin/health/+server.ts",d.apiAdminHealth()),u("src/routes/api/admin/queue/+server.ts",d.apiAdminQueue()),u("src/routes/api/admin/queue/[id]/retry/+server.ts",d.apiAdminQueueRetry()),u("src/routes/api/admin/queue/[id]/+server.ts",d.apiAdminQueueDelete()),u("src/routes/api/admin/scheduler/+server.ts",d.apiAdminScheduler()),u("src/routes/api/admin/scheduler/[name]/run/+server.ts",d.apiAdminSchedulerRun()),u("src/routes/api/admin/scheduler/[name]/toggle/+server.ts",d.apiAdminSchedulerToggle()),u("src/routes/api/admin/logs/+server.ts",d.apiAdminLogs()),u("src/routes/api/admin/stats/+server.ts",d.apiAdminStats()),this.info("Creating background jobs..."),u("src/lib/shared/jobs/SendWelcomeEmail.ts",d.sendWelcomeEmail()),u("src/lib/shared/jobs/DailyDigestJob.ts",d.dailyDigestJob()),u("src/lib/shared/jobs/ExportDataJob.ts",d.exportDataJob()),this.info("Creating scheduled tasks..."),u("src/lib/shared/scheduler/CleanupExpiredTokens.ts",d.cleanupExpiredTokens()),u("src/lib/shared/scheduler/CleanExpiredSessions.ts",d.cleanExpiredSessions()),u("src/lib/shared/scheduler/DailyDigestEmail.ts",d.dailyDigestEmail()),u("src/lib/shared/scheduler/PruneAuditLogs.ts",d.pruneAuditLogs()),u("src/lib/shared/scheduler/QueueHealthCheck.ts",d.queueHealthCheck()),this.info("Creating layouts..."),u("src/routes/+layout.svelte",d.rootLayoutSvelte(c)),u("src/routes/+layout.server.ts",d.rootLayoutServer()),u("src/routes/+error.svelte",d.errorSvelte()),u("src/routes/+page.svelte",d.homePage(c)),this.info("Setting up testing..."),u("vitest.config.ts",d.vitestConfig()),u("playwright.config.ts",d.playwrightConfig()),u("tests/unit/example.test.ts",d.exampleUnitTest()),u("tests/feature/auth.test.ts",d.exampleFeatureTest()),u("src/lib/factories/UserFactory.ts",d.scaffoldUserFactory()),this.success(`Project structure created (${h})`),!t["no-install"]){this.info("Installing dependencies...");try{o("npm install",{cwd:m,stdio:"inherit"}),this.success("Dependencies installed")}catch{this.warn("npm install failed \u2014 run it manually with: cd "+c+" && npm install")}this.info("Installing shadcn-svelte components...");try{o("npx shadcn-svelte@latest add --all --yes --no-changelog",{cwd:m,stdio:"inherit"}),this.success("shadcn-svelte components installed")}catch{this.warn("shadcn-svelte setup failed \u2014 run manually: cd "+c+" && npx shadcn-svelte@latest add --all")}this.info("Running migrations...");try{o("npx svelar migrate",{cwd:m,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:m,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!
|
|
7412
6935
|
`),this.log(` Next steps:
|
|
7413
|
-
`),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
|
|
7414
|
-
`).
|
|
6936
|
+
`),this.log(` cd ${c}`),t["no-install"]&&(this.log(" npm install"),this.log(" npx shadcn-svelte@latest add --all"),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 _o(l){return/Service\./.test(l)?"services":/Controller\./.test(l)?"controllers":/Repository\./.test(l)?"repositories":/Request\./.test(l)?"dtos":/Resource\./.test(l)?"resources":/Action\./.test(l)?"actions":/Listener\./.test(l)?"listeners":/Notification\./.test(l)?"notifications":/Registered|Created|Updated|Deleted|Verified|Invited/.test(l)?"events":"models"}function jo(l){let e=l.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/${_o(r)}/${r}`}let t=l.match(/^src\/lib\/shared\/(.+)$/);return t?`src/lib/${t[1]}`:l}function Mr(l,e,t){return e==="schemas"?`$lib/schemas/${l}${t}`:e==="gates"?`$lib/gates${t}`:`$lib/${nn(e)}/${e}${t}`}function nn(l){return/Service$/.test(l)?"services":/Controller$/.test(l)?"controllers":/Repository$/.test(l)?"repositories":/Request$/.test(l)?"dtos":/Resource$/.test(l)?"resources":/Action$/.test(l)?"actions":/Listener$/.test(l)?"listeners":/Notification$/.test(l)?"notifications":/Registered|Created|Updated|Deleted|Verified|Invited/.test(l)?"events":"models"}function Oo(l,e){let s=e.match(/modules\/(\w+)\//)?.[1]||"";return l=l.replace(/\$lib\/modules\/(\w+)\/(\w+)(\.js)?/g,(r,i,n,a)=>Mr(i,n,a||"")),l=l.replace(/\.\/lib\/modules\/(\w+)\/(\w+)(\.js)?/g,(r,i,n,a)=>n==="schemas"?`./lib/schemas/${i}${a||""}`:n==="gates"?`./lib/gates${a||""}`:`./lib/${nn(n)}/${n}${a||""}`),l=l.replace(/\$lib\/shared\//g,"$lib/"),l=l.replace(/\.\/lib\/shared\//g,"./lib/"),e.includes("shared/")&&(l=l.replace(/'\.\.\/(\.\.\/\.\.\/)'/g,"'$1'"),l=l.replace(/'\.\.\/\.\.\/\.\.\//g,"'../../")),s&&(l=l.replace(/from '\.\/(\w+)(\.js)?'/g,(r,i,n)=>i.startsWith("$")||i==="app"?r:(n=n||"",`from '${Mr(s,i,n)}'`)),l=l.replace(/import '\.\/(\w+)(\.js)?'/g,(r,i,n)=>i.startsWith("$")||i==="app"?r:(n=n||"",`import '${Mr(s,i,n)}'`))),l}import{existsSync as us,readFileSync as Ke,writeFileSync as an,mkdirSync as qo}from"fs";import{join as F,dirname as Uo}from"path";import{createInterface as Fo}from"readline";function Bo(l){let e=Fo({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(l,s=>{e.close(),t(s.trim().toLowerCase())})})}function on(l){return new Promise(e=>{let t=new Set,s=0,r=process.stdin,i=process.stdout,n="\x1B[?25l",a="\x1B[?25h";function o(){c>0&&i.write(`\x1B[${l.length+2}A`),i.write(`\x1B[2K \x1B[36mSpace\x1B[0m toggle \x1B[36mA\x1B[0m toggle all \x1B[36m\u2191\u2193\x1B[0m navigate \x1B[36mEnter\x1B[0m confirm
|
|
6937
|
+
`);for(let f=0;f<l.length;f++){let v=f===s,L=t.has(f)?"\x1B[32m\u25C9\x1B[0m":"\x1B[90m\u25CB\x1B[0m",$=v?"\x1B[36m\u276F\x1B[0m":" ",D=v?`\x1B[1m${l[f].label}\x1B[0m`:l[f].label,N=l[f].hint?` \x1B[90m${l[f].hint}\x1B[0m`:"";i.write(`\x1B[2K ${$} ${L} ${D}${N}
|
|
6938
|
+
`)}let u=t.size;i.write(`\x1B[2K \x1B[90m${u} file${u!==1?"s":""} selected\x1B[0m
|
|
6939
|
+
`),c++}let c=0;i.write(n);let m=r.isRaw;r.setRawMode(!0),r.resume(),o();function p(u){let f=u.toString();if(f==="\r"||f===`
|
|
6940
|
+
`){h(),e([...t].sort((v,x)=>v-x));return}if(f===""){h(),e([]);return}if(f==="\x1B"&&u.length===1){h(),e([]);return}if(f===" "){t.has(s)?t.delete(s):t.add(s),o();return}if(f==="a"||f==="A"){if(t.size===l.length)t.clear();else for(let v=0;v<l.length;v++)t.add(v);o();return}if(f==="\x1B[A"||f==="k"){s=s>0?s-1:l.length-1,o();return}if(f==="\x1B[B"||f==="j"){s=s<l.length-1?s+1:0,o();return}}function h(){r.removeListener("data",p),r.setRawMode(m??!1),r.pause(),i.write(a)}r.on("data",p)})}var ms=class extends g{name="update";description="Update scaffold files from the latest svelar templates without overwriting customizations";flags=[{name:"force",alias:"f",description:"Overwrite all framework files without prompting",type:"boolean",default:!1},{name:"dry-run",alias:"d",description:"Show what would be updated without writing",type:"boolean",default:!1},{name:"category",alias:"c",description:"Only update a specific category (config, migration, route, page, domain, job, seeder)",type:"string",default:""},{name:"list",alias:"l",description:"List all updatable files and their status",type:"boolean",default:!1},{name:"include-user-files",alias:"u",description:"Include user-customizable files (app.ts, hooks, layouts, home page, etc.)",type:"boolean",default:!1}];async handle(e,t){let s=process.cwd(),r=t.force??!1,i=t["dry-run"]??!1,n=t.category??"",a=t.list??!1,o=t["include-user-files"]??!1,c=us(F(s,"src","lib","modules")),m="app";try{m=JSON.parse(Ke(F(s,"package.json"),"utf-8")).name??"app"}catch{}this.log(""),this.info("Svelar Update \u2014 scanning project files..."),this.log("");let p=this.getFileManifest(c,m),h=n?p.filter(R=>R.category===n):p;if(h.length===0){this.warn(`No files found for category "${n}". Valid categories: config, migration, route, page, domain, job, seeder`);return}let u=h.filter(R=>R.ownership==="framework"),f=h.filter(R=>R.ownership==="user"),v=[],x=[],L=[];for(let R of u){let I=F(s,R.path);if(!us(I)){v.push(R);continue}let X=Ke(I,"utf-8"),A;try{A=R.content()}catch{continue}this.normalize(X)===this.normalize(A)?L.push(R):x.push(R)}let $=[],D=[],N=[];if(o)for(let R of f){let I=F(s,R.path);if(!us(I)){D.push(R);continue}let X=Ke(I,"utf-8"),A;try{A=R.content()}catch{continue}this.normalize(X)===this.normalize(A)?N.push(R):$.push(R)}if(a){this.printStatus(v,x,L,"Framework Files"),o?(this.log(""),this.printStatus(D,$,N,"User-Customizable Files")):(this.log(""),this.log(` \x1B[90m${f.length} user-customizable files not shown. Use --include-user-files to include.\x1B[0m`));return}if(this.log(` Framework files scanned: ${u.length}`),this.log(` Up to date: \x1B[32m${L.length}\x1B[0m`),this.log(` Changed/outdated: \x1B[33m${x.length}\x1B[0m`),this.log(` Missing (new): \x1B[36m${v.length}\x1B[0m`),!o&&f.length>0&&this.log(` User files (excluded): \x1B[90m${f.length}\x1B[0m \x1B[90m(use --include-user-files to include)\x1B[0m`),this.log(""),x.length===0&&v.length===0&&$.length===0&&D.length===0){this.success("All scaffold files are up to date!");return}v.length>0&&await this.handleNewFiles(v,s,r,i),x.length>0&&await this.handleChangedFiles(x,s,r,i,"Framework"),o&&(D.length>0&&await this.handleNewFiles(D,s,r,i),$.length>0&&(this.log(""),this.warn("The following are user-customizable files. Updating them may overwrite your changes."),await this.handleChangedFiles($,s,!1,i,"User"))),this.log(""),this.success("Update complete.")}async handleNewFiles(e,t,s,r){this.info(`New files available (${e.length}):`);for(let n of e)this.log(` \x1B[36m+\x1B[0m ${n.path} \x1B[90m(${n.description})\x1B[0m`);if(this.log(""),r)return;if(s){for(let n of e)this.writeFile(F(t,n.path),n.content()),this.success(`Created ${n.path}`);return}this.log(" Select files to create:"),this.log("");let i=await on(e.map(n=>({label:n.path,hint:n.description})));if(this.log(""),i.length===0)this.log(" Skipped new files.");else for(let n of i)this.writeFile(F(t,e[n].path),e[n].content()),this.success(`Created ${e[n].path}`);this.log("")}async handleChangedFiles(e,t,s,r,i){this.info(`${i} files with updates (${e.length}):`);for(let o of e)this.log(` \x1B[33m~\x1B[0m ${o.path} \x1B[90m(${o.description})\x1B[0m`);if(this.log(""),r){this.info("Dry run \u2014 no files were modified.");return}if(s){for(let o of e)this.backupAndWrite(F(t,o.path),o.content()),this.success(`Updated ${o.path}`);return}let n=await Bo(" View diffs before selecting? [y/N] ");if(n==="y"||n==="yes")for(let o of e)this.log(`
|
|
6941
|
+
\x1B[1m${o.path}\x1B[0m \x1B[90m(${o.description})\x1B[0m`),this.showDiff(F(t,o.path),o.content());this.log(" Select files to update (creates .bak backups):"),this.log("");let a=await on(e.map(o=>({label:o.path,hint:o.description})));if(this.log(""),a.length===0)this.log(" No files updated.");else for(let o of a)this.backupAndWrite(F(t,e[o].path),e[o].content()),this.success(`Updated ${e[o].path} \x1B[90m(backup: ${e[o].path}.bak)\x1B[0m`)}backupAndWrite(e,t){if(us(e)){let s=Ke(e,"utf-8");an(e+".bak",s)}this.writeFile(e,t)}normalize(e){return e.replace(/\r\n/g,`
|
|
6942
|
+
`).trim()}writeFile(e,t){qo(Uo(e),{recursive:!0}),an(e,t)}showDiff(e,t){let s=Ke(e,"utf-8").split(`
|
|
7415
6943
|
`),r=t.split(`
|
|
7416
|
-
`);this.log(""),this.log(` \x1B[90m--- ${e} (current)\x1B[0m`),this.log(` \x1B[90m+++ ${e} (updated)\x1B[0m`);let i=Math.max(s.length,r.length),a=0,n=[];for(let c=0;c<i;c++){let m=s[c]??"",p=r[c]??"";m!==p?(s[c]!==void 0&&n.push(` \x1B[31m- ${m}\x1B[0m`),r[c]!==void 0&&n.push(` \x1B[32m+ ${p}\x1B[0m`),a=0):(a<2&&n.length>0&&n.push(` \x1B[90m ${m}\x1B[0m`),a++)}let l=n.slice(0,40);for(let c of l)this.log(c);n.length>40&&this.log(` \x1B[90m... and ${n.length-40} more lines\x1B[0m`),this.log("")}printStatus(e,t,s){let r=[];for(let i of e)r.push(["\x1B[36mNEW\x1B[0m",i.path,i.category,i.description]);for(let i of t)r.push(["\x1B[33mCHANGED\x1B[0m",i.path,i.category,i.description]);for(let i of s)r.push(["\x1B[32mOK\x1B[0m",i.path,i.category,i.description]);this.table(["Status","File","Category","Description"],r)}getFileManifest(e,t){let s=[],r=(v,y,C,T)=>{s.push({path:v,content:y,category:C,description:T})};r("src/app.ts",()=>d.appTs(),"config","Application bootstrap"),r("src/hooks.server.ts",()=>d.hooksServerTs(),"config","SvelteKit hooks"),r("vite.config.ts",()=>d.viteConfig(),"config","Vite configuration"),r(".env.example",()=>d.envExample(),"config","Environment template"),r("svelar.database.json",()=>d.svelarDatabaseJson(),"config","Database config"),r("src/app.css",()=>d.appCss(),"config","Global styles"),r("src/app.html",()=>d.appHtml(),"config","HTML shell"),r("src/lib/database/migrations/00000001_create_users_table.ts",()=>d.createUsersTable(),"migration","Users table"),r("src/lib/database/migrations/00000002_create_posts_table.ts",()=>d.createPostsTable(),"migration","Posts table"),r("src/lib/database/migrations/00000003_create_permissions_tables.ts",()=>d.createPermissionsTables(),"migration","Permissions tables"),r("src/lib/database/migrations/00000004_add_role_to_users.ts",()=>d.addRoleToUsers(),"migration","Role column on users"),r("src/lib/database/migrations/00000005_create_sessions_table.ts",()=>d.createSessionsTable(),"migration","Sessions table"),r("src/lib/database/migrations/00000006_create_audit_logs_table.ts",()=>d.createAuditLogsTable(),"migration","Audit logs table"),r("src/lib/database/migrations/00000007_create_notifications_table.ts",()=>d.createNotificationsTable(),"migration","Notifications table"),r("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",()=>d.createFailedJobsTable(),"migration","Failed jobs table"),r("src/lib/database/migrations/00000009_add_stripe_to_users.ts",()=>d.addStripeToUsers(),"migration","Stripe customer ID on users"),r("src/lib/database/migrations/00000010_create_subscription_plans.ts",()=>d.createSubscriptionPlansTable(),"migration","Subscription plans table"),r("src/lib/database/migrations/00000011_create_subscriptions.ts",()=>d.createSubscriptionsTable(),"migration","Subscriptions table"),r("src/lib/database/migrations/00000012_create_invoices.ts",()=>d.createInvoicesTable(),"migration","Invoices table");let i=e?"src/lib/modules/auth":"src/lib",a=e?`${i}/User.ts`:`${i}/models/User.ts`,n=e?`${i}/UserRepository.ts`:`${i}/repositories/UserRepository.ts`,l=e?`${i}/AuthService.ts`:`${i}/services/AuthService.ts`,c=e?`${i}/AuthController.ts`:`${i}/controllers/AuthController.ts`,m=e?`${i}/RegisterUserAction.ts`:`${i}/actions/RegisterUserAction.ts`;r(a,()=>d.userModel(),"domain","User model"),r(n,()=>d.userRepository(),"domain","User repository"),r(l,()=>d.authService(),"domain","Auth service"),r(c,()=>d.authController(),"domain","Auth controller"),r(m,()=>d.registerUserAction(),"domain","Register user action");let p=e?i:`${i}/dtos`;r(`${e?i:p}/RegisterRequest.ts`,()=>d.registerRequest(),"domain","Register DTO"),r(`${e?i:p}/LoginRequest.ts`,()=>d.loginRequest(),"domain","Login DTO"),r(`${e?i:p}/ForgotPasswordRequest.ts`,()=>d.forgotPasswordRequest(),"domain","Forgot password DTO"),r(`${e?i:p}/ResetPasswordRequest.ts`,()=>d.resetPasswordRequest(),"domain","Reset password DTO"),r(`${e?i:p}/OtpSendRequest.ts`,()=>d.otpSendRequest(),"domain","OTP send DTO"),r(`${e?i:p}/OtpVerifyRequest.ts`,()=>d.otpVerifyRequest(),"domain","OTP verify DTO"),r(`${e?i:`${i}/resources`}/UserResource.ts`,()=>d.userResource(),"domain","User resource"),r(`${e?i:`${i}/schemas`}/gates.ts`,()=>d.gates(),"domain","Authorization gates"),r(`${e?i+"/schemas":`${i}/schemas`}.ts`,()=>d.authSchema(),"domain","Auth Zod schemas");let h=e?"src/lib/modules/posts":"src/lib";r(`${e?h:`${h}/models`}/Post.ts`,()=>d.postModel(),"domain","Post model"),r(`${e?h:`${h}/repositories`}/PostRepository.ts`,()=>d.postRepository(),"domain","Post repository"),r(`${e?h:`${h}/services`}/PostService.ts`,()=>d.postService(),"domain","Post service"),r(`${e?h:`${h}/controllers`}/PostController.ts`,()=>d.postController(),"domain","Post controller"),r(`${e?h:`${h}/actions`}/CreatePostAction.ts`,()=>d.createPostAction(),"domain","Create post action"),r("src/lib/database/seeders/DatabaseSeeder.ts",()=>d.databaseSeeder(),"seeder","Database seeder"),r("src/routes/login/+page.server.ts",()=>d.loginPageServer(),"page","Login server"),r("src/routes/login/+page.svelte",()=>d.loginPageSvelte(),"page","Login page"),r("src/routes/register/+page.server.ts",()=>d.registerPageServer(),"page","Register server"),r("src/routes/register/+page.svelte",()=>d.registerPageSvelte(),"page","Register page"),r("src/routes/logout/+page.server.ts",()=>d.logoutPageServer(),"page","Logout handler"),r("src/routes/forgot-password/+page.server.ts",()=>d.forgotPasswordPageServer(),"page","Forgot password server"),r("src/routes/forgot-password/+page.svelte",()=>d.forgotPasswordPageSvelte(),"page","Forgot password page"),r("src/routes/reset-password/+page.server.ts",()=>d.resetPasswordPageServer(),"page","Reset password server"),r("src/routes/reset-password/+page.svelte",()=>d.resetPasswordPageSvelte(),"page","Reset password page"),r("src/routes/otp-login/+page.server.ts",()=>d.otpLoginPageServer(),"page","OTP login server"),r("src/routes/otp-login/+page.svelte",()=>d.otpLoginPageSvelte(),"page","OTP login page"),r("src/routes/verify-email/+page.server.ts",()=>d.verifyEmailPageServer(),"page","Verify email server"),r("src/routes/verify-email/+page.svelte",()=>d.verifyEmailPageSvelte(),"page","Verify email page"),r("src/routes/dashboard/+layout.server.ts",()=>d.dashboardLayoutServer(),"page","Dashboard auth guard"),r("src/routes/dashboard/+layout.svelte",()=>d.dashboardLayoutSvelte(),"page","Dashboard layout"),r("src/routes/dashboard/+page.server.ts",()=>d.dashboardPageServer(),"page","Dashboard server"),r("src/routes/dashboard/+page.svelte",()=>d.dashboardPageSvelte(),"page","Dashboard overview"),r("src/routes/dashboard/api-keys/+page.server.ts",()=>d.apiKeysPageServer(),"page","API keys server"),r("src/routes/dashboard/api-keys/+page.svelte",()=>d.apiKeysPageSvelte(),"page","API keys page"),r("src/routes/dashboard/team/+page.server.ts",()=>d.teamPageServer(),"page","Team server"),r("src/routes/dashboard/team/+page.svelte",()=>d.teamPageSvelte(),"page","Team page"),r("src/routes/dashboard/billing/+page.server.ts",()=>d.billingPageServer(),"page","Billing server"),r("src/routes/dashboard/billing/+page.svelte",()=>d.billingPageSvelte(),"page","Billing page"),r("src/routes/admin/+layout.server.ts",()=>d.adminLayoutServer(),"page","Admin auth guard"),r("src/routes/admin/+layout.svelte",()=>d.adminLayoutSvelte(),"page","Admin layout"),r("src/routes/admin/+page.server.ts",()=>d.adminPageServer(),"page","Admin server"),r("src/routes/admin/+page.svelte",()=>d.adminPageSvelte(),"page","Admin dashboard"),r("src/routes/api/health/+server.ts",()=>d.apiHealth(),"route","Health check"),r("src/routes/api/auth/register/+server.ts",()=>d.apiAuthRegister(),"route","Auth register API"),r("src/routes/api/auth/login/+server.ts",()=>d.apiAuthLogin(),"route","Auth login API"),r("src/routes/api/auth/logout/+server.ts",()=>d.apiAuthLogout(),"route","Auth logout API"),r("src/routes/api/auth/me/+server.ts",()=>d.apiAuthMe(),"route","Auth me API"),r("src/routes/api/auth/forgot-password/+server.ts",()=>d.apiAuthForgotPassword(),"route","Forgot password API"),r("src/routes/api/auth/reset-password/+server.ts",()=>d.apiAuthResetPassword(),"route","Reset password API"),r("src/routes/api/auth/otp/send/+server.ts",()=>d.apiAuthOtpSend(),"route","OTP send API"),r("src/routes/api/auth/otp/verify/+server.ts",()=>d.apiAuthOtpVerify(),"route","OTP verify API"),r("src/routes/api/auth/verify-email/+server.ts",()=>d.apiAuthVerifyEmail(),"route","Verify email API"),r("src/routes/api/posts/+server.ts",()=>d.apiPosts(),"route","Posts list/create API"),r("src/routes/api/posts/[id]/+server.ts",()=>d.apiPostsSingle(),"route","Post CRUD API"),r("src/routes/api/posts/mine/+server.ts",()=>d.apiPostsMine(),"route","My posts API"),r("src/routes/api/broadcasting/[channel]/+server.ts",()=>d.apiBroadcasting(),"route","SSE broadcasting"),r("src/routes/api/internal/broadcast/+server.ts",()=>d.apiInternalBroadcast(),"route","Internal broadcast bridge"),r("src/routes/api/admin/users/+server.ts",()=>d.apiAdminUsers(),"route","Admin users API"),r("src/routes/api/admin/roles/+server.ts",()=>d.apiAdminRoles(),"route","Admin roles API"),r("src/routes/api/admin/permissions/+server.ts",()=>d.apiAdminPermissions(),"route","Admin permissions API"),r("src/routes/api/admin/role-permissions/+server.ts",()=>d.apiAdminRolePermissions(),"route","Role-permissions API"),r("src/routes/api/admin/user-roles/+server.ts",()=>d.apiAdminUserRoles(),"route","User-roles API"),r("src/routes/api/admin/user-permissions/+server.ts",()=>d.apiAdminUserPermissions(),"route","User-permissions API"),r("src/routes/api/admin/export/+server.ts",()=>d.apiAdminExport(),"route","Admin data export"),r("src/routes/api/admin/health/+server.ts",()=>d.apiAdminHealth(),"route","Admin health API"),r("src/routes/api/admin/queue/+server.ts",()=>d.apiAdminQueue(),"route","Admin queue API"),r("src/routes/api/admin/queue/[id]/retry/+server.ts",()=>d.apiAdminQueueRetry(),"route","Queue retry API"),r("src/routes/api/admin/queue/[id]/+server.ts",()=>d.apiAdminQueueDelete(),"route","Queue job API"),r("src/routes/api/admin/scheduler/+server.ts",()=>d.apiAdminScheduler(),"route","Admin scheduler API"),r("src/routes/api/admin/scheduler/[name]/run/+server.ts",()=>d.apiAdminSchedulerRun(),"route","Run task API"),r("src/routes/api/admin/scheduler/[name]/toggle/+server.ts",()=>d.apiAdminSchedulerToggle(),"route","Toggle task API"),r("src/routes/api/admin/logs/+server.ts",()=>d.apiAdminLogs(),"route","Admin logs API"),r("src/routes/api/admin/stats/+server.ts",()=>d.apiAdminStats(),"route","Admin stats API"),r("src/routes/api/admin/billing/subscriptions/+server.ts",()=>d.apiAdminBillingSubscriptions(),"route","Admin billing subscriptions"),r("src/routes/api/admin/billing/refund/+server.ts",()=>d.apiAdminBillingRefund(),"route","Admin billing refund"),r("src/routes/api/admin/billing/cancel/+server.ts",()=>d.apiAdminBillingCancel(),"route","Admin billing cancel"),r("src/routes/api/webhooks/stripe/+server.ts",()=>d.stripeWebhookRoute(),"route","Stripe webhook");let u=e?"src/lib/shared/jobs":"src/lib/jobs";r(`${u}/SendWelcomeEmail.ts`,()=>d.sendWelcomeEmail(),"job","Welcome email job"),r(`${u}/DailyDigestJob.ts`,()=>d.dailyDigestJob(),"job","Daily digest job"),r(`${u}/ExportDataJob.ts`,()=>d.exportDataJob(),"job","Export data job");let b=e?"src/lib/shared/scheduler":"src/lib/scheduler";return r(`${b}/CleanupExpiredTokens.ts`,()=>d.cleanupExpiredTokens(),"job","Cleanup tokens task"),r(`${b}/CleanExpiredSessions.ts`,()=>d.cleanExpiredSessions(),"job","Clean sessions task"),r(`${b}/DailyDigestEmail.ts`,()=>d.dailyDigestEmail(),"job","Daily digest task"),r(`${b}/PruneAuditLogs.ts`,()=>d.pruneAuditLogs(),"job","Prune audit logs task"),r(`${b}/QueueHealthCheck.ts`,()=>d.queueHealthCheck(),"job","Queue health check task"),r("src/routes/+layout.svelte",()=>d.rootLayoutSvelte(t),"page","Root layout"),r("src/routes/+layout.server.ts",()=>d.rootLayoutServer(),"page","Root layout server"),r("src/routes/+error.svelte",()=>d.errorSvelte(),"page","Error page"),r("src/routes/+page.svelte",()=>d.homePage(t),"page","Home page"),s}};var ps=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:a,writeFileSync:n}=await import("fs"),l=s(32).toString("hex");if(t.show){this.log(`
|
|
7417
|
-
APP_KEY=${
|
|
7418
|
-
`);return}let c=r(process.cwd(),".env");if(!i(c)){let h=r(process.cwd(),".env.example");if(i(h)){let u=
|
|
7419
|
-
`),this.success("Application key set (created .env).");return}let m=
|
|
7420
|
-
${m}`);this.success("Application key set.")}};var fs=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(()=>(gs(),
|
|
7421
|
-
`)){let e=
|
|
6944
|
+
`);this.log(" \x1B[90m--- current\x1B[0m"),this.log(" \x1B[90m+++ updated\x1B[0m");let i=Math.max(s.length,r.length),n=0,a=[];for(let c=0;c<i;c++){let m=s[c]??"",p=r[c]??"";m!==p?(s[c]!==void 0&&a.push(` \x1B[31m- ${m}\x1B[0m`),r[c]!==void 0&&a.push(` \x1B[32m+ ${p}\x1B[0m`),n=0):(n<2&&a.length>0&&a.push(` \x1B[90m ${m}\x1B[0m`),n++)}let o=a.slice(0,50);for(let c of o)this.log(c);a.length>50&&this.log(` \x1B[90m... and ${a.length-50} more lines\x1B[0m`),this.log("")}printStatus(e,t,s,r){this.info(r);let i=[];for(let n of e)i.push(["\x1B[36mNEW\x1B[0m",n.path,n.category,n.description]);for(let n of t)i.push(["\x1B[33mCHANGED\x1B[0m",n.path,n.category,n.description]);for(let n of s)i.push(["\x1B[32mOK\x1B[0m",n.path,n.category,n.description]);this.table(["Status","File","Category","Description"],i)}getFileManifest(e,t){let s=[],r=(v,x,L,$,D="framework")=>{s.push({path:v,content:x,category:L,description:$,ownership:D})};r("src/app.ts",()=>d.appTs(),"config","Application bootstrap","user"),r("src/hooks.server.ts",()=>d.hooksServerTs(),"config","SvelteKit hooks","user"),r("vite.config.ts",()=>d.viteConfig(),"config","Vite configuration","user"),r(".env.example",()=>d.envExample(),"config","Environment template"),r("svelar.database.json",()=>d.svelarDatabaseJson(),"config","Database config"),r("src/app.css",()=>d.appCss(),"config","Global styles"),r("src/app.html",()=>d.appHtml(),"config","HTML shell"),r("src/lib/database/migrations/00000001_create_users_table.ts",()=>d.createUsersTable(),"migration","Users table"),r("src/lib/database/migrations/00000002_create_posts_table.ts",()=>d.createPostsTable(),"migration","Posts table"),r("src/lib/database/migrations/00000003_create_permissions_tables.ts",()=>d.createPermissionsTables(),"migration","Permissions tables"),r("src/lib/database/migrations/00000004_add_role_to_users.ts",()=>d.addRoleToUsers(),"migration","Role column on users"),r("src/lib/database/migrations/00000005_create_sessions_table.ts",()=>d.createSessionsTable(),"migration","Sessions table"),r("src/lib/database/migrations/00000006_create_audit_logs_table.ts",()=>d.createAuditLogsTable(),"migration","Audit logs table"),r("src/lib/database/migrations/00000007_create_notifications_table.ts",()=>d.createNotificationsTable(),"migration","Notifications table"),r("src/lib/database/migrations/00000008_create_failed_jobs_table.ts",()=>d.createFailedJobsTable(),"migration","Failed jobs table");let i=e?"src/lib/modules/auth":"src/lib",n=e?`${i}/User.ts`:`${i}/models/User.ts`,a=e?`${i}/UserRepository.ts`:`${i}/repositories/UserRepository.ts`,o=e?`${i}/AuthService.ts`:`${i}/services/AuthService.ts`,c=e?`${i}/AuthController.ts`:`${i}/controllers/AuthController.ts`,m=e?`${i}/RegisterUserAction.ts`:`${i}/actions/RegisterUserAction.ts`;r(n,()=>d.userModel(),"domain","User model"),r(a,()=>d.userRepository(),"domain","User repository"),r(o,()=>d.authService(),"domain","Auth service"),r(c,()=>d.authController(),"domain","Auth controller"),r(m,()=>d.registerUserAction(),"domain","Register user action");let p=e?i:`${i}/dtos`;r(`${e?i:p}/RegisterRequest.ts`,()=>d.registerRequest(),"domain","Register DTO"),r(`${e?i:p}/LoginRequest.ts`,()=>d.loginRequest(),"domain","Login DTO"),r(`${e?i:p}/ForgotPasswordRequest.ts`,()=>d.forgotPasswordRequest(),"domain","Forgot password DTO"),r(`${e?i:p}/ResetPasswordRequest.ts`,()=>d.resetPasswordRequest(),"domain","Reset password DTO"),r(`${e?i:p}/OtpSendRequest.ts`,()=>d.otpSendRequest(),"domain","OTP send DTO"),r(`${e?i:p}/OtpVerifyRequest.ts`,()=>d.otpVerifyRequest(),"domain","OTP verify DTO"),r(`${e?i:`${i}/resources`}/UserResource.ts`,()=>d.userResource(),"domain","User resource"),r(`${e?i:`${i}/schemas`}/gates.ts`,()=>d.gates(),"domain","Authorization gates"),r(`${e?i+"/schemas":`${i}/schemas`}.ts`,()=>d.authSchema(),"domain","Auth Zod schemas");let h=e?"src/lib/modules/posts":"src/lib";r(`${e?h:`${h}/models`}/Post.ts`,()=>d.postModel(),"domain","Post model","user"),r(`${e?h:`${h}/repositories`}/PostRepository.ts`,()=>d.postRepository(),"domain","Post repository","user"),r(`${e?h:`${h}/services`}/PostService.ts`,()=>d.postService(),"domain","Post service","user"),r(`${e?h:`${h}/controllers`}/PostController.ts`,()=>d.postController(),"domain","Post controller","user"),r(`${e?h:`${h}/actions`}/CreatePostAction.ts`,()=>d.createPostAction(),"domain","Create post action","user"),r("src/lib/database/seeders/DatabaseSeeder.ts",()=>d.databaseSeeder(),"seeder","Database seeder","user"),r("src/routes/login/+page.server.ts",()=>d.loginPageServer(),"page","Login server"),r("src/routes/login/+page.svelte",()=>d.loginPageSvelte(),"page","Login page"),r("src/routes/register/+page.server.ts",()=>d.registerPageServer(),"page","Register server"),r("src/routes/register/+page.svelte",()=>d.registerPageSvelte(),"page","Register page"),r("src/routes/logout/+page.server.ts",()=>d.logoutPageServer(),"page","Logout handler"),r("src/routes/forgot-password/+page.server.ts",()=>d.forgotPasswordPageServer(),"page","Forgot password server"),r("src/routes/forgot-password/+page.svelte",()=>d.forgotPasswordPageSvelte(),"page","Forgot password page"),r("src/routes/reset-password/+page.server.ts",()=>d.resetPasswordPageServer(),"page","Reset password server"),r("src/routes/reset-password/+page.svelte",()=>d.resetPasswordPageSvelte(),"page","Reset password page"),r("src/routes/otp-login/+page.server.ts",()=>d.otpLoginPageServer(),"page","OTP login server"),r("src/routes/otp-login/+page.svelte",()=>d.otpLoginPageSvelte(),"page","OTP login page"),r("src/routes/verify-email/+page.server.ts",()=>d.verifyEmailPageServer(),"page","Verify email server"),r("src/routes/verify-email/+page.svelte",()=>d.verifyEmailPageSvelte(),"page","Verify email page"),r("src/routes/dashboard/+layout.server.ts",()=>d.dashboardLayoutServer(),"page","Dashboard auth guard"),r("src/routes/dashboard/+layout.svelte",()=>d.dashboardLayoutSvelte(),"page","Dashboard layout"),r("src/routes/dashboard/+page.server.ts",()=>d.dashboardPageServer(),"page","Dashboard server"),r("src/routes/dashboard/+page.svelte",()=>d.dashboardPageSvelte(),"page","Dashboard overview"),r("src/routes/dashboard/api-keys/+page.server.ts",()=>d.apiKeysPageServer(),"page","API keys server"),r("src/routes/dashboard/api-keys/+page.svelte",()=>d.apiKeysPageSvelte(),"page","API keys page"),r("src/routes/dashboard/team/+page.server.ts",()=>d.teamPageServer(),"page","Team server"),r("src/routes/dashboard/team/+page.svelte",()=>d.teamPageSvelte(),"page","Team page"),r("src/routes/admin/+layout.server.ts",()=>d.adminLayoutServer(),"page","Admin auth guard"),r("src/routes/admin/+layout.svelte",()=>d.adminLayoutSvelte(),"page","Admin layout"),r("src/routes/admin/+page.server.ts",()=>d.adminPageServer(),"page","Admin server"),r("src/routes/admin/+page.svelte",()=>d.adminPageSvelte(),"page","Admin dashboard"),r("src/routes/api/health/+server.ts",()=>d.apiHealth(),"route","Health check"),r("src/routes/api/auth/register/+server.ts",()=>d.apiAuthRegister(),"route","Auth register API"),r("src/routes/api/auth/login/+server.ts",()=>d.apiAuthLogin(),"route","Auth login API"),r("src/routes/api/auth/logout/+server.ts",()=>d.apiAuthLogout(),"route","Auth logout API"),r("src/routes/api/auth/me/+server.ts",()=>d.apiAuthMe(),"route","Auth me API"),r("src/routes/api/auth/forgot-password/+server.ts",()=>d.apiAuthForgotPassword(),"route","Forgot password API"),r("src/routes/api/auth/reset-password/+server.ts",()=>d.apiAuthResetPassword(),"route","Reset password API"),r("src/routes/api/auth/otp/send/+server.ts",()=>d.apiAuthOtpSend(),"route","OTP send API"),r("src/routes/api/auth/otp/verify/+server.ts",()=>d.apiAuthOtpVerify(),"route","OTP verify API"),r("src/routes/api/auth/verify-email/+server.ts",()=>d.apiAuthVerifyEmail(),"route","Verify email API"),r("src/routes/api/posts/+server.ts",()=>d.apiPosts(),"route","Posts list/create API"),r("src/routes/api/posts/[id]/+server.ts",()=>d.apiPostsSingle(),"route","Post CRUD API"),r("src/routes/api/posts/mine/+server.ts",()=>d.apiPostsMine(),"route","My posts API"),r("src/routes/api/broadcasting/[channel]/+server.ts",()=>d.apiBroadcasting(),"route","SSE broadcasting"),r("src/routes/api/internal/broadcast/+server.ts",()=>d.apiInternalBroadcast(),"route","Internal broadcast bridge"),r("src/routes/api/admin/users/+server.ts",()=>d.apiAdminUsers(),"route","Admin users API"),r("src/routes/api/admin/roles/+server.ts",()=>d.apiAdminRoles(),"route","Admin roles API"),r("src/routes/api/admin/permissions/+server.ts",()=>d.apiAdminPermissions(),"route","Admin permissions API"),r("src/routes/api/admin/role-permissions/+server.ts",()=>d.apiAdminRolePermissions(),"route","Role-permissions API"),r("src/routes/api/admin/user-roles/+server.ts",()=>d.apiAdminUserRoles(),"route","User-roles API"),r("src/routes/api/admin/user-permissions/+server.ts",()=>d.apiAdminUserPermissions(),"route","User-permissions API"),r("src/routes/api/admin/export/+server.ts",()=>d.apiAdminExport(),"route","Admin data export"),r("src/routes/api/admin/health/+server.ts",()=>d.apiAdminHealth(),"route","Admin health API"),r("src/routes/api/admin/queue/+server.ts",()=>d.apiAdminQueue(),"route","Admin queue API"),r("src/routes/api/admin/queue/[id]/retry/+server.ts",()=>d.apiAdminQueueRetry(),"route","Queue retry API"),r("src/routes/api/admin/queue/[id]/+server.ts",()=>d.apiAdminQueueDelete(),"route","Queue job API"),r("src/routes/api/admin/scheduler/+server.ts",()=>d.apiAdminScheduler(),"route","Admin scheduler API"),r("src/routes/api/admin/scheduler/[name]/run/+server.ts",()=>d.apiAdminSchedulerRun(),"route","Run task API"),r("src/routes/api/admin/scheduler/[name]/toggle/+server.ts",()=>d.apiAdminSchedulerToggle(),"route","Toggle task API"),r("src/routes/api/admin/logs/+server.ts",()=>d.apiAdminLogs(),"route","Admin logs API"),r("src/routes/api/admin/stats/+server.ts",()=>d.apiAdminStats(),"route","Admin stats API");let u=e?"src/lib/shared/jobs":"src/lib/jobs";r(`${u}/SendWelcomeEmail.ts`,()=>d.sendWelcomeEmail(),"job","Welcome email job","user"),r(`${u}/DailyDigestJob.ts`,()=>d.dailyDigestJob(),"job","Daily digest job","user"),r(`${u}/ExportDataJob.ts`,()=>d.exportDataJob(),"job","Export data job","user");let f=e?"src/lib/shared/scheduler":"src/lib/scheduler";return r(`${f}/CleanupExpiredTokens.ts`,()=>d.cleanupExpiredTokens(),"job","Cleanup tokens task","user"),r(`${f}/CleanExpiredSessions.ts`,()=>d.cleanExpiredSessions(),"job","Clean sessions task","user"),r(`${f}/DailyDigestEmail.ts`,()=>d.dailyDigestEmail(),"job","Daily digest task","user"),r(`${f}/PruneAuditLogs.ts`,()=>d.pruneAuditLogs(),"job","Prune audit logs task","user"),r(`${f}/QueueHealthCheck.ts`,()=>d.queueHealthCheck(),"job","Queue health check task","user"),r("src/routes/+layout.svelte",()=>d.rootLayoutSvelte(t),"page","Root layout","user"),r("src/routes/+layout.server.ts",()=>d.rootLayoutServer(),"page","Root layout server","user"),r("src/routes/+error.svelte",()=>d.errorSvelte(),"page","Error page","user"),r("src/routes/+page.svelte",()=>d.homePage(t),"page","Home page","user"),s}};var ps=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"),o=s(32).toString("hex");if(t.show){this.log(`
|
|
6945
|
+
APP_KEY=${o}
|
|
6946
|
+
`);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=${o}`),a(c,u),this.success("Application key set (created .env from .env.example).")}else a(c,`APP_KEY=${o}
|
|
6947
|
+
`),this.success("Application key set (created .env).");return}let m=n(c,"utf-8"),p=m.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=m.replace(/^APP_KEY=.*$/m,`APP_KEY=${o}`);a(c,h)}else a(c,`APP_KEY=${o}
|
|
6948
|
+
${m}`);this.success("Application key set.")}};var fs=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(()=>(gs(),Ir)),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(o=>[o.name,o.version,o.description||"-",o.enabled?"\u2713 Enabled":" Disabled",o.hasConfig?"\u2713":"-",o.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 bs=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(()=>(gs(),Ir)),{PluginPublisher:i}=await Promise.resolve().then(()=>(Or(),ln)),n=r,a=i;await n.discover();let o=n.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 m=new c,p={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let h=await a.publish(m,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 vs=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(()=>(dn(),cn)),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 un=Ur(process.cwd(),".env");if(Wo(un))for(let l of hn(un,"utf-8").split(`
|
|
6949
|
+
`)){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 Jo=mn(pn(import.meta.url));Ko(zo(Ur(Jo,"ts-resolve-hook.mjs")).href,import.meta.url);var Vo=mn(pn(import.meta.url)),Qo=Ur(Vo,"..","..","package.json"),Go=JSON.parse(hn(Qo,"utf-8")),y=new Ge(Go.version);y.register(ds);y.register(ms);y.register(ps);y.register(Ze);y.register(Xe);y.register(et);y.register(tt);y.register(st);y.register(rt);y.register(it);y.register(nt);y.register(at);y.register(ot);y.register(vt);y.register(yt);y.register(lt);y.register(ct);y.register(dt);y.register(ut);y.register(mt);y.register(pt);y.register(ht);y.register(gt);y.register(ft);y.register(bt);y.register(wt);y.register(Ct);y.register(xt);y.register(Pt);y.register(St);y.register(Rt);y.register(Tt);y.register($t);y.register(Lt);y.register(Mt);y.register(Nt);y.register(It);y.register(cs);y.register(fs);y.register(bs);y.register(vs);async function Yo(){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 i=t(r).filter(n=>(n.endsWith(".ts")||n.endsWith(".js"))&&!n.startsWith("."));for(let n of i)try{let a=l(r,n),c=await import(s(a).href),m=c.default??Object.values(c).find(p=>typeof p=="function"&&p.prototype&&"handle"in p.prototype);m&&typeof m=="function"&&y.add(new m)}catch{}}Yo().then(()=>y.run());
|