@beeblock/svelar 0.4.0

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.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/actions/index.d.ts +101 -0
  4. package/dist/actions/index.js +1 -0
  5. package/dist/api-keys/index.d.ts +58 -0
  6. package/dist/api-keys/index.js +1 -0
  7. package/dist/audit/index.d.ts +52 -0
  8. package/dist/audit/index.js +1 -0
  9. package/dist/auth/Auth.d.ts +283 -0
  10. package/dist/auth/Gate.d.ts +166 -0
  11. package/dist/auth/index.d.ts +2 -0
  12. package/dist/auth/index.js +80 -0
  13. package/dist/broadcasting/client.d.ts +195 -0
  14. package/dist/broadcasting/client.js +1 -0
  15. package/dist/broadcasting/index.d.ts +318 -0
  16. package/dist/broadcasting/index.js +20 -0
  17. package/dist/cache/index.d.ts +77 -0
  18. package/dist/cache/index.js +1 -0
  19. package/dist/cli/Cli.d.ts +23 -0
  20. package/dist/cli/Command.d.ts +36 -0
  21. package/dist/cli/bin.d.ts +8 -0
  22. package/dist/cli/bin.js +5856 -0
  23. package/dist/cli/commands/KeyGenerateCommand.d.ts +16 -0
  24. package/dist/cli/commands/MakeActionCommand.d.ts +15 -0
  25. package/dist/cli/commands/MakeBroadcastingCommand.d.ts +29 -0
  26. package/dist/cli/commands/MakeChannelCommand.d.ts +18 -0
  27. package/dist/cli/commands/MakeCommandCommand.d.ts +16 -0
  28. package/dist/cli/commands/MakeConfigCommand.d.ts +13 -0
  29. package/dist/cli/commands/MakeControllerCommand.d.ts +28 -0
  30. package/dist/cli/commands/MakeDashboardCommand.d.ts +34 -0
  31. package/dist/cli/commands/MakeDockerCommand.d.ts +32 -0
  32. package/dist/cli/commands/MakeEventCommand.d.ts +11 -0
  33. package/dist/cli/commands/MakeJobCommand.d.ts +11 -0
  34. package/dist/cli/commands/MakeListenerCommand.d.ts +16 -0
  35. package/dist/cli/commands/MakeMiddlewareCommand.d.ts +11 -0
  36. package/dist/cli/commands/MakeMigrationCommand.d.ts +17 -0
  37. package/dist/cli/commands/MakeModelCommand.d.ts +25 -0
  38. package/dist/cli/commands/MakeObserverCommand.d.ts +23 -0
  39. package/dist/cli/commands/MakePluginCommand.d.ts +11 -0
  40. package/dist/cli/commands/MakeProviderCommand.d.ts +11 -0
  41. package/dist/cli/commands/MakeRepositoryCommand.d.ts +22 -0
  42. package/dist/cli/commands/MakeRequestCommand.d.ts +15 -0
  43. package/dist/cli/commands/MakeResourceCommand.d.ts +30 -0
  44. package/dist/cli/commands/MakeRouteCommand.d.ts +42 -0
  45. package/dist/cli/commands/MakeSchemaCommand.d.ts +20 -0
  46. package/dist/cli/commands/MakeSeederCommand.d.ts +11 -0
  47. package/dist/cli/commands/MakeServiceCommand.d.ts +28 -0
  48. package/dist/cli/commands/MakeTaskCommand.d.ts +12 -0
  49. package/dist/cli/commands/MigrateCommand.d.ts +26 -0
  50. package/dist/cli/commands/NewCommand.d.ts +21 -0
  51. package/dist/cli/commands/NewCommandTemplates.d.ts +123 -0
  52. package/dist/cli/commands/PluginInstallCommand.d.ts +16 -0
  53. package/dist/cli/commands/PluginListCommand.d.ts +11 -0
  54. package/dist/cli/commands/PluginPublishCommand.d.ts +22 -0
  55. package/dist/cli/commands/QueueFailedCommand.d.ts +9 -0
  56. package/dist/cli/commands/QueueFlushCommand.d.ts +9 -0
  57. package/dist/cli/commands/QueueRetryCommand.d.ts +16 -0
  58. package/dist/cli/commands/QueueWorkCommand.d.ts +25 -0
  59. package/dist/cli/commands/RoutesListCommand.d.ts +30 -0
  60. package/dist/cli/commands/ScheduleRunCommand.d.ts +15 -0
  61. package/dist/cli/commands/SeedCommand.d.ts +14 -0
  62. package/dist/cli/commands/TinkerCommand.d.ts +10 -0
  63. package/dist/cli/index.d.ts +36 -0
  64. package/dist/cli/index.js +1973 -0
  65. package/dist/cli/ts-resolve-hook.mjs +74 -0
  66. package/dist/cli/ts-resolver.mjs +8 -0
  67. package/dist/config/Config.d.ts +65 -0
  68. package/dist/config/index.d.ts +1 -0
  69. package/dist/config/index.js +1 -0
  70. package/dist/container/Application.d.ts +33 -0
  71. package/dist/container/Container.d.ts +70 -0
  72. package/dist/container/ServiceProvider.d.ts +21 -0
  73. package/dist/container/index.d.ts +3 -0
  74. package/dist/container/index.js +1 -0
  75. package/dist/dashboard/index.d.ts +123 -0
  76. package/dist/dashboard/index.js +5 -0
  77. package/dist/database/Connection.d.ts +80 -0
  78. package/dist/database/Migration.d.ts +76 -0
  79. package/dist/database/SchemaBuilder.d.ts +91 -0
  80. package/dist/database/Seeder.d.ts +9 -0
  81. package/dist/database/index.d.ts +4 -0
  82. package/dist/database/index.js +4 -0
  83. package/dist/email-templates/index.d.ts +51 -0
  84. package/dist/email-templates/index.js +57 -0
  85. package/dist/errors/Handler.d.ts +100 -0
  86. package/dist/errors/index.d.ts +1 -0
  87. package/dist/errors/index.js +5 -0
  88. package/dist/events/EventServiceProvider.d.ts +82 -0
  89. package/dist/events/Listener.d.ts +28 -0
  90. package/dist/events/index.d.ts +80 -0
  91. package/dist/events/index.js +1 -0
  92. package/dist/excel/index.d.ts +154 -0
  93. package/dist/excel/index.js +1 -0
  94. package/dist/feature-flags/index.d.ts +158 -0
  95. package/dist/feature-flags/index.js +59 -0
  96. package/dist/forms/index.d.ts +81 -0
  97. package/dist/forms/index.js +1 -0
  98. package/dist/hashing/Hash.d.ts +51 -0
  99. package/dist/hashing/index.d.ts +1 -0
  100. package/dist/hashing/index.js +1 -0
  101. package/dist/hooks/index.d.ts +135 -0
  102. package/dist/hooks/index.js +5 -0
  103. package/dist/http/index.d.ts +201 -0
  104. package/dist/http/index.js +2 -0
  105. package/dist/i18n/index.d.ts +81 -0
  106. package/dist/i18n/index.js +1 -0
  107. package/dist/index.d.ts +54 -0
  108. package/dist/index.js +127 -0
  109. package/dist/logging/LogViewer.d.ts +95 -0
  110. package/dist/logging/LogViewer.js +1 -0
  111. package/dist/logging/index.d.ts +83 -0
  112. package/dist/logging/index.js +3 -0
  113. package/dist/mail/index.d.ts +149 -0
  114. package/dist/mail/index.js +1 -0
  115. package/dist/middleware/Middleware.d.ts +208 -0
  116. package/dist/middleware/index.d.ts +1 -0
  117. package/dist/middleware/index.js +1 -0
  118. package/dist/notifications/index.d.ts +85 -0
  119. package/dist/notifications/index.js +2 -0
  120. package/dist/orm/Model.d.ts +123 -0
  121. package/dist/orm/Observer.d.ts +34 -0
  122. package/dist/orm/QueryBuilder.d.ts +119 -0
  123. package/dist/orm/Relationship.d.ts +58 -0
  124. package/dist/orm/index.d.ts +4 -0
  125. package/dist/orm/index.js +1 -0
  126. package/dist/pagination/index.d.ts +8 -0
  127. package/dist/pagination/index.js +0 -0
  128. package/dist/pdf/GeneratePdfJob.d.ts +99 -0
  129. package/dist/pdf/GeneratePdfJob.js +41 -0
  130. package/dist/pdf/index.d.ts +328 -0
  131. package/dist/pdf/index.js +41 -0
  132. package/dist/permissions/index.d.ts +161 -0
  133. package/dist/permissions/index.js +60 -0
  134. package/dist/plugins/BootstrapPlugins.d.ts +11 -0
  135. package/dist/plugins/PluginInstaller.d.ts +30 -0
  136. package/dist/plugins/PluginInstaller.js +1 -0
  137. package/dist/plugins/PluginPublisher.d.ts +32 -0
  138. package/dist/plugins/PluginPublisher.js +1 -0
  139. package/dist/plugins/PluginRegistry.d.ts +55 -0
  140. package/dist/plugins/PluginRegistry.js +1 -0
  141. package/dist/plugins/index.d.ts +206 -0
  142. package/dist/plugins/index.js +1 -0
  143. package/dist/queue/JobMonitor.d.ts +109 -0
  144. package/dist/queue/JobMonitor.js +5 -0
  145. package/dist/queue/index.d.ts +279 -0
  146. package/dist/queue/index.js +5 -0
  147. package/dist/repositories/index.d.ts +147 -0
  148. package/dist/repositories/index.js +1 -0
  149. package/dist/routing/Controller.d.ts +115 -0
  150. package/dist/routing/FormRequest.d.ts +94 -0
  151. package/dist/routing/Resource.d.ts +213 -0
  152. package/dist/routing/Response.d.ts +138 -0
  153. package/dist/routing/index.d.ts +4 -0
  154. package/dist/routing/index.js +5 -0
  155. package/dist/scheduler/ScheduleMonitor.d.ts +141 -0
  156. package/dist/scheduler/ScheduleMonitor.js +1 -0
  157. package/dist/scheduler/SchedulerLock.d.ts +33 -0
  158. package/dist/scheduler/index.d.ts +208 -0
  159. package/dist/scheduler/index.js +34 -0
  160. package/dist/services/index.d.ts +79 -0
  161. package/dist/services/index.js +1 -0
  162. package/dist/session/Session.d.ts +166 -0
  163. package/dist/session/index.d.ts +1 -0
  164. package/dist/session/index.js +16 -0
  165. package/dist/storage/index.d.ts +154 -0
  166. package/dist/storage/index.js +1 -0
  167. package/dist/support/Pipeline.d.ts +65 -0
  168. package/dist/support/date.d.ts +136 -0
  169. package/dist/support/date.js +1 -0
  170. package/dist/support/index.d.ts +8 -0
  171. package/dist/support/index.js +1 -0
  172. package/dist/support/singleton.d.ts +10 -0
  173. package/dist/support/uuid.d.ts +40 -0
  174. package/dist/teams/index.d.ts +91 -0
  175. package/dist/teams/index.js +78 -0
  176. package/dist/uploads/index.d.ts +63 -0
  177. package/dist/uploads/index.js +2 -0
  178. package/dist/validation/index.d.ts +46 -0
  179. package/dist/validation/index.js +1 -0
  180. package/dist/webhooks/index.d.ts +66 -0
  181. package/dist/webhooks/index.js +1 -0
  182. package/package.json +338 -0
  183. package/src/i18n/LanguageSwitcher.svelte +47 -0
  184. package/src/i18n/index.ts +113 -0
  185. package/src/ui/Alert.svelte +22 -0
  186. package/src/ui/Avatar.svelte +18 -0
  187. package/src/ui/AvatarFallback.svelte +18 -0
  188. package/src/ui/AvatarImage.svelte +12 -0
  189. package/src/ui/Badge.svelte +27 -0
  190. package/src/ui/Button.svelte +51 -0
  191. package/src/ui/Card.svelte +15 -0
  192. package/src/ui/CardContent.svelte +15 -0
  193. package/src/ui/CardDescription.svelte +15 -0
  194. package/src/ui/CardFooter.svelte +15 -0
  195. package/src/ui/CardHeader.svelte +15 -0
  196. package/src/ui/CardTitle.svelte +15 -0
  197. package/src/ui/Icon.svelte +81 -0
  198. package/src/ui/Input.svelte +40 -0
  199. package/src/ui/Label.svelte +20 -0
  200. package/src/ui/Separator.svelte +10 -0
  201. package/src/ui/Tabs.svelte +23 -0
  202. package/src/ui/TabsContent.svelte +27 -0
  203. package/src/ui/TabsList.svelte +19 -0
  204. package/src/ui/TabsTrigger.svelte +28 -0
  205. package/src/ui/Toaster.svelte +279 -0
  206. package/src/ui/index.ts +31 -0
  207. package/src/ui/toast.ts +212 -0
@@ -0,0 +1,1973 @@
1
+ var ai=Object.defineProperty;var Me=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var f=(c,e)=>()=>(c&&(e=c(c=0)),e);var C=(c,e)=>{for(var t in e)ai(c,t,{get:e[t],enumerable:!0})};function w(c,e){let t=Symbol.for(c),s=globalThis;return s[t]||(s[t]=e()),s[t]}var E=f(()=>{"use strict"});var v={};C(v,{Connection:()=>m});var yt,m,b=f(()=>{"use strict";E();yt=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),o=t.map(u=>typeof u=="boolean"?u?1:0:u instanceof Date?u.toISOString():u),a=n.prepare(e),l=e.trimStart().toUpperCase();return l.startsWith("SELECT")||l.startsWith("PRAGMA")||l.startsWith("WITH")?a.all(...o):a.run(...o)}case"postgres":return(await this.rawClient(s))(e,...t);case"mysql":{let n=await this.rawClient(s),[o]=await n.execute(e,t);return o}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(a){let l=i.prepare(a);return{all(...u){return l.all(...u)},run(...u){return l.run(...u)},get(...u){return l.get(...u)}}},exec(a){i.exec(a)},pragma(a){return i.prepare(`PRAGMA ${a}`).all()},close(){i.close()}},o;try{let{drizzle:a}=await import("drizzle-orm/better-sqlite3");o=a(n)}catch{o=n}return{drizzle:o,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{}}},m=w("svelar.connection",()=>new yt)});var O,Qt,B,_,Jr,Gt=f(()=>{"use strict";b();E();O=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 Qt(this.column)}build(){return this.column}},Qt=class{constructor(e){this.column=e}onDelete(e){return this.column.references.onDelete=e,this}onUpdate(e){return this.column.references.onUpdate=e,this}},B=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 O(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 O(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 O(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 O(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} (
2
+ ${r.join(`,
3
+ `)}
4
+ )`);for(let i of this.indices){let n=i.name??`idx_${e}_${i.columns.join("_")}`,o=i.unique?"UNIQUE ":"";s.push(`CREATE ${o}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}},_=class{constructor(e){this.connectionName=e}async createTable(e,t){let s=new B;t(s);let r=m.getDriver(this.connectionName),i=s.toSQL(e,r);for(let n of i)await m.raw(n,[],this.connectionName)}async dropTable(e){await m.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async dropTableIfExists(e){await m.raw(`DROP TABLE IF EXISTS ${e}`,[],this.connectionName)}async renameTable(e,t){m.getDriver(this.connectionName)==="mysql"?await m.raw(`RENAME TABLE ${e} TO ${t}`,[],this.connectionName):await m.raw(`ALTER TABLE ${e} RENAME TO ${t}`,[],this.connectionName)}async hasTable(e){let t=m.getDriver(this.connectionName),s;switch(t){case"sqlite":s=await m.raw("SELECT name FROM sqlite_master WHERE type='table' AND name=?",[e],this.connectionName);break;case"postgres":s=await m.raw("SELECT tablename FROM pg_tables WHERE tablename = $1",[e],this.connectionName);break;case"mysql":s=await m.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 B;t(s);let r=m.getDriver(this.connectionName),i=s.columns;for(let n of i){let o=s.columnToSQL(n,r);await m.raw(`ALTER TABLE ${e} ADD COLUMN ${o}`,[],this.connectionName)}}async dropColumn(e,t){await m.raw(`ALTER TABLE ${e} DROP COLUMN ${t}`,[],this.connectionName)}},Jr=w("svelar.schema",()=>new _)});var zr={};C(zr,{Migration:()=>me,Migrator:()=>ge});var me,ge,Yt=f(()=>{"use strict";b();Gt();me=class{schema=new _},ge=class{migrationsTable="svelar_migrations";connectionName;constructor(e){this.connectionName=e}async ensureMigrationsTable(){let e=new _(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 m.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 m.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,o=e.find(a=>a.name===n);o&&(await o.migration.down(),await m.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=m.getDriver(this.connectionName),t=[];switch(e){case"sqlite":{t=(await m.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",[],this.connectionName)).map(r=>r.name),await m.raw("PRAGMA foreign_keys = OFF",[],this.connectionName);for(let r of t)await m.raw(`DROP TABLE IF EXISTS "${r}"`,[],this.connectionName);await m.raw("PRAGMA foreign_keys = ON",[],this.connectionName);break}case"mysql":{t=(await m.raw("SHOW TABLES",[],this.connectionName)).map(r=>Object.values(r)[0]),await m.raw("SET FOREIGN_KEY_CHECKS = 0",[],this.connectionName);for(let r of t)await m.raw(`DROP TABLE IF EXISTS \`${r}\``,[],this.connectionName);await m.raw("SET FOREIGN_KEY_CHECKS = 1",[],this.connectionName);break}case"postgres":{t=(await m.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'",[],this.connectionName)).map(r=>r.tablename);for(let r of t)await m.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 m.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 m.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 m.raw(`SELECT MAX(batch) as max_batch FROM ${this.migrationsTable}`,[],this.connectionName))[0]?.max_batch??0}catch{return 0}}}});var Oe={};C(Oe,{SchedulerLock:()=>ye});import{hostname as Ao}from"os";async function fe(){let{Connection:c}=await Promise.resolve().then(()=>(b(),v));return c}async function No(){return(await fe()).getDriver()}var Gr,q,ye,we=f(()=>{"use strict";Gr=!1,q=`${Ao()}:${process.pid}:${Math.random().toString(36).slice(2,10)}`;ye=class{static getOwnerId(){return q}static async ensureTable(){if(Gr)return;let e=await fe();switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
5
+ task_key TEXT PRIMARY KEY,
6
+ owner TEXT NOT NULL,
7
+ expires_at TEXT NOT NULL
8
+ )`);break;case"postgres":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
9
+ task_key VARCHAR(255) PRIMARY KEY,
10
+ owner VARCHAR(255) NOT NULL,
11
+ expires_at TIMESTAMPTZ NOT NULL
12
+ )`);break;case"mysql":await e.raw(`CREATE TABLE IF NOT EXISTS scheduler_locks (
13
+ task_key VARCHAR(255) PRIMARY KEY,
14
+ owner VARCHAR(255) NOT NULL,
15
+ expires_at DATETIME NOT NULL
16
+ ) ENGINE=InnoDB`);break}Gr=!0}static async acquire(e,t=5){await this.ensureTable();let s=await fe(),r=await No(),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,q,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,q,n]);break;case"mysql":await s.raw("INSERT IGNORE INTO scheduler_locks (task_key, owner, expires_at) VALUES (?, ?, ?)",[e,q,n]);break}});let o=await s.raw("SELECT owner FROM scheduler_locks WHERE task_key = ?",[e]);return o.length>0&&o[0].owner===q}catch{return!1}}static async release(e){try{await(await fe()).raw("DELETE FROM scheduler_locks WHERE task_key = ? AND owner = ?",[e,q])}catch{}}static async releaseAll(){try{await(await fe()).raw("DELETE FROM scheduler_locks WHERE owner = ?",[q])}catch{}}}});var Xr={};C(Xr,{ScheduledTask:()=>_e,Scheduler:()=>ss,SchedulerLock:()=>ye,cronMatches:()=>ts,parseCron:()=>Yr,task:()=>Do});function be(c,e,t){if(c==="*")return null;let s=new Set;for(let r of c.split(",")){let[i,n]=r.split("/"),o=n?parseInt(n,10):1;if(i==="*")for(let a=e;a<=t;a+=o)s.add(a);else if(i.includes("-")){let[a,l]=i.split("-"),u=parseInt(a,10),d=parseInt(l,10);for(let h=u;h<=d;h+=o)s.add(h)}else s.add(parseInt(i,10))}return[...s].sort((r,i)=>r-i)}function Yr(c){let e=c.trim().split(/\s+/);if(e.length!==5)throw new Error(`Invalid cron expression: "${c}". Expected 5 fields.`);return{minute:be(e[0],0,59),hour:be(e[1],0,23),dayOfMonth:be(e[2],1,31),month:be(e[3],1,12),dayOfWeek:be(e[4],0,6)}}function ts(c,e){let t=Yr(c),s=e.getMinutes(),r=e.getHours(),i=e.getDate(),n=e.getMonth()+1,o=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(o))}function Do(c,e,t){class s extends _e{name=c;schedule(){return t&&t(this),this}async handle(){return e()}}return new s}var _e,ss,Zr=f(()=>{"use strict";we();_e=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(()=>(we(),Oe));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(()=>(we(),Oe));await s.release(this.name)}catch{}}}},ss=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(ts(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(()=>(we(),Oe));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=>ts(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(()=>(b(),v));switch(e.getDriver()){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
17
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
18
+ task TEXT NOT NULL,
19
+ success INTEGER NOT NULL,
20
+ duration INTEGER NOT NULL,
21
+ error TEXT,
22
+ ran_at TEXT NOT NULL
23
+ )`);break;case"postgres":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
24
+ id SERIAL PRIMARY KEY,
25
+ task VARCHAR(255) NOT NULL,
26
+ success BOOLEAN NOT NULL,
27
+ duration INTEGER NOT NULL,
28
+ error TEXT,
29
+ ran_at TIMESTAMPTZ NOT NULL
30
+ )`);break;case"mysql":await e.raw(`CREATE TABLE IF NOT EXISTS scheduled_task_runs (
31
+ id INT AUTO_INCREMENT PRIMARY KEY,
32
+ task VARCHAR(255) NOT NULL,
33
+ success TINYINT NOT NULL,
34
+ duration INT NOT NULL,
35
+ error TEXT,
36
+ ran_at DATETIME NOT NULL
37
+ ) ENGINE=InnoDB`);break}this._historyTableEnsured=!0}async persistResult(e){try{await this.ensureHistoryTable();let{Connection:t}=await Promise.resolve().then(()=>(b(),v));await t.raw("INSERT INTO scheduled_task_runs (task, success, duration, error, ran_at) VALUES (?, ?, ?, ?, ?)",[e.task,e.success,e.duration,e.error||null,e.timestamp.toISOString()])}catch{}}}});var tn={};C(tn,{Job:()=>K,Queue:()=>ls});var K,Le,ns,W,Ie,is,os,as,cs,ls,us=f(()=>{"use strict";E();K=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)}},Le=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(){}},ns=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()}},W=class{constructor(e,t){this.table=e;this.registry=t}async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(b(),v));return e}async push(e){await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, payload, attempts, max_attempts, available_at, created_at)
38
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,[e.id,e.queue,JSON.stringify({jobClass:e.jobClass,payload:e.payload}),e.attempts,e.maxAttempts,Math.floor(e.availableAt/1e3),Math.floor(e.createdAt/1e3)])}async pop(e="default"){let t=await this.getConnection(),s=Math.floor(Date.now()/1e3),r=await t.raw(`SELECT * FROM ${this.table}
39
+ WHERE queue = ? AND available_at <= ? AND reserved_at IS NULL
40
+ ORDER BY created_at ASC LIMIT 1`,[e,s]);if(!r||r.length===0)return null;let 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),o=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:o}}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])}},Ie=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(),o=this.config.prefix??"svelar",a=new i.Worker(e,async l=>{let u=l.data,d=t.resolve(u.jobClass,u.payload);d.attempts=l.attemptsMade+1,await d.handle()},{connection:n,prefix:o,concurrency:r?.concurrency??1});return a.on("failed",async(l,u)=>{let d=l?.data;if(d)try{let h=t.resolve(d.jobClass,d.payload);l.attemptsMade>=(l.opts?.attempts??3)&&(h.failed(u),await s.store({id:l.id,jobClass:d.jobClass,payload:d.payload,queue:e,attempts:l.attemptsMade,maxAttempts:l.opts?.attempts??3,availableAt:Date.now(),createdAt:l.timestamp??Date.now(),job:h},u))}catch{console.error("[Queue] Failed to resolve job for failure handler:",u.message)}}),a}},is=class{table="svelar_failed_jobs";async getConnection(){let{Connection:e}=await Promise.resolve().then(()=>(b(),v));return e}async store(e,t){try{await(await this.getConnection()).raw(`INSERT INTO ${this.table} (id, queue, job_class, payload, exception, failed_at)
41
+ VALUES (?, ?, ?, ?, ?, ?)`,[crypto.randomUUID(),e.queue,e.jobClass,e.payload,t.stack??t.message,Math.floor(Date.now()/1e3)])}catch{console.error("[Queue] Could not persist failed job (run migration to create svelar_failed_jobs table)")}}async all(){return(await(await this.getConnection()).raw(`SELECT * FROM ${this.table} ORDER BY failed_at DESC`,[])??[]).map(s=>({id:s.id,queue:s.queue,jobClass:s.job_class,payload:s.payload,exception:s.exception,failedAt:s.failed_at}))}async find(e){let s=await(await this.getConnection()).raw(`SELECT * FROM ${this.table} WHERE id = ? LIMIT 1`,[e]);if(!s||s.length===0)return null;let r=s[0];return{id:r.id,queue:r.queue,jobClass:r.job_class,payload:r.payload,exception:r.exception,failedAt:r.failed_at}}async forget(e){return await(await this.getConnection()).raw(`DELETE FROM ${this.table} WHERE id = ?`,[e]),!0}async flush(){let e=await this.getConnection(),s=(await e.raw(`SELECT COUNT(*) as count FROM ${this.table}`,[]))?.[0]?.count??0;return await e.raw(`DELETE FROM ${this.table}`,[]),s}},os=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)}},as=class{config={default:"sync",connections:{sync:{driver:"sync"}}};drivers=new Map;processing=!1;jobRegistry=new os;failedStore=new is;_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 Le,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 cs(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 Ie){let a=await s.createWorker(r,this.jobRegistry,this.failedStore,{concurrency:e?.concurrency??1});return this.processing=!0,this._activeWorker=a,await new Promise(l=>{let u=()=>{this.processing?setTimeout(u,500):a.close().then(l).catch(l)};u()}),0}let i=e?.maxJobs??1/0,n=(e?.sleep??1)*1e3,o=0;for(this.processing=!0;this.processing&&o<i;){let a=await s.pop(r);if(!a){if(i===1/0){await new Promise(l=>setTimeout(l,n));continue}break}a.attempts++,a.job.attempts=a.attempts;try{await a.job.handle(),o++,s instanceof W&&await s.delete(a.id)}catch(l){if(a.attempts<a.maxAttempts){a.job.retrying(a.attempts);let u=a.job.retryDelay??60;s instanceof W?await s.release(a.id,u):(a.availableAt=Date.now()+u*1e3,await s.push(a))}else a.job.failed(l),await this.failedStore.store(a,l),s instanceof W&&await s.delete(a.id)}}return o}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 Le;break;case"memory":s=new ns;break;case"database":s=new W(t.table??"svelar_jobs",this.jobRegistry);break;case"redis":s=new Ie(t,this.jobRegistry);break;default:throw new Error(`Unknown queue driver: ${t.driver}`)}return this.drivers.set(e,s),s}},cs=class extends K{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()}))})}},ls=w("svelar.queue",()=>new as)});var A,hs=f(()=>{"use strict";b();A=class c{tableName;selectColumns=["*"];whereClauses=[];joinClauses=[];orderClauses=[];groupByColumns=[];havingClauses=[];limitValue=null;offsetValue=null;eagerLoads=[];isDistinct=!1;connectionName;cteClauses=[];unionClauses=[];modelClass;constructor(e,t,s){this.tableName=e,this.modelClass=t,this.connectionName=s}select(...e){return this.selectColumns=e.length>0?e:["*"],this}addSelect(...e){return this.selectColumns[0]==="*"?this.selectColumns=e:this.selectColumns.push(...e),this}distinct(){return this.isDistinct=!0,this}from(e){return this.tableName=e,this}where(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"AND"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}orWhere(e,t,s){return s===void 0?this.whereClauses.push({type:"basic",column:e,operator:"=",value:t,boolean:"OR"}):this.whereClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"OR"}),this}whereIn(e,t){return this.whereClauses.push({type:"in",column:e,values:t,boolean:"AND"}),this}whereNotIn(e,t){return this.whereClauses.push({type:"notIn",column:e,values:t,boolean:"AND"}),this}whereNull(e){return this.whereClauses.push({type:"null",column:e,boolean:"AND"}),this}whereNotNull(e){return this.whereClauses.push({type:"notNull",column:e,boolean:"AND"}),this}whereBetween(e,t){return this.whereClauses.push({type:"between",column:e,values:t,boolean:"AND"}),this}whereRaw(e,t=[]){return this.whereClauses.push({type:"raw",raw:e,values:t,boolean:"AND"}),this}whereNested(e,t="AND"){let s=new c(this.tableName,this.modelClass,this.connectionName);if(e(s),s.whereClauses.length>0){let{whereSQL:r,whereBindings:i}=s.buildWhere(),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 c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"exists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereNotExists(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.whereClauses.push({type:"notExists",subSQL:s,subBindings:r,boolean:"AND"}),this}whereSub(e,t,s){let r=new c("__placeholder__",void 0,this.connectionName);s(r);let{sql:i,bindings: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 c("__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 c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!1}),this}unionAll(e){let t=new c("__placeholder__",void 0,this.connectionName);e(t);let{sql:s,bindings:r}=t.toSQL();return this.unionClauses.push({sql:s,bindings:r,all:!0}),this}join(e,t,s,r){return this.joinClauses.push({type:"INNER",table:e,first:t,operator:s,second:r}),this}leftJoin(e,t,s,r){return this.joinClauses.push({type:"LEFT",table:e,first:t,operator:s,second:r}),this}rightJoin(e,t,s,r){return this.joinClauses.push({type:"RIGHT",table:e,first:t,operator:s,second:r}),this}crossJoin(e){return this.joinClauses.push({type:"CROSS",table:e,first:"",operator:"",second:""}),this}orderBy(e,t="asc"){return this.orderClauses.push({column:e,direction:t}),this}latest(e="created_at"){return this.orderBy(e,"desc")}oldest(e="created_at"){return this.orderBy(e,"asc")}groupBy(...e){return this.groupByColumns.push(...e),this}having(e,t,s){return this.havingClauses.push({type:"basic",column:e,operator:t,value:s,boolean:"AND"}),this}limit(e){return this.limitValue=e,this}offset(e){return this.offsetValue=e,this}take(e){return this.limit(e)}skip(e){return this.offset(e)}with(...e){return this.eagerLoads.push(...e),this}async get(){let{sql:e,bindings:t}=this.toSQL(),s=await m.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 m.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 m.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 m.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 m.raw(t,s,this.connectionName))[0]?.aggregate??null}async min(e){let{sql:t,bindings:s}=this.buildAggregate(`MIN(${e})`);return(await m.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 m.raw(this.toSQL().sql,this.toSQL().bindings,this.connectionName)).map(s=>s[e])}async value(e){return this.selectColumns=[e],this.limitValue=1,(await m.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=m.getDriver(this.connectionName),i=Object.keys(e),n=Object.values(e),o=n.map(()=>"?").join(", "),a=s??i.filter(u=>!t.includes(u)),l;if(r==="postgres"){let u=a.map(d=>`${d} = EXCLUDED.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${o}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}else if(r==="mysql"){let u=a.map(d=>`${d} = VALUES(${d})`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${o}) ON DUPLICATE KEY UPDATE ${u}`}else{let u=a.map(d=>`${d} = excluded.${d}`).join(", ");l=`INSERT INTO ${this.tableName} (${i.join(", ")}) VALUES (${o}) ON CONFLICT (${t.join(", ")}) DO UPDATE SET ${u}`}return m.raw(l,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 o=t.map(a=>n[a]);s.push(...o),r.push(`(${o.map(()=>"?").join(", ")})`)}let i=`INSERT INTO ${this.tableName} (${t.join(", ")}) VALUES ${r.join(", ")}`;return m.raw(i,s,this.connectionName)}async firstOrCreate(e,t={}){for(let[n,o]of Object.entries(e))this.where(n,o);let s=await this.first();if(s)return s;let r={...e,...t},i=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(r);return new c(this.tableName,this.modelClass,this.connectionName).findOrFail(i)}async updateOrCreate(e,t){let s=new c(this.tableName,this.modelClass,this.connectionName);for(let[o,a]of Object.entries(e))s.where(o,a);let r=await s.first();if(r)return await new c(this.tableName,this.modelClass,this.connectionName).where(this.modelClass?.primaryKey??"id",r[this.modelClass?.primaryKey??"id"]).update(t),new c(this.tableName,this.modelClass,this.connectionName).findOrFail(r[this.modelClass?.primaryKey??"id"]);let i={...e,...t},n=await new c(this.tableName,this.modelClass,this.connectionName).insertGetId(i);return new c(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 c("__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(){m.getDriver(this.connectionName)==="sqlite"?(await m.raw(`DELETE FROM ${this.tableName}`,[],this.connectionName),await m.raw("DELETE FROM sqlite_sequence WHERE name = ?",[this.tableName],this.connectionName)):await m.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 m.raw(i,s,this.connectionName)}async insertGetId(e,t="id"){let s=m.getDriver(this.connectionName),r=Object.keys(e),i=Object.values(e),n=i.map(()=>"?").join(", "),o=`INSERT INTO ${this.tableName} (${r.join(", ")}) VALUES (${n})`;return s==="postgres"?(o+=` RETURNING ${t}`,(await m.raw(o,i,this.connectionName))[0]?.[t]):(await m.raw(o,i,this.connectionName),s==="sqlite"?(await m.raw("SELECT last_insert_rowid() as id",[],this.connectionName))[0]?.id:s==="mysql"?(await m.raw("SELECT LAST_INSERT_ID() as id",[],this.connectionName))[0]?.id:0)}async update(e){let t=Object.keys(e),s=Object.values(e),r=t.map(a=>`${a} = ?`).join(", "),{whereSQL:i,whereBindings:n}=this.buildWhere(),o=`UPDATE ${this.tableName} SET ${r}${i}`;return await m.raw(o,[...s,...n],this.connectionName),1}async delete(){let{whereSQL:e,whereBindings:t}=this.buildWhere(),s=`DELETE FROM ${this.tableName}${e}`;return await m.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 m.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 o=this.cteClauses.some(l=>l.recursive)?"WITH RECURSIVE":"WITH",a=this.cteClauses.map(l=>(t.push(...l.bindings),`${l.name} AS (${l.sql})`));e.push(`${o} ${a.join(", ")}`)}this._selectBindings?.length&&t.push(...this._selectBindings);let s=this.isDistinct?"DISTINCT ":"";e.push(`SELECT ${s}${this.selectColumns.join(", ")}`),e.push(`FROM ${this.tableName}`);for(let 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 o of this.havingClauses)o.type==="raw"?(n.push(o.raw),o.values&&t.push(...o.values)):(n.push(`${o.column} ${o.operator} ?`),t.push(o.value));e.push(`HAVING ${n.join(" AND ")}`)}if(this.orderClauses.length>0){let n=this.orderClauses.map(o=>o.__raw?o.column:`${o.column} ${o.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 c(this.tableName,this.modelClass,this.connectionName);return e.selectColumns=[...this.selectColumns],e.whereClauses=[...this.whereClauses],e.joinClauses=[...this.joinClauses],e.orderClauses=[...this.orderClauses],e.groupByColumns=[...this.groupByColumns],e.havingClauses=[...this.havingClauses],e.limitValue=this.limitValue,e.offsetValue=this.offsetValue,e.eagerLoads=[...this.eagerLoads],e.isDistinct=this.isDistinct,e.cteClauses=[...this.cteClauses],e.unionClauses=[...this.unionClauses],e}buildWhere(){if(this.whereClauses.length===0)return{whereSQL:"",whereBindings:[]};let e=[],t=[];for(let s=0;s<this.whereClauses.length;s++){let r=this.whereClauses[s],i=s===0?"WHERE":r.boolean;switch(r.type){case"basic":if((r.operator==="IS"||r.operator==="IS NOT")&&r.value===null){let a=(r.operator==="IS","null");e.push(`${i} ${r.column} ${r.operator} ${a}`)}else e.push(`${i} ${r.column} ${r.operator} ?`),t.push(r.value);break;case"in":let n=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} IN (${n})`),t.push(...r.values);break;case"notIn":let o=r.values.map(()=>"?").join(", ");e.push(`${i} ${r.column} NOT IN (${o})`),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 J,z,V,Q,G,ps=f(()=>{"use strict";b();J=class{parentModel;relatedModel;constructor(e,t){this.parentModel=e,this.relatedModel=t}query(){return this.relatedModel.query()}},z=class extends J{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(o=>o.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),n=new Map;for(let o of i)n.set(o.getAttribute(this.foreignKey),o);for(let o of t){let a=o.getAttribute(this.localKey);o.setRelation(s,n.get(a)??null)}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}},V=class extends J{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(o=>o.getAttribute(this.localKey)),i=await this.relatedModel.query().whereIn(this.foreignKey,r).get(),n=new Map;for(let o of i){let a=o.getAttribute(this.foreignKey);n.has(a)||n.set(a,[]),n.get(a).push(o)}for(let o of t){let a=o.getAttribute(this.localKey);o.setRelation(s,n.get(a)??[])}}async create(t){let s=this.parentModel.getAttribute(this.localKey);return this.relatedModel.create({...t,[this.foreignKey]:s})}async createMany(t){let s=[];for(let r of t)s.push(await this.create(r));return s}},Q=class extends J{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(o=>o.getAttribute(this.foreignKey)).filter(o=>o!=null);if(r.length===0){for(let o of t)o.setRelation(s,null);return}let i=await this.relatedModel.query().whereIn(this.ownerKey,r).get(),n=new Map;for(let o of i)n.set(o.getAttribute(this.ownerKey),o);for(let o of t){let a=o.getAttribute(this.foreignKey);o.setRelation(s,n.get(a)??null)}}associate(t){return this.parentModel.setAttribute(this.foreignKey,t.getAttribute(this.ownerKey)),this.parentModel}dissociate(){return this.parentModel.setAttribute(this.foreignKey,null),this.parentModel}},G=class extends J{constructor(t,s,r,i,n,o="id",a="id"){super(t,s);this.pivotTable=r;this.foreignPivotKey=i;this.relatedPivotKey=n;this.parentKey=o;this.relatedKey=a}async load(t){let s=t.getAttribute(this.parentKey),r=this.relatedModel.tableName,n=(await m.raw(`SELECT ${this.relatedPivotKey} FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ?`,[s])).map(o=>o[this.relatedPivotKey]);return n.length===0?[]:this.relatedModel.query().whereIn(this.relatedKey,n).get()}async eagerLoad(t,s){let r=t.map(d=>d.getAttribute(this.parentKey));if(r.length===0){for(let d of t)d.setRelation(s,[]);return}let i=r.map(()=>"?").join(", "),n=await m.raw(`SELECT * FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} IN (${i})`,r),o=[...new Set(n.map(d=>d[this.relatedPivotKey]))],a=o.length>0?await this.relatedModel.query().whereIn(this.relatedKey,o).get():[],l=new Map;for(let d of a)l.set(d.getAttribute(this.relatedKey),d);let u=new Map;for(let d of n){let h=d[this.foreignPivotKey],g=d[this.relatedPivotKey],y=l.get(g);y&&(u.has(h)||u.set(h,[]),u.get(h).push(y))}for(let d of t){let h=d.getAttribute(this.parentKey);d.setRelation(s,u.get(h)??[])}}async attach(t,s){let r=this.parentModel.getAttribute(this.parentKey),i={[this.foreignPivotKey]:r,[this.relatedPivotKey]:t,...s},n=Object.keys(i),o=Object.values(i),a=o.map(()=>"?").join(", ");await m.raw(`INSERT INTO ${this.pivotTable} (${n.join(", ")}) VALUES (${a})`,o)}async detach(t){let s=this.parentModel.getAttribute(this.parentKey);t?await m.raw(`DELETE FROM ${this.pivotTable} WHERE ${this.foreignPivotKey} = ? AND ${this.relatedPivotKey} = ?`,[s,t]):await m.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 m.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 sn=f(()=>{"use strict"});var ve,ms=f(()=>{"use strict";ve=class{app;constructor(e){this.app=e}boot(){}}});var rn=f(()=>{"use strict";ms();je()});var Te,Y,je=f(()=>{"use strict";E();sn();rn();Te=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)}},Y=w("svelar.event",()=>new Te)});var qe,nn=f(()=>{"use strict";hs();ps();je();qe=class c{static table;static primaryKey="id";static incrementing=!0;static timestamps=!0;static createdAt="created_at";static updatedAt="updated_at";static casts={};static fillable=[];static hidden=[];static connection=void 0;static hooks=new Map;static observers=new Map;static events=[];attributes={};originalAttributes={};relations={};exists=!1;constructor(e){return e&&this.fill(e),new Proxy(this,{get(t,s,r){return typeof s=="symbol"||s in t||typeof s!="string"||["table","primaryKey","incrementing","timestamps","casts","fillable","hidden","connection"].includes(s)?Reflect.get(t,s,r):typeof t[s]=="function"?t[s].bind(t):t.getAttribute(s)},set(t,s,r){return typeof s=="symbol"||s in t?Reflect.set(t,s,r):(t.setAttribute(s,r),!0)}})}static query(){let e=new this,t=this;return new A(t.table,this,t.connection)}static async find(e){let t=this;return this.query().find(e,t.primaryKey)}static async findOrFail(e){let t=this;return this.query().findOrFail(e,t.primaryKey)}static async all(){return this.query().get()}static async first(){return this.query().first()}static async firstOrFail(){return this.query().firstOrFail()}static where(e,t,s){return this.query().where(e,t,s)}static whereIn(e,t){return this.query().whereIn(e,t)}static whereNull(e){return this.query().whereNull(e)}static whereNotNull(e){return this.query().whereNotNull(e)}static orderBy(e,t){return this.query().orderBy(e,t)}static latest(e){return this.query().latest(e)}static oldest(e){return this.query().oldest(e)}static with(...e){return this.query().with(...e)}static async count(){return this.query().count()}static async create(e){let t=new this,s=this;if(t.fill(e),await t.fireHook("creating"),await t.fireHook("saving"),s.timestamps){let o=new Date().toISOString();t.setAttribute(s.createdAt,o),t.setAttribute(s.updatedAt,o)}let r=t.getInsertableAttributes(),n=await new A(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 A(e.table,this.constructor,e.connection).where(e.primaryKey,s).update(t)}this.syncOriginal(),await this.fireHook("updated"),await this.fireHook("saved")}else{if(await this.fireHook("creating"),await this.fireHook("saving"),e.timestamps){let i=new Date().toISOString();this.getAttribute(e.createdAt)||this.setAttribute(e.createdAt,i),this.setAttribute(e.updatedAt,i)}let t=this.getInsertableAttributes(),r=await new A(e.table,this.constructor,e.connection).insertGetId(t,e.primaryKey);e.incrementing&&r&&this.setAttribute(e.primaryKey,r),this.syncOriginal(),this.exists=!0,await this.fireHook("created"),await this.fireHook("saved")}}async update(e){this.fill(e),await this.save()}async delete(){let e=this.constructor;await this.fireHook("deleting");let t=this.getAttribute(e.primaryKey);await new A(e.table,this.constructor,e.connection).where(e.primaryKey,t).delete(),this.exists=!1,await this.fireHook("deleted")}async refresh(){let e=this.constructor,t=this.getAttribute(e.primaryKey),s=await this.constructor.find(t);s&&(this.attributes={...s.attributes},this.syncOriginal())}getAttribute(e){let t=this.constructor,s=this.attributes[e],r=t.casts[e];if(r&&s!==void 0&&s!==null)switch(r){case"number":return Number(s);case"boolean":return!!s;case"string":return String(s);case"date":return new Date(s);case"json":return typeof s=="string"?JSON.parse(s):s}return s}setAttribute(e,t){this.constructor.casts[e]==="json"&&typeof t!="string"?this.attributes[e]=JSON.stringify(t):this.attributes[e]=t}fill(e){let t=this.constructor;for(let[s,r]of Object.entries(e))t.fillable.length>0&&!t.fillable.includes(s)||this.setAttribute(s,r)}getAttributes(){return{...this.attributes}}getOriginal(e){return e?this.originalAttributes[e]:{...this.originalAttributes}}getDirty(){let e={};for(let[t,s]of Object.entries(this.attributes))s!==this.originalAttributes[t]&&(e[t]=s);return e}isDirty(...e){let t=this.getDirty();return e.length===0?Object.keys(t).length>0:e.some(s=>s in t)}isClean(...e){return!this.isDirty(...e)}wasChanged(...e){return this.isDirty(...e)}hasOne(e,t,s){return new z(this,e,t,s??this.constructor.primaryKey)}hasMany(e,t,s){return new V(this,e,t,s??this.constructor.primaryKey)}belongsTo(e,t,s){return new Q(this,e,t,s??e.primaryKey)}belongsToMany(e,t,s,r,i,n){return new G(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 c?i.toJSON():i):r instanceof c?t[s]=r.toJSON():t[s]=r;return t}toObject(){return this.toJSON()}static hydrate(e){let t=new this;return t.attributes={...e},t.syncOriginal(),t.exists=!0,t}static boot(e){this.hooks.set(this.name,e)}static observe(e){let t=this.observers.get(this.name)??[];t.push(e),this.observers.set(this.name,t)}static removeObservers(){this.observers.delete(this.name)}async fireHook(e){let t=this.constructor,s=c.hooks.get(t.name);s?.[e]&&await s[e](this),typeof this[e]=="function"&&await this[e]();let r=c.observers.get(t.name)??[];for(let n of r){let o=n[e];typeof o=="function"&&await o.call(n,this)}let i=t.name.toLowerCase();await Y.emit(`${i}.${e}`,this)}async fireEvent(e){let t=this.constructor;if(!t.events.includes(e))throw new Error(`Event "${e}" is not declared in ${t.name}.events. Add it to: static events = ['${e}', ...];`);let s=c.observers.get(t.name)??[];for(let i of s){let n=i[e];typeof n=="function"&&await n.call(i,this)}let r=t.name.toLowerCase();await Y.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 Ue,on=f(()=>{"use strict";Ue=class{async call(e){await new e().run()}}});var U,an,gs=f(()=>{"use strict";E();U=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}},an=w("svelar.container",()=>new U)});var He,cn=f(()=>{"use strict";gs();He=class{container;providers=[];booted=!1;constructor(e){this.container=e??new U,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 S,L,Fe,X,Be,Z,ee,We,te,se=f(()=>{"use strict";S=class{},L=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 o=this.namedMiddleware.get(n);o&&r.push(o)}let i=t;for(let n=r.length-1;n>=0;n--){let o=r[n],a=i;typeof o.handle=="function"?i=()=>o.handle(e,a):i=()=>o(e,a)}return i()}count(){return this.middleware.length}},Fe=class extends S{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}},X=class extends S{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()}},Be=class extends S{async handle(e,t){let s=Date.now(),r=e.event.request.method,i=e.event.url.pathname,n=await t(),o=Date.now()-s,a=n instanceof Response?n.status:200;return console.log(`[${new Date().toISOString()}] ${r} ${i} \u2192 ${a} (${o}ms)`),n}},Z=class extends S{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(l=>n.startsWith(l)))return this.setTokenAndContinue(e,t);if(this.excludePaths.some(l=>n.startsWith(l)))return t();let o=this.getCookieToken(s),a=s.request.headers.get(this.headerName)??await this.getBodyToken(s);return!o||!a||!this.timingSafeEqual(o,a)?new Response(JSON.stringify({message:"CSRF token mismatch"}),{status:419,headers:{"Content-Type":"application/json"}}):t()}async setTokenAndContinue(e,t){let s=await t();if(!(s instanceof Response))return s;let i=this.getCookieToken(e.event)||this.generateToken();return s.headers.append("Set-Cookie",`${this.cookieName}=${i}; Path=/; SameSite=Lax`),s}getCookieToken(e){let s=(e.request.headers.get("cookie")??"").match(new RegExp(`${this.cookieName}=([^;]+)`));return s?s[1]:null}async getBodyToken(e){try{let t=e.request.headers.get("content-type")??"";if(t.includes("application/x-www-form-urlencoded")||t.includes("multipart/form-data"))return(await e.request.clone().formData()).get(this.fieldName);if(t.includes("application/json"))return(await e.request.clone().json())[this.fieldName]??null}catch{}return null}generateToken(){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}timingSafeEqual(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),i=s.encode(t),n=0;for(let o=0;o<r.length;o++)n|=r[o]^i[o];return n===0}},ee=class extends S{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 o=s.url.origin;return n===o||this.allowedOrigins.has(n)?t():new Response(JSON.stringify({message:"Cross-origin request blocked"}),{status:403,headers:{"Content-Type":"application/json"}})}},We=class extends S{secret;tolerance;signatureHeader;timestampHeader;onlyPaths;constructor(e){super(),this.secret=e.secret,this.tolerance=e.tolerance??300,this.signatureHeader=e.signatureHeader??"X-Signature",this.timestampHeader=e.timestampHeader??"X-Timestamp",this.onlyPaths=e.onlyPaths??null}async handle(e,t){let{event:s}=e;if(this.onlyPaths){let x=s.url.pathname;if(!this.onlyPaths.some(k=>x.startsWith(k)))return t()}let r=s.request.headers.get(this.signatureHeader),i=s.request.headers.get(this.timestampHeader);if(!r||!i)return new Response(JSON.stringify({message:"Missing request signature"}),{status:401,headers:{"Content-Type":"application/json"}});let n=parseInt(i,10),o=Math.floor(Date.now()/1e3);if(isNaN(n)||Math.abs(o-n)>this.tolerance)return new Response(JSON.stringify({message:"Request signature expired"}),{status:401,headers:{"Content-Type":"application/json"}});let l=await s.request.clone().text(),{createHmac:u}=await import("crypto"),d=s.request.method.toUpperCase(),h=s.url.pathname+s.url.search,g=`${i}.${d}.${h}.${l}`,y=u("sha256",this.secret).update(g).digest("hex");return r.length!==y.length||!this.timingSafeCompare(r,y)?new Response(JSON.stringify({message:"Invalid request signature"}),{status:401,headers:{"Content-Type":"application/json"}}):t()}timingSafeCompare(e,t){if(e.length!==t.length)return!1;let s=new TextEncoder,r=s.encode(e),i=s.encode(t),n=0;for(let o=0;o<r.length;o++)n|=r[o]^i[o];return n===0}static sign(e,t,s,r,i){let{createHmac:n}=Me("crypto"),o=i??Math.floor(Date.now()/1e3),a=`${o}.${t.toUpperCase()}.${s}.${r}`;return{signature:n("sha256",e).update(a).digest("hex"),timestamp:o}}},te=class extends S{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 a=Math.ceil((n.blockedUntil-i)/1e3);return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}if(n.count>=this.maxAttempts){n.blockedUntil=i+this.decayMinutes*6e4,n.count=0;let a=this.decayMinutes*60;return new Response(JSON.stringify({message:"Too many attempts. Please try again later.",retry_after:a}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(a)}})}}let o=await t();if(o instanceof Response&&o.status>=400&&o.status<500){let a=this.attempts.get(r)??{count:0,blockedUntil:0};if(a.count++,this.attempts.set(r,a),this.attempts.size>1e4)for(let[l,u]of this.attempts)i>u.blockedUntil+this.decayMinutes*6e4*2&&this.attempts.delete(l)}return o}}});import{z as re}from"zod";function ln(c,e=!1){let t=new c;return e?{GET:t.handle("show"),PUT:t.handle("update"),PATCH:t.handle("update"),DELETE:t.handle("destroy")}:{GET:t.handle("index"),POST:t.handle("store")}}var Ke,I,xe,Ee,Se,un=f(()=>{"use strict";se();Ke=class{controllerMiddleware=[];middleware(e,t){let s;typeof e=="function"&&e.prototype instanceof S?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 L;for(let{middleware:o}of s)r.use(o);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 re.ZodObject?t:re.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 o=await e.request.formData();r=Object.fromEntries(o)}else r=Object.fromEntries(e.url.searchParams);let n=s.safeParse(r);if(!n.success)throw new I(n.error);return n.data}validateQuery(e,t){let s=t instanceof re.ZodObject?t:re.object(t),r=Object.fromEntries(e.url.searchParams),i=s.safeParse(r);if(!i.success)throw new I(i.error);return i.data}validateParams(e,t){let r=(t instanceof re.ZodObject?t:re.object(t)).safeParse(e.params);if(!r.success)throw new I(r.error);return r.data}handleError(e,t){return e instanceof I?this.json({message:"Validation failed",errors:e.errors},422):e instanceof xe?this.json({message:e.message||"Not found"},404):e instanceof Ee?this.json({message:e.message||"Unauthorized"},401):e instanceof Se?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)}};I=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)}}},xe=class extends Error{constructor(e="Not found"){super(e),this.name="NotFoundError"}},Ee=class extends Error{constructor(e="Unauthorized"){super(e),this.name="UnauthorizedError"}},Se=class extends Error{constructor(e="Forbidden"){super(e),this.name="ForbiddenError"}}});import{randomBytes as _o,createHmac as dn,timingSafeEqual as Lo}from"crypto";import{promises as j}from"fs";import{join as Ce}from"path";var ne,Pe,H,Je,ze,Ve,ie,fs=f(()=>{"use strict";se();ne=class c{constructor(e,t){this.id=e;t&&(this.data={...t},this.data._flash&&(this.previousFlashData=this.data._flash,delete this.data._flash))}data={};dirty=!1;flashData={};previousFlashData={};get(e,t){return e in this.flashData?this.flashData[e]:e in this.previousFlashData?this.previousFlashData[e]:e in this.data?this.data[e]:t}set(e,t){this.data[e]=t,this.dirty=!0}has(e){return e in this.data||e in this.flashData||e in this.previousFlashData}forget(e){delete this.data[e],this.dirty=!0}flush(){this.data={},this.dirty=!0}flash(e,t){this.flashData[e]=t,this.dirty=!0}all(){return{...this.data,...this.previousFlashData,...this.flashData}}isDirty(){return this.dirty||Object.keys(this.flashData).length>0}toPersist(){let e={...this.data};return Object.keys(this.flashData).length>0&&(e._flash=this.flashData),e}regenerateId(){let e=this.id,t=c.generateId();this.id=t,this.dirty=!0;let s=Pe.get(e);return s instanceof H&&s.markOldSessionId(e),Pe.delete(e),t}static generateId(){return _o(32).toString("hex")}},Pe=new Map,H=class{sessions=new Map;oldSessionIds=new Set;async read(e){if(this.oldSessionIds.has(e))return null;let t=this.sessions.get(e);return t?Date.now()>t.expiresAt?(this.sessions.delete(e),null):t.data:null}async write(e,t,s){this.sessions.set(e,{data:t,expiresAt:Date.now()+s*1e3}),Pe.set(e,this)}async destroy(e){this.sessions.delete(e),Pe.delete(e)}async gc(e){let t=Date.now();for(let[s,r]of this.sessions)t>r.expiresAt&&(this.sessions.delete(s),Pe.delete(s))}markOldSessionId(e){this.oldSessionIds.add(e),this.sessions.delete(e)}},Je=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(()=>(b(),v));switch(e.getDriver(this.connectionName)){case"sqlite":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
42
+ id TEXT PRIMARY KEY,
43
+ payload TEXT NOT NULL,
44
+ expires_at TEXT NOT NULL
45
+ )`,[],this.connectionName);break;case"postgres":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
46
+ id VARCHAR(255) PRIMARY KEY,
47
+ payload TEXT NOT NULL,
48
+ expires_at TIMESTAMPTZ NOT NULL
49
+ )`,[],this.connectionName);break;case"mysql":await e.raw(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
50
+ id VARCHAR(255) PRIMARY KEY,
51
+ payload TEXT NOT NULL,
52
+ expires_at DATETIME NOT NULL
53
+ ) ENGINE=InnoDB`,[],this.connectionName);break}this.tableEnsured=!0}catch{}}async read(e){await this.ensureTable();let{Connection:t}=await Promise.resolve().then(()=>(b(),v)),s=await t.raw(`SELECT payload, expires_at FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName);if(s.length===0)return null;let r=s[0];if(new Date(r.expires_at)<new Date)return await this.destroy(e),null;try{return JSON.parse(r.payload)}catch{return null}}async write(e,t,s){await this.ensureTable();let{Connection:r}=await Promise.resolve().then(()=>(b(),v)),i=JSON.stringify(t),n=new Date(Date.now()+s*1e3).toISOString(),o=r.getDriver(this.connectionName);o==="sqlite"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
54
+ ON CONFLICT(id) DO UPDATE SET payload = excluded.payload, expires_at = excluded.expires_at`,[e,i,n],this.connectionName):o==="postgres"?await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES ($1, $2, $3)
55
+ ON CONFLICT(id) DO UPDATE SET payload = $2, expires_at = $3`,[e,i,n],this.connectionName):await r.raw(`INSERT INTO ${this.tableName} (id, payload, expires_at) VALUES (?, ?, ?)
56
+ ON DUPLICATE KEY UPDATE payload = VALUES(payload), expires_at = VALUES(expires_at)`,[e,i,n],this.connectionName)}async destroy(e){let{Connection:t}=await Promise.resolve().then(()=>(b(),v));await t.raw(`DELETE FROM ${this.tableName} WHERE id = ?`,[e],this.connectionName)}async gc(e){let{Connection:t}=await Promise.resolve().then(()=>(b(),v));await t.raw(`DELETE FROM ${this.tableName} WHERE expires_at < ?`,[new Date().toISOString()],this.connectionName)}},ze=class{dir;constructor(e){this.dir=e??Ce(process.cwd(),"storage","sessions")}filePath(e){let t=e.replace(/[^a-zA-Z0-9_-]/g,"");return Ce(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(Ce(this.dir,r),"utf-8"),n=JSON.parse(i);new Date(n.expiresAt)<s&&await j.unlink(Ce(this.dir,r))}catch{await j.unlink(Ce(this.dir,r)).catch(()=>{})}}catch{}}},Ve=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){}},ie=class extends S{config;constructor(e){super(),this.config={cookieName:"svelar_session",lifetime:7200,secret:process.env.APP_KEY??(()=>{throw new Error("APP_KEY is not set. Set it in your .env file before using sessions.")})(),path:"/",domain:"",secure:process.env.NODE_ENV==="production",httpOnly:!0,sameSite:"lax",...e}}async handle(e,t){let s=e.event.request.headers.get("cookie")??"",r=this.getSessionIdFromCookie(s),i=null;if(r){let a=this.verifySignedId(r);a?(i=await this.config.store.read(a),r=a):r=null}r||(r=ne.generateId());let n=new ne(r,i??{});e.event.locals.session=n,e.locals.session=n;let o=await t();if(n.isDirty()&&await this.config.store.write(n.id,n.toPersist(),this.config.lifetime),o instanceof Response){let a=this.signId(n.id),l=this.buildCookieString(a);o.headers.append("Set-Cookie",l)}return o}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=dn("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=dn("sha256",this.config.secret).update(s).digest("base64url");if(r.length!==i.length)return null;let n=Buffer.from(r),o=Buffer.from(i);if(n.length!==o.length)return null;try{if(Lo(n,o))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 Re={};C(Re,{Hash:()=>bs});import{randomBytes as ys,scrypt as hn,timingSafeEqual as Io}from"crypto";async function jo(c,e=16384){let t=ys(16),s=64,r=await new Promise((i,n)=>{hn(c,t,s,{N:e,r:8,p:1},(o,a)=>{o?n(o):i(a)})});return`$scrypt$N=${e}$${t.toString("base64")}$${r.toString("base64")}`}async function qo(c,e){let t=e.split("$");if(t.length!==5||t[1]!=="scrypt")return!1;let s=parseInt(t[2].replace("N=",""),10),r=Buffer.from(t[3],"base64"),i=Buffer.from(t[4],"base64"),n=i.length,o=await new Promise((a,l)=>{hn(c,r,n,{N:s,r:8,p:1},(u,d)=>{u?l(u):a(d)})});return Io(o,i)}var ws,bs,oe=f(()=>{"use strict";E();ws=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 jo(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 qo(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 ys(Math.ceil(e/2)).toString("hex").slice(0,e)}randomToken(e=32){return ys(e).toString("base64url")}},bs=w("svelar.hash",()=>new ws)});var pn={};C(pn,{EmailTemplates:()=>Uo});import{randomUUID as D}from"crypto";var vs,Uo,mn=f(()=>{"use strict";E();vs=class{config={driver:"memory"};templates=new Map;constructor(){this.registerDefaults()}configure(e){this.config=e}async register(e){let t={...e,id:D(),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(()=>(b(),v));await s.connection()}catch{this.templates.set(e.name,t)}return t}async render(e,t){let s=await this.get(e);if(!s)throw new Error(`Template "${e}" not found`);let r=this.interpolate(s.subject,t),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:D(),name:"welcome",subject:"Welcome to {{appName}}, {{user.name}}!",html:`
57
+ <h1>Welcome, {{user.name}}!</h1>
58
+ <p>Thank you for joining {{appName}}.</p>
59
+ <p>Your account has been created with the email: <strong>{{user.email}}</strong></p>
60
+ <p><a href="{{confirmUrl}}">Confirm your email address</a></p>
61
+ `,text:`Welcome, {{user.name}}!
62
+
63
+ Confirm your email: {{confirmUrl}}`,variables:["appName","user.name","user.email","confirmUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("password-reset",{id:D(),name:"password-reset",subject:"Reset your {{appName}} password",html:`
64
+ <h1>Password Reset</h1>
65
+ <p>Hi {{user.name}},</p>
66
+ <p>Click the link below to reset your password. This link expires in 1 hour.</p>
67
+ <p><a href="{{resetUrl}}">Reset Password</a></p>
68
+ <p>If you didn't request this, you can ignore this email.</p>
69
+ `,text:`Reset your password: {{resetUrl}}
70
+
71
+ This link expires in 1 hour.`,variables:["appName","user.name","resetUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("email-verification",{id:D(),name:"email-verification",subject:"Verify your email address",html:`
72
+ <h1>Verify Your Email</h1>
73
+ <p>Hi {{user.name}},</p>
74
+ <p><a href="{{verifyUrl}}">Click here to verify your email address</a></p>
75
+ <p>This link expires in 24 hours.</p>
76
+ `,text:"Verify your email: {{verifyUrl}}",variables:["user.name","verifyUrl"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("team-invitation",{id:D(),name:"team-invitation",subject:"{{inviter.name}} invited you to join {{team.name}}",html:`
77
+ <h1>Team Invitation</h1>
78
+ <p>Hi {{user.name}},</p>
79
+ <p><strong>{{inviter.name}}</strong> has invited you to join the team <strong>{{team.name}}</strong>.</p>
80
+ <p><a href="{{acceptUrl}}">Accept Invitation</a></p>
81
+ <p>This invitation expires in 3 days.</p>
82
+ `,text:"Accept: {{acceptUrl}}",variables:["user.name","inviter.name","team.name","acceptUrl"],category:"notification",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("invoice",{id:D(),name:"invoice",subject:"Invoice #{{invoice.number}} from {{appName}}",html:`
83
+ <h1>Invoice #{{invoice.number}}</h1>
84
+ <p>Hi {{customer.name}},</p>
85
+ <p>Thank you for your purchase!</p>
86
+ <p><strong>Amount:</strong> {{invoice.amount}}</p>
87
+ <p><strong>Date:</strong> {{invoice.date}}</p>
88
+ <p><a href="{{invoiceUrl}}">View Invoice</a></p>
89
+ `,text:`Invoice #{{invoice.number}}
90
+ Amount: {{invoice.amount}}`,variables:["appName","customer.name","invoice.number","invoice.amount","invoice.date","invoiceUrl"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-confirmation",{id:D(),name:"subscription-confirmation",subject:"Subscription Confirmation",html:`
91
+ <h1>Subscription Confirmed</h1>
92
+ <p>Hi {{user.name}},</p>
93
+ <p>Your {{plan.name}} plan is now active.</p>
94
+ <p><strong>Price:</strong> {{plan.price}} / {{plan.interval}}</p>
95
+ <p>Your next billing date is {{nextBillingDate}}.</p>
96
+ `,text:`Your {{plan.name}} plan is active.
97
+ Next billing: {{nextBillingDate}}`,variables:["user.name","plan.name","plan.price","plan.interval","nextBillingDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("otp-code",{id:D(),name:"otp-code",subject:"Your {{appName}} verification code: {{code}}",html:`
98
+ <h1>Your Verification Code</h1>
99
+ <p>Hi {{user.name}},</p>
100
+ <p>Your one-time verification code is:</p>
101
+ <p style="font-size: 32px; font-weight: bold; letter-spacing: 8px; text-align: center; padding: 16px; background: #f3f4f6; border-radius: 8px; font-family: monospace;">{{code}}</p>
102
+ <p>This code expires in {{expiresMinutes}} minutes.</p>
103
+ <p>If you didn't request this code, you can safely ignore this email.</p>
104
+ `,text:`Your verification code: {{code}}
105
+
106
+ This code expires in {{expiresMinutes}} minutes.`,variables:["appName","user.name","code","expiresMinutes","purpose"],category:"auth",active:!0,createdAt:Date.now(),updatedAt:Date.now()}),this.templates.set("subscription-canceled",{id:D(),name:"subscription-canceled",subject:"Your subscription has been canceled",html:`
107
+ <h1>Subscription Canceled</h1>
108
+ <p>Hi {{user.name}},</p>
109
+ <p>Your {{plan.name}} subscription has been canceled.</p>
110
+ <p>You have access until {{accessUntilDate}}.</p>
111
+ `,text:`Your {{plan.name}} subscription is canceled.
112
+ Access until: {{accessUntilDate}}`,variables:["user.name","plan.name","accessUntilDate"],category:"billing",active:!0,createdAt:Date.now(),updatedAt:Date.now()})}interpolate(e,t){let s=e;return s=s.replace(/\{\{#if\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/if\}\}/g,(r,i,n)=>this.getNestedValue(t,i)?n:""),s=s.replace(/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,i,n)=>{let o=this.getNestedValue(t,i);return Array.isArray(o)?o.map((a,l)=>{let u={...t,this:a,$index:l};return this.interpolate(n,u)}).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)}},Uo=w("svelar.emailTemplates",()=>new vs)});var $s={};C($s,{Mailable:()=>$e,Mailer:()=>Rs});function Ps(c){return typeof c=="string"?c:`${c.name} <${c.address}>`}function R(c){return c?Array.isArray(c)?c:[c]:[]}function gn(c){return Buffer.isBuffer(c)?c.toString("base64"):Buffer.from(c).toString("base64")}var Qe,Ts,xs,Es,Ss,$e,Cs,Rs,Ge=f(()=>{"use strict";E();Qe=class{async send(e){let t=R(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:[]}}},Ts=class{async send(e){return{accepted:R(e.to),rejected:[]}}},xs=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?Ps(e.from):void 0,to:R(e.to).join(", "),cc:R(e.cc).join(", ")||void 0,bcc:R(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}}},Es=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=R(e.to),r=R(e.cc),i=R(e.bcc),n={From:e.from?Ps(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(l=>({Name:l.filename,Content:gn(l.content),ContentType:l.contentType||"application/octet-stream"})));let o=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(!o.ok){let l=await o.json().catch(()=>({Message:o.statusText}));throw new Error(`Postmark error ${o.status}: ${l.Message||JSON.stringify(l)}`)}let a=await o.json();return{accepted:s,rejected:[],messageId:a.MessageID}}},Ss=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=R(e.to),r=R(e.cc),i=R(e.bcc),n={from:e.from?Ps(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(([l,u])=>({name:l,value:u}))),e.attachments?.length&&(n.attachments=e.attachments.map(l=>({filename:l.filename,content:gn(l.content),content_type:l.contentType||"application/octet-stream"})));let o=await fetch("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(n)});if(!o.ok){let l=await o.json().catch(()=>({message:o.statusText}));throw new Error(`Resend error ${o.status}: ${l.message||JSON.stringify(l)}`)}let a=await o.json();return{accepted:s,rejected:[],messageId:a.id}}},$e=class{message={};to(e){return this.message.to=e,this}cc(e){return this.message.cc=e,this}bcc(e){return this.message.bcc=e,this}from(e){return this.message.from=e,this}replyTo(e){return this.message.replyTo=e,this}subject(e){return this.message.subject=e,this}text(e){return this.message.text=e,this}html(e){return this.message.html=e,this}attach(e,t,s){return this.message.attachments||(this.message.attachments=[]),this.message.attachments.push({filename:e,content:t,contentType:s}),this}tag(e,t){return this.message.tags||(this.message.tags={}),this.message.tags[e]=t,this}toMessage(){return this.message}},Cs=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 Qe;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 xs(s);break;case"postmark":r=new Es(s);break;case"resend":r=new Ss(s);break;case"log":r=new Qe;break;case"null":r=new Ts;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}},Rs=w("svelar.mail",()=>new Cs)});import{createHmac as ae,randomBytes as ke}from"crypto";function fn(c){return(typeof c=="string"?Buffer.from(c):c).toString("base64url")}function yn(c){return Buffer.from(c,"base64url").toString("utf-8")}function wn(c,e,t,s){return ae(s==="HS384"?"sha384":s==="HS512"?"sha512":"sha256",t).update(`${c}.${e}`).digest("base64url")}function ks(c,e,t="HS256"){let s=fn(JSON.stringify({alg:t,typ:"JWT"})),r=fn(JSON.stringify(c)),i=wn(s,r,e,t);return`${s}.${r}.${i}`}function As(c,e){let t=c.split(".");if(t.length!==3)return null;let[s,r,i]=t,n;try{n=JSON.parse(yn(s))}catch{return null}let o=wn(s,r,e,n.alg);if(i!==o)return null;try{let a=JSON.parse(yn(r));return a.exp&&Date.now()/1e3>a.exp?null:a}catch{return null}}var Ye,ce,Xe,Ns=f(()=>{"use strict";se();Ye=class{config;currentUser=null;constructor(e){this.config={identifierColumn:"email",passwordColumn:"password",...e}}async attempt(e,t){let{Hash:s}=await Promise.resolve().then(()=>(oe(),Re)),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 o=n.getAttribute(this.config.passwordColumn);return await s.verify(i,o)?(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(()=>(oe(),Re));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=ks(i,t.secret,t.algorithm),o=new Date((r+s)*1e3),a={user:e,token:n,expiresAt:o};if(t.refreshTokens){let l=t.refreshExpiresIn??604800,u=ke(32).toString("base64url"),d=ae("sha256",t.secret).update(u).digest("hex"),h=new Date((r+l)*1e3),{Connection:g}=await Promise.resolve().then(()=>(b(),v)),y=t.refreshTable??"refresh_tokens";await g.raw(`INSERT INTO ${y} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),d,h.toISOString(),new Date().toISOString()]),a.refreshToken=u,a.refreshExpiresAt=h}return a}async refreshJwt(e){if(!this.config.jwt)throw new Error("JWT configuration required.");if(!this.config.jwt.refreshTokens)throw new Error("Refresh tokens are not enabled. Set jwt.refreshTokens = true.");let t=this.config.jwt,s=ae("sha256",t.secret).update(e).digest("hex"),{Connection:r}=await Promise.resolve().then(()=>(b(),v)),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 o=n[0];if(o.revoked_at||new Date(o.expires_at)<new Date)return null;await r.raw(`UPDATE ${i} SET revoked_at = ? WHERE token = ?`,[new Date().toISOString(),s]);let a=await this.config.model.find(o.user_id);return a?(this.currentUser=a,this.issueTokenPair(a)):null}async revokeRefreshTokens(e){if(!this.config.jwt?.refreshTokens)return;let{Connection:t}=await Promise.resolve().then(()=>(b(),v)),s=this.config.jwt.refreshTable??"refresh_tokens";await t.raw(`UPDATE ${s} SET revoked_at = ? WHERE user_id = ? AND revoked_at IS NULL`,[new Date().toISOString(),e])}async resolveFromToken(e){if(!this.config.jwt)throw new Error("JWT configuration required.");let t=As(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(()=>(oe(),Re));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=ke(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=ae("sha256",r).update(s).digest("hex"),{Connection:n}=await Promise.resolve().then(()=>(b(),v)),o=this.config.token?.table??"personal_access_tokens";return await n.raw(`INSERT INTO ${o} (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(()=>(b(),v)),s=this.config.token?.table??"personal_access_tokens",r=this.config.jwt?.secret??process.env.APP_KEY;if(!r)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");let i=ae("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 o=await this.config.model.find(n[0].user_id);return o&&(this.currentUser=o),o}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(()=>(b(),v)),r=this.config.passwordResets?.table??"password_resets",i=this.config.passwordResets?.expiresIn??3600;await this.ensureTable(r,`
113
+ CREATE TABLE IF NOT EXISTS ${r} (
114
+ email TEXT NOT NULL,
115
+ token TEXT NOT NULL,
116
+ expires_at TEXT NOT NULL,
117
+ created_at TEXT NOT NULL
118
+ )
119
+ `),await s.raw(`DELETE FROM ${r} WHERE email = ?`,[e]);let n=ke(32).toString("base64url"),o=this.hashToken(n),a=new Date(Date.now()+i*1e3).toISOString();await s.raw(`INSERT INTO ${r} (email, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e,o,a,new Date().toISOString()]);let l=this.config.appUrl??process.env.APP_URL??"http://localhost:5173",u=this.config.appName??process.env.APP_NAME??"Svelar",d=`${l}/reset-password?token=${n}&email=${encodeURIComponent(e)}`;return await this.sendAuthEmail("password-reset",e,{appName:u,"user.name":t.getAttribute("name")??e,resetUrl:d}),!0}async resetPassword(e,t,s){let{Connection:r}=await Promise.resolve().then(()=>(b(),v)),{Hash:i}=await Promise.resolve().then(()=>(oe(),Re)),n=this.config.passwordResets?.table??"password_resets",o=this.hashToken(e),a=await r.raw(`SELECT email, expires_at FROM ${n} WHERE token = ? AND email = ?`,[o,t]);if(a.length===0)return!1;let l=a[0];if(new Date(l.expires_at)<new Date)return await r.raw(`DELETE FROM ${n} WHERE email = ?`,[t]),!1;let u=await this.config.model.where(this.config.identifierColumn,t).first();if(!u)return!1;let d=await i.make(s);return await this.config.model.where("id",u.getAttribute("id")).update({[this.config.passwordColumn]:d}),await r.raw(`DELETE FROM ${n} WHERE email = ?`,[t]),await this.revokeRefreshTokens(u.getAttribute("id")),!0}async sendVerificationEmail(e){let{Connection:t}=await Promise.resolve().then(()=>(b(),v)),s=this.config.emailVerification?.table??"email_verifications",r=this.config.emailVerification?.expiresIn??86400,i=e.getAttribute(this.config.identifierColumn);await this.ensureTable(s,`
120
+ CREATE TABLE IF NOT EXISTS ${s} (
121
+ user_id TEXT NOT NULL,
122
+ token TEXT NOT NULL,
123
+ expires_at TEXT NOT NULL,
124
+ created_at TEXT NOT NULL
125
+ )
126
+ `),await t.raw(`DELETE FROM ${s} WHERE user_id = ?`,[e.getAttribute("id")]);let n=ke(32).toString("base64url"),o=this.hashToken(n),a=new Date(Date.now()+r*1e3).toISOString();await t.raw(`INSERT INTO ${s} (user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?)`,[e.getAttribute("id"),o,a,new Date().toISOString()]);let u=`${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:u})}async verifyEmail(e,t){let{Connection:s}=await Promise.resolve().then(()=>(b(),v)),r=this.config.emailVerification?.table??"email_verifications",i=this.config.emailVerification?.verifiedColumn??"email_verified_at",n=this.hashToken(e),o=await s.raw(`SELECT user_id, expires_at FROM ${r} WHERE token = ? AND user_id = ?`,[n,t]);return o.length===0?!1:new Date(o[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(()=>(b(),v)),i=this.config.otp?.table??"otp_codes",n=this.config.otp?.expiresIn??600,o=this.config.otp?.length??6;await this.ensureTable(i,`
127
+ CREATE TABLE IF NOT EXISTS ${i} (
128
+ email TEXT NOT NULL,
129
+ code TEXT NOT NULL,
130
+ purpose TEXT NOT NULL DEFAULT 'login',
131
+ expires_at TEXT NOT NULL,
132
+ used_at TEXT,
133
+ created_at TEXT NOT NULL
134
+ )
135
+ `),await r.raw(`DELETE FROM ${i} WHERE email = ? AND purpose = ?`,[e,t]);let a=this.generateOtpCode(o),l=this.hashToken(a),u=new Date(Date.now()+n*1e3).toISOString();await r.raw(`INSERT INTO ${i} (email, code, purpose, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,[e,l,t,u,new Date().toISOString()]);let d=this.config.appName??process.env.APP_NAME??"Svelar",h=Math.ceil(n/60);return await this.sendAuthEmail("otp-code",e,{appName:d,"user.name":s.getAttribute("name")??e,code:a,purpose:t,expiresMinutes:String(h)}),!0}async verifyOtp(e,t,s="login"){let{Connection:r}=await Promise.resolve().then(()=>(b(),v)),i=this.config.otp?.table??"otp_codes",n=this.hashToken(t),o=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(o.length===0)return null;if(new Date(o[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 a=await this.config.model.where(this.config.identifierColumn,e).first();return a&&(this.currentUser=a),a}async attemptOtp(e,t,s,r="login"){let i=await this.verifyOtp(e,t,r);return i?(s&&(s.set("auth_user_id",i.getAttribute("id")),s.regenerateId()),i):null}async cleanupExpiredTokens(){let{Connection:e}=await Promise.resolve().then(()=>(b(),v)),t=new Date().toISOString(),s=0,r=0,i=0,n=this.config.passwordResets?.table??"password_resets",o=this.config.emailVerification?.table??"email_verifications",a=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 ${o} WHERE expires_at < ?`,[t]))?.changes??0}catch{}try{i=(await e.raw(`DELETE FROM ${a} WHERE expires_at < ? OR used_at IS NOT NULL`,[t]))?.changes??0}catch{}return{passwordResets:s,verifications:r,otpCodes:i}}hashToken(e){let t=this.config.jwt?.secret??process.env.APP_KEY;if(!t)throw new Error("APP_KEY is not set. Set it in your .env file or pass jwt.secret in auth config.");return ae("sha256",t).update(e).digest("hex")}generateOtpCode(e){let t=ke(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(()=>(b(),v));await s.raw(t),this.tablesEnsured.add(e)}async sendAuthEmail(e,t,s){try{let{EmailTemplates:r}=await Promise.resolve().then(()=>(mn(),pn)),{Mailer:i}=await Promise.resolve().then(()=>(Ge(),$s)),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)}}},ce=class extends S{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()}},Xe=class extends S{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 Ho,mkdir as Fo}from"fs/promises";import{dirname as Bo}from"path";function N(){return new Date().toISOString()}var Ze,Ae,Ds,Ms,Os,_s,Ls,et,Is=f(()=>{"use strict";E();Ze={debug:0,info:1,warn:2,error:3,fatal:4},Ae=class{minLevel;format;constructor(e){this.minLevel=e.level??"debug",this.format=e.format??"text"}write(e){if(Ze[e.level]<Ze[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)}`:"",o=e.level==="error"||e.level==="fatal"?"error":"log";console[o](`${r}[${e.timestamp}] ${i}${s} ${e.message}${n}`)}},Ds=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(Ze[e.level]<Ze[this.minLevel])return;this.initialized||(await Fo(Bo(this.path),{recursive:!0}),this.initialized=!0);let t;if(this.format==="json")t=JSON.stringify(e)+`
136
+ `;else{let s=e.level.toUpperCase().padEnd(5),r=Object.keys(e.context).length>0?` ${JSON.stringify(e.context)}`:"";t=`[${e.timestamp}] ${s} ${e.message}${r}
137
+ `}await Ho(this.path,t)}},Ms=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)}}},Os=class{minLevel="debug";write(){}},_s=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 Ls(this.resolveChannel(e))}debug(e,t={}){this.writeToDefault({level:"debug",message:e,context:t,timestamp:N()})}info(e,t={}){this.writeToDefault({level:"info",message:e,context:t,timestamp:N()})}warn(e,t={}){this.writeToDefault({level:"warn",message:e,context:t,timestamp:N()})}error(e,t={}){this.writeToDefault({level:"error",message:e,context:t,timestamp:N()})}fatal(e,t={}){this.writeToDefault({level:"fatal",message:e,context:t,timestamp:N()})}writeToDefault(e){this.resolveChannel(this.config.default).write(e)}resolveChannel(e){if(this.channels.has(e))return this.channels.get(e);let t=this.config.channels[e];if(!t){let r=new Ae({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 Ae(e);case"file":return new Ds(e);case"stack":return new Ms(e,t=>this.resolveChannel(t));case"null":return new Os;default:return new Ae(e)}}},Ls=class{constructor(e){this.channel=e}debug(e,t={}){this.channel.write({level:"debug",message:e,context:t,timestamp:N()})}info(e,t={}){this.channel.write({level:"info",message:e,context:t,timestamp:N()})}warn(e,t={}){this.channel.write({level:"warn",message:e,context:t,timestamp:N()})}error(e,t={}){this.channel.write({level:"error",message:e,context:t,timestamp:N()})}fatal(e,t={}){this.channel.write({level:"fatal",message:e,context:t,timestamp:N()})}};et=w("svelar.log",()=>new _s)});function nt(c,e){throw new $(c,e??Wo(c))}function bn(c,e,t){c&&nt(e,t)}function vn(c,e,t){c||nt(e,t)}function Wo(c){return{400:"Bad request",401:"Unauthenticated",403:"Forbidden",404:"Not found",405:"Method not allowed",409:"Conflict",419:"Page expired",422:"Unprocessable entity",429:"Too many requests",500:"Internal server error",502:"Bad gateway",503:"Service unavailable",504:"Gateway timeout"}[c]??"An error occurred"}var $,tt,js,qs,st,rt,le,Us=f(()=>{"use strict";Is();$=class extends Error{constructor(t,s,r){super(s);this.statusCode=t;this.details=r;this.name="HttpError"}},tt=class extends ${constructor(e="The requested resource was not found"){super(404,e),this.name="NotFoundError"}},js=class extends ${constructor(e="Unauthenticated"){super(401,e),this.name="UnauthorizedError"}},qs=class extends ${constructor(e="You do not have permission to perform this action"){super(403,e),this.name="ForbiddenError"}},st=class extends ${constructor(t,s="The given data was invalid"){super(422,s,{errors:t});this.errors=t;this.name="ValidationError"}},rt=class extends tt{constructor(e,t){super(t?`${e} with ID ${t} not found`:`${e} not found`),this.name="ModelNotFoundError"}};le=class{config;constructor(e={}){this.config={debug:process.env.NODE_ENV!=="production",dontReport:[st,tt,js,qs],...e}}async handle(e,t){let s=e instanceof Error?e:new Error(String(e));return await this.reportError(s,t),this.config.render?this.config.render(s,t):this.renderError(s)}handleSvelteKitError(){return({error:e,event:t,status:s,message:r})=>{let i=e instanceof Error?e:new Error(String(e));return this.reportError(i,t),i instanceof $?{message:i.message,status:i.statusCode,...i.details??{},...this.config.debug?{stack:i.stack}:{}}:{message:this.config.debug?i.message:"An unexpected error occurred",status:s,...this.config.debug?{stack:i.stack}:{}}}}middleware(){let e=this;return async(t,s)=>{try{return await s()}catch(r){return e.handle(r,t.event)}}}async reportError(e,t){if(this.config.dontReport){for(let r of this.config.dontReport)if(e instanceof r)return}let s={error:e.name,...t?.url?{url:t.url.toString()}:{},...e.stack?{stack:e.stack}:{}};if(et.error(e.message,s),this.config.report)try{await this.config.report(e,t?{url:t.url?.toString()}:void 0)}catch{}}renderError(e){if(e instanceof $){let s={message:e.message};return e instanceof st&&(s.errors=e.errors),e.details&&Object.assign(s,e.details),this.config.debug&&(s.exception=e.name,s.stack=e.stack?.split(`
138
+ `).map(r=>r.trim())),new Response(JSON.stringify(s),{status:e.statusCode,headers:{"Content-Type":"application/json"}})}let t={message:this.config.debug?e.message:"Internal server error"};return this.config.debug&&(t.exception=e.name,t.stack=e.stack?.split(`
139
+ `).map(s=>s.trim())),new Response(JSON.stringify(t),{status:500,headers:{"Content-Type":"application/json"}})}}});function Tn(c={}){let{auth:e,secret:t=process.env.APP_KEY||(()=>{throw new Error("APP_KEY is not set. Set it in your .env file.")})(),sessionStore:s,sessionLifetime:r=86400,rateLimit:i=100,rateLimitWindow:n=6e4,csrfPaths:o=["/api/"],csrfExcludePaths:a=["/api/webhooks"],authThrottleAttempts:l=5,authThrottleDecay:u=1,debug:d=process.env.NODE_ENV!=="production",middleware:h=[],namedMiddleware:g={},i18n:y,errorConfig:x={}}=c,k=[new ee,new X({maxRequests:i,windowMs:n}),new Z({onlyPaths:o,excludePaths:a}),new ie({store:s??new H,secret:t,lifetime:r})];e&&k.push(new ce(e)),k.push(...h);let ri={"auth-throttle":new te({maxAttempts:l,decayMinutes:u}),...g},wr=new le({debug:d,...x}),br=Hs({middleware:k,namedMiddleware:ri,onError:(pt,mt)=>wr.handle(pt,mt)}),ht;if(y){let{paraglideMiddleware:pt,getTextDirection:mt=()=>"ltr"}=y;ht=Fs(async({event:gt,resolve:ni})=>pt(gt.request,({request:ii,locale:vr})=>(gt.request=ii,ni(gt,{transformPageChunk:({html:oi})=>oi.replace("%lang%",vr).replace("%dir%",mt(vr))}))),br)}else ht=br;return{handle:ht,handleError:wr.handleSvelteKitError()}}function Hs(c={}){let e=new L;if(c.middleware)for(let t of c.middleware)e.use(t);if(c.namedMiddleware)for(let[t,s]of Object.entries(c.namedMiddleware))e.register(t,s);return async function({event:s,resolve:r}){let i={event:s,params:s.params??{},locals:s.locals??{}};try{c.app&&!c.app.isBooted()&&await c.app.bootstrap();let n=await e.execute(i,async()=>r(s));return n instanceof Response?n:r(s)}catch(n){if(c.onError){let o=await c.onError(n,s);if(o instanceof Response)return o}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 Fs(...c){return async function({event:t,resolve:s}){let r=s;for(let i=c.length-1;i>=0;i--){let n=c[i],o=r;r=a=>n({event:a,resolve:o})}return r(t)}}var Bs=f(()=>{"use strict";se();fs();Ns();Us()});function xn(c,e){let t=process.env[c];return t===void 0?e!==void 0?e:"":t==="true"?!0:t==="false"?!1:t==="null"?null:/^\d+$/.test(t)?Number(t):t}var Ws,En,Sn=f(()=>{"use strict";E();Ws=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:o}=await import("url"),a=t(e);if(!i(a))return[];let l=n(a).filter(d=>(d.endsWith(".ts")||d.endsWith(".js"))&&!d.startsWith(".")),u=[];for(let d of l){let h=s(d,r(d)),g=t(a,d);try{let x=await import(o(g).href),k=x.default??x.config??x;k&&typeof k=="object"&&!Array.isArray(k)&&(this.set(h,k),u.push(h))}catch{}}return u}get(e,t){let s=e.split("."),r=this.items.get(s[0]);for(let i=1;i<s.length;i++){if(r==null)return t;r=r[s[i]]}return r??t}set(e,t){let s=e.split(".");if(s.length===1){this.items.set(e,t);return}let r=this.items.get(s[0]);(r===void 0||typeof r!="object")&&(r={},this.items.set(s[0],r));let i=r;for(let 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}},En=w("svelar.config",()=>new Ws)});import{z as T}from"zod";function Pn(c,e){let t=c.safeParse(e);if(t.success)return{success:!0,data:t.data};let s={};for(let r of t.error.issues){let i=r.path.length>0?r.path:["_root"],n=s;for(let a=0;a<i.length-1;a++){let l=i[a];l in n||(n[l]={}),n=n[l]}let o=i[i.length-1];n[o]||(n[o]=[]),n[o].push(r.message)}return{success:!1,errors:s}}var Cn,Rn=f(()=>{"use strict";Cn={required:()=>T.string().min(1,"This field is required"),email:()=>T.string().email("Must be a valid email address"),string:(c,e)=>{let t=T.string();return c!==void 0&&(t=t.min(c)),e!==void 0&&(t=t.max(e)),t},number:(c,e)=>{let t=T.number();return c!==void 0&&(t=t.min(c)),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:c=>T.enum(c),array:c=>T.array(c),nullable:c=>c.nullable(),optional:c=>c.optional(),confirmed:(c="password")=>T.object({[c]:T.string(),[`${c}_confirmation`]:T.string()}).refine(e=>e[c]===e[`${c}_confirmation`],{message:"Confirmation does not match",path:[`${c}_confirmation`]}),min:c=>T.number().min(c),max:c=>T.number().max(c),between:(c,e)=>T.number().min(c).max(e),regex:(c,e)=>T.string().regex(c,e),ip:()=>T.string().refine(c=>{let e=c.split(".");return e.length!==4?!1:e.every(t=>{let s=Number(t);return Number.isInteger(s)&&s>=0&&s<=255})},{message:"Must be a valid IP address"}),json:()=>T.string().refine(c=>{try{return JSON.parse(c),!0}catch{return!1}},{message:"Must be valid JSON"})}});var $n={};C($n,{FormAuthorizationError:()=>de,FormRequest:()=>Ne,FormValidationError:()=>ue});var Ne,ue,de,Ks=f(()=>{"use strict";Ne=class{authorize(e){return!0}messages(){return{}}attributes(){return{}}passedValidation(e){return e}failedValidation(e){throw new ue(e)}failedAuthorization(){throw new de}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},o=t.rules().safeParse(i);if(!o.success){let a={},l=t.messages(),u=t.attributes();for(let d of o.error.issues){let h=d.path.join("."),g=u[h]??h;a[g]||(a[g]=[]);let y=`${h}.${d.code}`,x=l[y]??l[h];a[g].push(x??d.message)}t.failedValidation(a)}return t.passedValidation(o.data)}},ue=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"}})}},de=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 kn,writeFile as Ko,unlink as Jo,mkdir as De,readdir as Js,stat as An,copyFile as zo,rename as Vo}from"fs/promises";import{existsSync as Qo}from"fs";import{join as Go,dirname as it}from"path";var zs,ot,Vs,Nn,Dn=f(()=>{"use strict";E();zs=class{constructor(e){this.config=e;if(!e.root)throw new Error('Local disk requires a "root" path.')}resolve(e){return Go(this.config.root,e)}async get(e){return kn(this.resolve(e))}async getText(e){return kn(this.resolve(e),"utf-8")}async put(e,t){let s=this.resolve(e);await De(it(s),{recursive:!0}),await Ko(s,t)}async append(e,t){let{appendFile:s}=await import("fs/promises"),r=this.resolve(e);await De(it(r),{recursive:!0}),await s(r,t)}async exists(e){return Qo(this.resolve(e))}async delete(e){try{return await Jo(this.resolve(e)),!0}catch{return!1}}async copy(e,t){let s=this.resolve(t);await De(it(s),{recursive:!0}),await zo(this.resolve(e),s)}async move(e,t){let s=this.resolve(t);await De(it(s),{recursive:!0}),await Vo(this.resolve(e),s)}async files(e=""){let t=this.resolve(e);try{return(await Js(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 Js(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 Js(t,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>e?`${e}/${r.name}`:r.name)}catch{return[]}}async makeDirectory(e){await De(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 An(this.resolve(e))).size}async lastModified(e){return(await An(this.resolve(e))).mtime}url(e){return`${this.config.urlPrefix??""}/${e}`}},ot=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 o=this.config.prefix;return o?n.slice(o.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 o=await s.send(new t.ListObjectsV2Command({Bucket:this.config.bucket,Prefix:r,ContinuationToken:n}));for(let a of o.Contents??[]){let l=this.config.prefix,u=l?a.Key.slice(l.length+1):a.Key;u&&i.push(u)}n=o.IsTruncated?o.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 o=this.config.prefix;return(o?n.Prefix.slice(o.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}))}}},Vs=class{config=null;disks=new Map;configure(e){this.config=e}disk(e){let t=e??this.config?.default??"local";if(this.disks.has(t))return this.disks.get(t);if(!this.config)throw new Error("Storage not configured. Call Storage.configure() first.");let s=this.config.disks[t];if(!s)throw new Error(`Storage disk "${t}" is not defined.`);let r=this.createDisk(s);return this.disks.set(t,r),r}async get(e){return this.disk().get(e)}async getText(e){return this.disk().getText(e)}async put(e,t){return this.disk().put(e,t)}async append(e,t){return this.disk().append(e,t)}async exists(e){return this.disk().exists(e)}async delete(e){return this.disk().delete(e)}async copy(e,t){return this.disk().copy(e,t)}async move(e,t){return this.disk().move(e,t)}async files(e){return this.disk().files(e)}async allFiles(e){return this.disk().allFiles(e)}async directories(e){return this.disk().directories(e)}async makeDirectory(e){return this.disk().makeDirectory(e)}async deleteDirectory(e){return this.disk().deleteDirectory(e)}async size(e){return this.disk().size(e)}async lastModified(e){return this.disk().lastModified(e)}url(e){return this.disk().url(e)}createDisk(e){switch(e.driver){case"local":return new zs(e);case"s3":return new ot(e);default:throw new Error(`Unknown storage driver: ${e.driver}`)}}s3Disk(e){let t=this.disk(e);if(!(t instanceof ot))throw new Error(`Disk "${e??this.config?.default}" is not an S3 disk.`);return t}},Nn=w("svelar.storage",()=>new Vs)});import{readFile as Yo,writeFile as Xo,unlink as Mn,mkdir as On}from"fs/promises";import{join as Zo,dirname as ea}from"path";import{createHash as ta}from"crypto";var Qs,Gs,Ys,Xs,_n,Ln=f(()=>{"use strict";E();Qs=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)}},Gs=class{basePath;constructor(e){this.basePath=e.path??"storage/cache"}filePath(e){let t=ta("md5").update(e).digest("hex");return Zo(this.basePath,t.slice(0,2),t)}async get(e){let t=this.filePath(e);try{let s=await Yo(t,"utf-8"),r=JSON.parse(s);return r.expiresAt&&Date.now()>r.expiresAt?(await Mn(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 On(ea(r),{recursive:!0}),await Xo(r,JSON.stringify(i))}async forget(e){try{return await Mn(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 On(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)}},Ys=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}},Xs=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 Qs;case"file":return new Gs(e);case"null":return new Ys;case"redis":throw new Error("Redis cache requires ioredis. Install: npm install ioredis");default:throw new Error(`Unknown cache driver: ${e.driver}`)}}},_n=w("svelar.cache",()=>new Xs)});var at,Zs,er,tr,In,jn=f(()=>{"use strict";E();at=class{},Zs=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(()=>(Ge(),$s));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)}}},er=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(()=>(b(),v));await r.raw(`INSERT INTO ${this.table} (id, notifiable_id, type, data, read_at, created_at)
140
+ VALUES (?, ?, ?, ?, NULL, ?)`,[crypto.randomUUID(),e.getAttribute("id"),s.type,JSON.stringify(s.data),new Date().toISOString()])}catch(r){console.error("[Notifications] Failed to store database notification:",r)}}},tr=class{channels=new Map;constructor(){this.channels.set("mail",new Zs),this.channels.set("database",new er)}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 o=this.channels.get(n);if(o)try{await o.send(r,t)}catch(a){console.error(`[Notifications] Channel "${n}" failed:`,a)}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)}}},In=w("svelar.notifier",()=>new tr)});function sr(c){return c.startsWith("private-")?"private":c.startsWith("presence-")?"presence":"public"}var rr,ct,nr,ir,qn,Un=f(()=>{"use strict";E();rr=class{subscribers=[];name;type;constructor(e){this.name=e,this.type=sr(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 o=`event: connected
141
+ data: ${JSON.stringify(n)}
142
+ id: ${Date.now()}
143
+
144
+ `;i.enqueue(new TextEncoder().encode(o));let a={controller:i,userId:e,userInfo:t};s.subscribers.push(a),s.type==="presence"&&e!==void 0&&s.sendInternal("member:joined",{id:e,...t},a)},cancel(){let i=s.subscribers.findIndex(o=>o.controller===this._controller),n=s.subscribers.length;s.subscribers=s.subscribers.filter(o=>{try{return o.controller.enqueue(new TextEncoder().encode(`:
145
+
146
+ `)),!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}
147
+ data: ${JSON.stringify(t)}
148
+ id: ${Date.now()}
149
+
150
+ `,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}
151
+ data: ${JSON.stringify(t)}
152
+ id: ${Date.now()}
153
+
154
+ `,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}
155
+ data: ${JSON.stringify(t)}
156
+ id: ${Date.now()}
157
+
158
+ `,i=new TextEncoder().encode(r);for(let n of this.subscribers)if(n.userId!==s)try{n.controller.enqueue(i)}catch{}}},ct=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(),o=await this.md5(i),a=["POST",`/apps/${this.config.appId}/events`,[`auth_key=${this.config.key}`,`auth_timestamp=${n}`,"auth_version=1.0",`body_md5=${o}`].join("&")].join(`
159
+ `),l=await this.hmacSha256(this.config.secret,a),u=this.config.useTLS!==!1?"https":"http",d=this.config.host??`api-${this.config.cluster??"mt1"}.pusher.com`,h=this.config.port??(this.config.useTLS!==!1?443:80),g=`${u}://${d}:${h}/apps/${this.config.appId}/events?auth_key=${this.config.key}&auth_timestamp=${n}&auth_version=1.0&body_md5=${o}&auth_signature=${l}`,y=await fetch(g,{method:"POST",headers:{"Content-Type":"application/json"},body:i});if(!y.ok){let x=await y.text();throw new Error(`Pusher API error (${y.status}): ${x}`)}}async authenticate(e,t,s){let r=`${e}:${t}`,i;s&&(i=JSON.stringify(s),r+=`:${i}`);let n=await this.hmacSha256(this.config.secret,r),o=`${this.config.key}:${n}`;return i?{auth:o,channel_data:i}:{auth:o}}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")}},nr=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)}},ir=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 ct(t))}channel(e,t){if(t){this.channelAuth.set(e,t);return}return this.sseChannels.has(e)||this.sseChannels.set(e,new rr(e)),this.sseChannels.get(e)}async authorize(e,t){if(sr(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=sr(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 nr(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 ct(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,a=>a==="{"||a==="}"?a:`\\${a}`).replace(/\\\{(\w+)\\\}/g,(a,l)=>(s.push(l),"([^.]+)")).replace(/\{(\w+)\}/g,(a,l)=>(s.push(l),"([^.]+)")),i=new RegExp(`^${r}$`),n=t.match(i);if(!n)return null;let o={};for(let a=0;a<s.length;a++)o[s[a]]=n[a+1];return o}},qn=w("svelar.broadcast",()=>new ir)});function lt(c,e,t){Hn&&Hn(c,e,{description:t})}async function Fn(c,e={}){let{csrfCookieName:t="XSRF-TOKEN",csrfHeaderName:s="X-CSRF-Token",showToast:r=!0,errorMessages:i={},...n}=e,o=(n.method||"GET").toUpperCase(),a=new Headers(n.headers);if(["POST","PUT","PATCH","DELETE"].includes(o)){let l=ar(t);l&&a.set(s,l)}n.body&&typeof n.body=="string"&&!a.has("Content-Type")&&a.set("Content-Type","application/json"),a.has("Accept")||a.set("Accept","application/json");try{let l=await fetch(c,{...n,headers:a});return!l.ok&&r&&await ra(l,{...sa,...i}),l}catch(l){throw r&&lt("error","Network Error","Unable to connect. Check your internet connection."),l}}async function ra(c,e){let t="";try{if((c.headers.get("content-type")??"").includes("application/json")){let n=await c.clone().json();if(t=n.message??"",c.status===422&&n.errors){let o=Object.entries(n.errors).map(([a,l])=>`${a}: ${l.join(", ")}`).slice(0,3).join(`
160
+ `);lt("warning",e[422]??"Validation Error",o);return}}}catch{}let s=t||e[c.status]||`Error ${c.status}`,r=c.status>=500?"error":c.status===429?"warning":"error";if(c.status===401){lt("warning",s,"Please sign in to continue.");return}lt(r,s)}function ar(c="XSRF-TOKEN"){if(typeof document>"u")return null;let e=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function Bn(c,e){if(!e)return c;let t=new URL(c,"http://localhost");for(let[s,r]of Object.entries(e))r!=null&&t.searchParams.set(s,String(r));return t.pathname+t.search}var sa,Hn,or,he,Zu,Wn=f(()=>{"use strict";sa={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."},Hn=null;or=class c{_baseUrl="";_headers={};_timeout=3e4;_retries=0;_retryDelay=1e3;_query={};constructor(e){e?.baseUrl&&(this._baseUrl=e.baseUrl),e?.headers&&(this._headers={...e.headers}),e?.timeout&&(this._timeout=e.timeout),e?.retries&&(this._retries=e.retries),e?.retryDelay&&(this._retryDelay=e.retryDelay)}clone(){let e=new c;return e._baseUrl=this._baseUrl,e._headers={...this._headers},e._timeout=this._timeout,e._retries=this._retries,e._retryDelay=this._retryDelay,e._query={...this._query},e}baseUrl(e){let t=this.clone();return t._baseUrl=e,t}withHeaders(e){let t=this.clone();return t._headers={...t._headers,...e},t}withToken(e,t="Bearer"){return this.withHeaders({Authorization:`${t} ${e}`})}withBasicAuth(e,t){let s=Buffer.from(`${e}:${t}`).toString("base64");return this.withHeaders({Authorization:`Basic ${s}`})}accept(e){return this.withHeaders({Accept:e})}contentType(e){return this.withHeaders({"Content-Type":e})}timeout(e){let t=this.clone();return t._timeout=e,t}retry(e,t=1e3){let s=this.clone();return s._retries=e,s._retryDelay=t,s}query(e){let t=this.clone();for(let[s,r]of Object.entries(e))r!=null&&(t._query[s]=String(r));return t}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async put(e,t){return this.request("PUT",e,t)}async patch(e,t){return this.request("PATCH",e,t)}async delete(e,t){return this.request("DELETE",e,t)}async request(e,t,s){let r=this.buildFullUrl(t),i={...this._headers},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 o=null,a=1+this._retries;for(let l=0;l<a;l++){l>0&&await new Promise(u=>setTimeout(u,this._retryDelay*l));try{let u=new AbortController,d=setTimeout(()=>u.abort(),this._timeout),h=await fetch(r,{method:e,headers:i,body:n,signal:u.signal});if(clearTimeout(d),!h.ok&&h.status<500&&l<a-1,!h.ok&&h.status>=500&&l<a-1){o=new he(`HTTP ${h.status}: ${h.statusText}`,h.status,await h.text());continue}let g=h.headers.get("content-type")??"",y;if(g.includes("application/json")?y=await h.json():y=await h.text(),!h.ok)throw new he(`HTTP ${h.status}: ${typeof y=="string"?y:JSON.stringify(y)}`,h.status,y);return{data:y,status:h.status,headers:h.headers,ok:!0}}catch(u){if(u instanceof he)throw u;if(o=u,u.name==="AbortError"&&(o=new he("Request timed out",0,null)),l>=a-1)break}}throw o??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}},he=class extends Error{constructor(t,s,r){super(t);this.status=s;this.body=r;this.name="HttpRequestError"}},Zu=new or});function Kn(c){let{paraglideMiddleware:e,getTextDirection:t=()=>"ltr",langPlaceholder:s="%lang%",dirPlaceholder:r="%dir%"}=c;return({event:i,resolve:n})=>e(i.request,({request:o,locale:a})=>(i.request=o,n(i,{transformPageChunk:({html:l})=>l.replace(s,a).replace(r,t(a))})))}function Jn(c){return e=>c.deLocalizeUrl(e.url).pathname}var zn=f(()=>{"use strict"});function Vn(c,e,t={}){return async s=>{let{superValidate:r,fail:i,message:n}=await import("sveltekit-superforms"),{zod:o}=await import("sveltekit-superforms/adapters"),a=await r(s,o(c));if(!a.valid)return i(400,{form:a});try{let l=await e(a.data,s);if(t.redirectTo){let{redirect:u}=await import("@sveltejs/kit");throw u(303,t.redirectTo)}return l??{form:a}}catch(l){if(l?.status>=300&&l?.status<400)throw l;return n(a,t.errorMessage||l.message||"An error occurred",{status:l.status||400})}}}async function Qn(c,e){let{superValidate:t}=await import("sveltekit-superforms"),{zod:s}=await import("sveltekit-superforms/adapters");return t(e??null,s(c))}async function Gn(c,e){let t=await c.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(()=>(Ks(),$n));throw new i(r.error.flatten().fieldErrors)}return r.data}var Yn=f(()=>{"use strict"});var Xn={};C(Xn,{Application:()=>He,AuthManager:()=>Ye,AuthenticateMiddleware:()=>ce,BelongsTo:()=>Q,BelongsToMany:()=>G,Broadcast:()=>qn,Cache:()=>_n,ColumnBuilder:()=>O,Connection:()=>m,Container:()=>U,Controller:()=>Ke,CorsMiddleware:()=>Fe,CsrfMiddleware:()=>Z,DatabaseSessionStore:()=>Je,ErrorHandler:()=>le,Event:()=>Y,EventDispatcher:()=>Te,FileSessionStore:()=>ze,ForbiddenError:()=>Se,FormAuthorizationError:()=>de,FormRequest:()=>Ne,FormValidationError:()=>ue,HasMany:()=>V,HasOne:()=>z,Hash:()=>bs,HttpError:()=>$,Job:()=>K,Log:()=>et,LoggingMiddleware:()=>Be,Mailable:()=>$e,Mailer:()=>Rs,MemorySessionStore:()=>H,Middleware:()=>S,MiddlewareStack:()=>L,Migration:()=>me,Migrator:()=>ge,Model:()=>qe,ModelNotFoundError:()=>rt,NotFoundError:()=>xe,Notification:()=>at,Notifier:()=>In,OriginMiddleware:()=>ee,QueryBuilder:()=>A,Queue:()=>ls,RateLimitMiddleware:()=>X,RedisSessionStore:()=>Ve,RequireAuthMiddleware:()=>Xe,Schema:()=>_,Seeder:()=>Ue,ServiceProvider:()=>ve,Session:()=>ne,SessionMiddleware:()=>ie,SignatureMiddleware:()=>We,Storage:()=>Nn,TableBuilder:()=>B,ThrottleMiddleware:()=>te,UnauthorizedError:()=>Ee,ValidationError:()=>I,abort:()=>nt,abortIf:()=>bn,abortUnless:()=>vn,apiFetch:()=>Fn,buildUrl:()=>Bn,config:()=>En,container:()=>an,createFormAction:()=>Vn,createI18nHandle:()=>Kn,createReroute:()=>Jn,createSvelarApp:()=>Tn,createSvelarHooks:()=>Hs,env:()=>xn,getCsrfToken:()=>ar,loadForm:()=>Qn,resource:()=>ln,rules:()=>Cn,schema:()=>Jr,sequence:()=>Fs,signJwt:()=>ks,validate:()=>Pn,validateForm:()=>Gn,verifyJwt:()=>As,z:()=>T});var Zn=f(()=>{"use strict";nn();hs();ps();b();Gt();Yt();on();gs();ms();cn();se();un();Bs();Sn();Rn();Ns();oe();fs();Us();je();Ks();Dn();Is();Ln();us();Ge();jn();Un();Wn();zn();Yn();Bs()});var ur={};C(ur,{PluginRegistry:()=>ut});var lr,ut,dt=f(()=>{"use strict";E();lr=class{plugins=new Map;enabledPlugins=new Set;async discover(){let{join:e}=await import("path"),{existsSync:t,readdirSync:s}=await import("fs"),{readFile:r}=await import("fs/promises"),i=[],n=e(process.cwd(),"node_modules");if(!t(n))return i;try{let o=s(n,{withFileTypes:!0});for(let a of o){if(!a.isDirectory())continue;let l=a.name;if(l.startsWith("."))continue;let u=l.startsWith("svelar-");if(!u)continue;let d=e(n,l,"package.json");if(t(d))try{let h=await r(d,"utf-8"),g=JSON.parse(h),y=g.keywords?.includes("svelar-plugin");if(!u&&!y)continue;let x={name:g.name||l,version:g.version||"0.0.0",description:g.description||"",packageName:l,installed:!0,enabled:!1,hasConfig:!!g.svelar?.config,hasMigrations:!!g.svelar?.migrations};i.push(x),this.plugins.set(x.name,x)}catch{}}}catch{}return i}enable(e){let t=this.plugins.get(e);if(!t)throw new Error(`Plugin "${e}" not found in registry.`);this.enabledPlugins.add(e),t.enabled=!0}disable(e){this.enabledPlugins.delete(e);let t=this.plugins.get(e);t&&(t.enabled=!1)}isEnabled(e){return this.enabledPlugins.has(e)}list(){return[...this.plugins.values()]}listEnabled(){return[...this.plugins.values()].filter(e=>this.enabledPlugins.has(e.name))}get(e){return this.plugins.get(e)}register(e){this.plugins.set(e.name,e)}},ut=w("svelar.pluginRegistry",()=>new lr)});var ei={};C(ei,{PluginPublisher:()=>pr});var hr,pr,mr=f(()=>{"use strict";E();hr=class{async publish(e,t){let{mkdir:s,copyFile:r}=await import("fs/promises"),{join:i,dirname:n}=await import("path"),{existsSync:o}=await import("fs"),a={configs:[],migrations:[],assets:[]},l=e.publishables?.()||{};for(let[u,d]of Object.entries(l))for(let h of d){if(t?.only&&h.type!==t.only)continue;let g=i(process.cwd(),h.dest),y=n(g);if(!(o(g)&&!t?.force))try{await s(y,{recursive:!0}),await r(h.source,g),h.type==="config"?a.configs.push(g):h.type==="migration"?a.migrations.push(g):h.type==="asset"&&a.assets.push(g)}catch(x){console.warn(`Failed to publish ${h.source} to ${g}:`,x)}}return a}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 o=Me("path").join(process.cwd(),n.dest);n.type==="config"?t.configs.push(o):n.type==="migration"?t.migrations.push(o):n.type==="asset"&&t.assets.push(o)}return t}},pr=w("svelar.pluginPublisher",()=>new hr)});var ti={};C(ti,{PluginInstaller:()=>na});var fr,na,si=f(()=>{"use strict";E();dt();mr();fr=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:o}=await import("fs");try{await this.runNpmInstall(e);let a=ut,l=await a.discover(),u;for(let h of l)if(h.packageName===e||h.name===e){u=h;break}if(!u)return{success:!1,pluginName:e,version:"0.0.0",published:null,error:`Plugin not found after installation. Make sure ${e} is a valid Svelar plugin.`};a.enable(u.name);let d=null;if(t?.publish!==!1)try{let h=await this.loadPluginClass(u.packageName);h&&(d=await pr.publish(new h))}catch(h){console.warn("Failed to publish plugin assets:",h)}return{success:!0,pluginName:u.name,version:u.version,published:d}}catch(a){return{success:!1,pluginName:e,version:"0.0.0",published:null,error:a?.message??String(a)}}}async uninstall(e){try{let t=ut,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}=Me("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}=Me("child_process"),i=r("npm",["uninstall",e],{cwd:process.cwd(),stdio:"inherit"});i.on("close",n=>{n===0?t():s(new Error(`npm uninstall exited with code ${n}`))}),i.on("error",s)})}async loadPluginClass(e){try{let t=await import(e);return t.default||Object.values(t)[0]}catch{return null}}},na=w("svelar.pluginInstaller",()=>new fr)});var ft=class{commands=new Map;version;constructor(e="0.1.0"){this.version=e}register(e){let t=new e;return this.commands.set(t.name,t),this}add(e){return this.commands.set(e.name,e),this}async run(e=process.argv.slice(2)){let[t,...s]=e;if(!t||t==="--help"||t==="-h"){this.showHelp();return}if(t==="--version"||t==="-v"){console.log(`Svelar v${this.version}`);return}let r=this.commands.get(t);r||(console.error(`\x1B[31mUnknown command:\x1B[0m ${t}`),console.log("Run \x1B[36msvelar --help\x1B[0m for available commands."),process.exit(1));let{args:i,flags:n}=this.parseArgs(s,r);try{await r.handle(i,n)}catch(o){let a=o instanceof Error?o.message:String(o);console.error(`\x1B[31mError:\x1B[0m ${a}`),o?.stack&&console.error(o.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 o=n.slice(2),a=o.indexOf("=");if(a!==-1){let d=o.slice(0,a);r[d]=o.slice(a+1);continue}let l=o;t.flags.find(d=>d.name===l)?.type==="boolean"?r[l]=!0:i+1<e.length&&!e[i+1].startsWith("-")?r[l]=e[++i]:r[l]=!0}else if(n.startsWith("-")&&n.length===2){let o=n.slice(1),a=t.flags.find(l=>l.alias===o);a&&(a.type==="boolean"?r[a.name]=!0:i+1<e.length&&(r[a.name]=e[++i]))}else s.push(n)}return{args:s,flags:r}}showHelp(){console.log(`
161
+ \x1B[36m ____ _
162
+ / ___|_ _____| | __ _ _ __
163
+ \\___ \\ \\ / / _ \\ |/ _\` | '__|
164
+ ___) \\ V / __/ | (_| | |
165
+ |____/ \\_/ \\___|_|\\__,_|_|\x1B[0m v${this.version}
166
+
167
+ \x1B[33mUsage:\x1B[0m
168
+ svelar <command> [arguments] [options]
169
+
170
+ \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(`
171
+ \x1B[32m${t}\x1B[0m`);for(let r of s){let i=30-r.name.length;console.log(` \x1B[36m${r.name}\x1B[0m${" ".repeat(Math.max(1,i))}${r.description}`)}}console.log()}};var p=class{arguments=[];flags=[];async bootstrap(){let{join:e}=await import("path"),{existsSync:t,readFileSync:s}=await import("fs"),{Connection:r}=await Promise.resolve().then(()=>(b(),v)),i=process.cwd();try{r.getDriver();return}catch{}let n=e(i,"svelar.database.json");if(t(n))try{let l=s(n,"utf-8"),u=JSON.parse(l);r.configure(u),this.info("Database configured from svelar.database.json");return}catch(l){this.warn(`Failed to parse svelar.database.json: ${String(l?.message??l)}`)}let o=process.env.DB_DRIVER??"sqlite",a=process.env.DB_PATH??"database.db";r.configure({default:o,connections:{[o]:{driver:o,filename:a,host:process.env.DB_HOST,port:process.env.DB_PORT?parseInt(process.env.DB_PORT):void 0,database:process.env.DB_NAME,user:process.env.DB_USER,password:process.env.DB_PASSWORD}}}),this.info(`Using ${o} database${o==="sqlite"?`: ${a}`:""}`)}log(e){console.log(e)}info(e){console.log(`\x1B[34mINFO\x1B[0m ${e}`)}success(e){console.log(`\x1B[32m\u2713\x1B[0m ${e}`)}warn(e){console.log(`\x1B[33mWARN\x1B[0m ${e}`)}error(e){console.error(`\x1B[31mERROR\x1B[0m ${e}`)}table(e,t){let s=e.map((n,o)=>Math.max(n.length,...t.map(a=>(a[o]??"").length))),r=s.map(n=>"\u2500".repeat(n+2)).join("\u253C"),i=n=>n.map((o,a)=>` ${(o??"").padEnd(s[a])} `).join("\u2502");console.log(i(e)),console.log(r);for(let n of t)console.log(i(n))}newLine(){console.log()}};import{writeFileSync as wt,mkdirSync as bt,existsSync as ci}from"fs";import{join as F}from"path";var vt=class extends p{name="make:model";description="Create a new model class";arguments=["name"];flags=[{name:"migration",alias:"m",description:"Also create a migration",type:"boolean"},{name:"controller",alias:"c",description:"Also create a controller",type:"boolean"},{name:"resource",alias:"r",description:"Create a resource controller",type:"boolean"},{name:"all",alias:"a",description:"Create model, migration, and controller",type:"boolean"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a model name.");return}let r=this.toSnakeCase(this.pluralize(s)),i=t.module||this.toSnakeCase(this.pluralize(s));t.module||this.warn(`No --module specified. Using "${i}" as module. Consider: --module ${i}`);let n=F(process.cwd(),"src","lib","modules",i);bt(n,{recursive:!0});let o=F(n,`${s}.ts`);if(ci(o)){this.warn(`Model ${s} already exists at ${o}`);return}let a=`import { Model } from '@beeblock/svelar/orm';
172
+
173
+ export class ${s} extends Model {
174
+ static table = '${r}';
175
+ static timestamps = true;
176
+ static fillable = []; // Add fillable columns here
177
+
178
+ // Declare your typed columns
179
+ declare id: number;
180
+ // declare name: string;
181
+ // declare email: string;
182
+
183
+ // Define relationships
184
+ // posts() {
185
+ // return this.hasMany(Post, 'user_id');
186
+ // }
187
+ }
188
+ `;if(wt(o,a),this.success(`Model created: src/lib/modules/${i}/${s}.ts`),t.migration||t.all){let u=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_create_${r}_table`,d=F(process.cwd(),"src","lib","database","migrations");bt(d,{recursive:!0});let h=`import { Migration } from '@beeblock/svelar/database';
189
+
190
+ export default class Create${s}sTable extends Migration {
191
+ async up() {
192
+ await this.schema.createTable('${r}', (table) => {
193
+ table.increments('id');
194
+ // Add your columns here
195
+ // table.string('name');
196
+ // table.string('email').unique();
197
+ table.timestamps();
198
+ });
199
+ }
200
+
201
+ async down() {
202
+ await this.schema.dropTable('${r}');
203
+ }
204
+ }
205
+ `;wt(F(d,`${u}.ts`),h),this.success(`Migration created: src/lib/database/migrations/${u}.ts`)}if(t.controller||t.resource||t.all){let l=`${s}Controller`,u=F(process.cwd(),"src","lib","modules",i);bt(u,{recursive:!0});let h=t.resource||t.all?this.generateResourceController(s,l):this.generateBasicController(s,l);wt(F(u,`${l}.ts`),h),this.success(`Controller created: src/lib/modules/${i}/${l}.ts`)}}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
206
+ import { z } from '@beeblock/svelar/validation';
207
+ import { ${e} } from './${e}.js';
208
+
209
+ export class ${t} extends Controller {
210
+ /** GET /api/${this.toSnakeCase(this.pluralize(e))} */
211
+ async index(event: RequestEvent) {
212
+ const ${this.pluralize(e.toLowerCase())} = await ${e}.all();
213
+ return this.json(${this.pluralize(e.toLowerCase())});
214
+ }
215
+
216
+ /** POST /api/${this.toSnakeCase(this.pluralize(e))} */
217
+ async store(event: RequestEvent) {
218
+ const data = await this.validate(event, z.object({
219
+ // Define validation rules
220
+ }));
221
+ const ${e.toLowerCase()} = await ${e}.create(data);
222
+ return this.created(${e.toLowerCase()});
223
+ }
224
+
225
+ /** GET /api/${this.toSnakeCase(this.pluralize(e))}/[id] */
226
+ async show(event: RequestEvent) {
227
+ const ${e.toLowerCase()} = await ${e}.findOrFail(event.params.id);
228
+ return this.json(${e.toLowerCase()});
229
+ }
230
+
231
+ /** PUT /api/${this.toSnakeCase(this.pluralize(e))}/[id] */
232
+ async update(event: RequestEvent) {
233
+ const ${e.toLowerCase()} = await ${e}.findOrFail(event.params.id);
234
+ const data = await this.validate(event, z.object({
235
+ // Define validation rules
236
+ }));
237
+ await ${e.toLowerCase()}.update(data);
238
+ return this.json(${e.toLowerCase()});
239
+ }
240
+
241
+ /** DELETE /api/${this.toSnakeCase(this.pluralize(e))}/[id] */
242
+ async destroy(event: RequestEvent) {
243
+ const ${e.toLowerCase()} = await ${e}.findOrFail(event.params.id);
244
+ await ${e.toLowerCase()}.delete();
245
+ return this.noContent();
246
+ }
247
+ }
248
+ `}generateBasicController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
249
+ import { ${e} } from './${e}.js';
250
+
251
+ export class ${t} extends Controller {
252
+ async index(event: RequestEvent) {
253
+ const items = await ${e}.all();
254
+ return this.json(items);
255
+ }
256
+ }
257
+ `}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 li,mkdirSync as ui}from"fs";import{join as Tr}from"path";var Tt=class extends p{name="make:migration";description="Create a new migration file";arguments=["name"];flags=[{name:"create",description:"Table to create",type:"string"},{name:"table",description:"Table to modify",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a migration name (e.g. create_users_table).");return}let r=Tr(process.cwd(),"src","lib","database","migrations");ui(r,{recursive:!0});let n=`${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}_${s}`,o=this.toPascalCase(s),a=t.create??this.detectTableName(s,"create"),l=t.table??this.detectTableName(s,"add"),u;a?u=`import { Migration } from '@beeblock/svelar/database';
258
+
259
+ export default class ${o} extends Migration {
260
+ async up() {
261
+ await this.schema.createTable('${a}', (table) => {
262
+ table.increments('id');
263
+ // Add your columns here
264
+ table.timestamps();
265
+ });
266
+ }
267
+
268
+ async down() {
269
+ await this.schema.dropTable('${a}');
270
+ }
271
+ }
272
+ `:l?u=`import { Migration } from '@beeblock/svelar/database';
273
+
274
+ export default class ${o} extends Migration {
275
+ async up() {
276
+ await this.schema.addColumn('${l}', (table) => {
277
+ // Add new columns here
278
+ // table.string('new_column');
279
+ });
280
+ }
281
+
282
+ async down() {
283
+ await this.schema.dropColumn('${l}', 'new_column');
284
+ }
285
+ }
286
+ `:u=`import { Migration } from '@beeblock/svelar/database';
287
+
288
+ export default class ${o} extends Migration {
289
+ async up() {
290
+ // Write your migration here
291
+ }
292
+
293
+ async down() {
294
+ // Reverse the migration
295
+ }
296
+ }
297
+ `,li(Tr(r,`${n}.ts`),u),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 di,mkdirSync as hi,existsSync as pi}from"fs";import{join as xr}from"path";var xt=class extends p{name="make:controller";description="Create a new controller class";arguments=["name"];flags=[{name:"resource",alias:"r",description:"Create a resource controller with CRUD methods",type:"boolean"},{name:"model",alias:"m",description:"Model name for resource controller",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a controller name.");return}let r=s.endsWith("Controller")?s:`${s}Controller`,i=r.replace(/Controller$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=xr(process.cwd(),"src","lib","modules",n);hi(o,{recursive:!0});let a=xr(o,`${r}.ts`);if(pi(a)){this.warn(`Controller ${r} already exists.`);return}let l=t.resource?this.generateResourceController(r,t.model):this.generateBasicController(r);di(a,l),this.success(`Controller created: src/lib/modules/${n}/${r}.ts`)}generateResourceController(e,t){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
298
+ import { z } from '@beeblock/svelar/validation';
299
+ ${t?`import { ${t} } from './${t}.js';
300
+ `:""}
301
+ export class ${e} extends Controller {
302
+ async index(event: RequestEvent) {
303
+ // List all resources
304
+ return this.json([]);
305
+ }
306
+
307
+ async store(event: RequestEvent) {
308
+ const data = await this.validate(event, z.object({
309
+ // Define validation rules
310
+ }));
311
+ // Create resource
312
+ return this.created(data);
313
+ }
314
+
315
+ async show(event: RequestEvent) {
316
+ const { id } = event.params;
317
+ // Find and return resource
318
+ return this.json({ id });
319
+ }
320
+
321
+ async update(event: RequestEvent) {
322
+ const { id } = event.params;
323
+ const data = await this.validate(event, z.object({
324
+ // Define validation rules
325
+ }));
326
+ // Update resource
327
+ return this.json({ id, ...data });
328
+ }
329
+
330
+ async destroy(event: RequestEvent) {
331
+ const { id } = event.params;
332
+ // Delete resource
333
+ return this.noContent();
334
+ }
335
+ }
336
+ `}generateBasicController(e){return`import { Controller, type RequestEvent } from '@beeblock/svelar/routing';
337
+
338
+ export class ${e} extends Controller {
339
+ async index(event: RequestEvent) {
340
+ return this.json({ message: 'Hello from ${e}' });
341
+ }
342
+ }
343
+ `}};import{writeFileSync as mi,mkdirSync as gi,existsSync as fi}from"fs";import{join as Er}from"path";var Et=class extends p{name="make:middleware";description="Create a new middleware class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a middleware name.");return}let s=t.endsWith("Middleware")?t:`${t}Middleware`,r=Er(process.cwd(),"src","lib","shared","middleware");gi(r,{recursive:!0});let i=Er(r,`${s}.ts`);if(fi(i)){this.warn(`Middleware ${s} already exists.`);return}let n=`import { Middleware, type MiddlewareContext, type NextFunction } from '@beeblock/svelar/middleware';
344
+
345
+ export class ${s} extends Middleware {
346
+ async handle(ctx: MiddlewareContext, next: NextFunction): Promise<Response | void> {
347
+ // Before request
348
+ // Example: const token = ctx.event.request.headers.get('authorization');
349
+
350
+ const response = await next();
351
+
352
+ // After request (optional)
353
+ return response;
354
+ }
355
+ }
356
+ `;mi(i,n),this.success(`Middleware created: src/lib/shared/middleware/${s}.ts`)}};import{writeFileSync as yi,mkdirSync as wi,existsSync as bi}from"fs";import{join as Sr}from"path";var St=class extends p{name="make:provider";description="Create a new service provider class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a provider name.");return}let s=t.endsWith("ServiceProvider")?t:`${t}ServiceProvider`,r=Sr(process.cwd(),"src","lib","shared","providers");wi(r,{recursive:!0});let i=Sr(r,`${s}.ts`);if(bi(i)){this.warn(`Provider ${s} already exists.`);return}let n=`import { ServiceProvider } from '@beeblock/svelar/container';
357
+ import type { Container } from '@beeblock/svelar/container';
358
+
359
+ export class ${s} extends ServiceProvider {
360
+ /**
361
+ * Register services in the container.
362
+ * Called before boot().
363
+ */
364
+ register(): void {
365
+ // this.app.singleton('myService', (container) => {
366
+ // return new MyService();
367
+ // });
368
+ }
369
+
370
+ /**
371
+ * Bootstrap services after all providers are registered.
372
+ */
373
+ boot(): void {
374
+ // Initialization logic here
375
+ }
376
+ }
377
+ `;yi(i,n),this.success(`Provider created: src/lib/shared/providers/${s}.ts`)}};import{writeFileSync as vi,mkdirSync as Ti,existsSync as xi}from"fs";import{join as Cr}from"path";var Ct=class extends p{name="make:seeder";description="Create a new database seeder class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a seeder name.");return}let s=t.endsWith("Seeder")?t:`${t}Seeder`,r=Cr(process.cwd(),"src","lib","database","seeders");Ti(r,{recursive:!0});let i=Cr(r,`${s}.ts`);if(xi(i)){this.warn(`Seeder ${s} already exists.`);return}let n=`import { Seeder } from '@beeblock/svelar/database';
378
+
379
+ export class ${s} extends Seeder {
380
+ async run(): Promise<void> {
381
+ // Seed your database here
382
+ // Example:
383
+ // await User.create({ name: 'Admin', email: 'admin@example.com' });
384
+ }
385
+ }
386
+ `;vi(i,n),this.success(`Seeder created: src/lib/database/seeders/${s}.ts`)}};import{writeFileSync as Ei,mkdirSync as Si,existsSync as Ci}from"fs";import{join as Pr}from"path";var Pt=class extends p{name="make:service";description="Create a new service class";arguments=["name"];flags=[{name:"crud",description:"Create a CRUD service with model",type:"boolean"},{name:"model",alias:"m",description:"Model name for CRUD service",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a service name.");return}let r=s.endsWith("Service")?s:`${s}Service`,i=r.replace(/Service$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=Pr(process.cwd(),"src","lib","modules",n);Si(o,{recursive:!0});let a=Pr(o,`${r}.ts`);if(Ci(a)){this.warn(`Service ${r} already exists.`);return}let l=t.crud?this.generateCrudService(r,t.model):this.generateBasicService(r);Ei(a,l),this.success(`Service created: src/lib/modules/${n}/${r}.ts`)}generateCrudService(e,t){let s=t||"Model";return`import { CrudService, type ServiceResult } from '@beeblock/svelar/services';
387
+ import { ${s} } from './${s}.js';
388
+
389
+ export class ${e} extends CrudService<${s}> {
390
+ protected model = ${s};
391
+
392
+ // Override or add custom methods:
393
+ // async findByEmail(email: string): Promise<ServiceResult<${s}>> {
394
+ // const record = await ${s}.where('email', email).first();
395
+ // if (!record) return this.fail('Not found');
396
+ // return this.ok(record);
397
+ // }
398
+ }
399
+ `}generateBasicService(e){return`import { Service, type ServiceResult } from '@beeblock/svelar/services';
400
+
401
+ export class ${e} extends Service {
402
+ async execute(data: any): Promise<ServiceResult<any>> {
403
+ try {
404
+ // Implement your business logic here
405
+ return this.ok(data);
406
+ } catch (error: any) {
407
+ return this.fail(error.message);
408
+ }
409
+ }
410
+ }
411
+ `}};import{writeFileSync as Pi,mkdirSync as Ri,existsSync as $i}from"fs";import{join as Rr}from"path";var Rt=class extends p{name="make:repository";description="Create a new repository class";arguments=["name"];flags=[{name:"model",alias:"m",description:"Model name for the repository",type:"string"},{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a repository name.");return}let r=s.endsWith("Repository")?s:`${s}Repository`,i=r.replace(/Repository$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=Rr(process.cwd(),"src","lib","modules",n);Ri(o,{recursive:!0});let a=Rr(o,`${r}.ts`);if($i(a)){this.warn(`Repository ${r} already exists.`);return}let l=t.model||this.inferModelName(r),u=`import { Repository } from '@beeblock/svelar/repositories';
412
+ import { ${l} } from './${l}.js';
413
+
414
+ export class ${r} extends Repository<${l}> {
415
+ model() {
416
+ return ${l};
417
+ }
418
+
419
+ // Custom query methods:
420
+ // async findByEmail(email: string): Promise<${l} | null> {
421
+ // return ${l}.where('email', email).first();
422
+ // }
423
+ //
424
+ // async findActive(): Promise<${l}[]> {
425
+ // return ${l}.where('active', true).orderBy('name').get();
426
+ // }
427
+ }
428
+ `;Pi(a,u),this.success(`Repository created: src/lib/modules/${n}/${r}.ts`)}inferModelName(e){return e.replace("Repository","")||"Model"}};import{writeFileSync as ki,mkdirSync as Ai,existsSync as Ni}from"fs";import{join as $r}from"path";var $t=class extends p{name="make:action";description="Create a new action class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an action name.");return}let r=s.endsWith("Action")?s:`${s}Action`,i=r.replace(/Action$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=$r(process.cwd(),"src","lib","modules",n);Ai(o,{recursive:!0});let a=$r(o,`${r}.ts`);if(Ni(a)){this.warn(`Action ${r} already exists.`);return}let l=`import { Action } from '@beeblock/svelar/actions';
429
+
430
+ interface ${r}Input {
431
+ // Define input type
432
+ }
433
+
434
+ interface ${r}Output {
435
+ // Define output type
436
+ }
437
+
438
+ export class ${r} extends Action<${r}Input, ${r}Output> {
439
+ async handle(input: ${r}Input): Promise<${r}Output> {
440
+ // Implement your single-use business logic here
441
+ throw new Error('Not implemented');
442
+ }
443
+ }
444
+ `;ki(a,l),this.success(`Action created: src/lib/modules/${n}/${r}.ts`)}};import{writeFileSync as Di,mkdirSync as Mi,existsSync as Oi}from"fs";import{join as kr}from"path";var kt=class extends p{name="make:request";description="Create a new FormRequest validation class";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a request name.");return}let r=s.endsWith("Request")?s:`${s}Request`,i=r.replace(/Request$/,""),n=t.module||i.toLowerCase();t.module||this.warn(`No --module specified. Using "${n}" as module. Consider: --module ${n}`);let o=kr(process.cwd(),"src","lib","modules",n);Mi(o,{recursive:!0});let a=kr(o,`${r}.ts`);if(Oi(a)){this.warn(`Request ${r} already exists.`);return}let l=`import { FormRequest } from '@beeblock/svelar/routing';
445
+ import { z } from '@beeblock/svelar/validation';
446
+
447
+ export class ${r} extends FormRequest {
448
+ rules() {
449
+ return z.object({
450
+ // Define validation rules
451
+ // name: z.string().min(2).max(100),
452
+ // email: z.string().email(),
453
+ });
454
+ }
455
+
456
+ messages() {
457
+ return {
458
+ // Custom error messages (optional)
459
+ // 'name.too_small': 'Name must be at least 2 characters',
460
+ };
461
+ }
462
+
463
+ authorize(event: any): boolean {
464
+ // Return false to throw 403 Forbidden
465
+ return true;
466
+ }
467
+
468
+ passedValidation(data: any) {
469
+ // Transform data after validation (optional)
470
+ return data;
471
+ }
472
+ }
473
+ `;Di(a,l),this.success(`Request created: src/lib/modules/${n}/${r}.ts`)}};import{writeFileSync as _i,mkdirSync as Li,existsSync as Ii}from"fs";import{join as Ar}from"path";var At=class extends p{name="make:plugin";description="Create a new plugin class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a plugin name.");return}let s=t.endsWith("Plugin")?t:`${t}Plugin`,r=Ar(process.cwd(),"src","lib","shared","plugins");Li(r,{recursive:!0});let i=Ar(r,`${s}.ts`);if(Ii(i)){this.warn(`Plugin ${s} already exists.`);return}let n=s.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,""),o=`import { Plugin } from '@beeblock/svelar/plugins';
474
+ import type { Container } from '@beeblock/svelar/container';
475
+
476
+ export class ${s} extends Plugin {
477
+ readonly name = '${n}';
478
+ readonly version = '1.0.0';
479
+ description = '${s} for Svelar';
480
+
481
+ async register(app: Container): Promise<void> {
482
+ // Register services, configuration, etc.
483
+ // app.singleton('myService', () => new MyService());
484
+ }
485
+
486
+ async boot(app: Container): Promise<void> {
487
+ // Resolve dependencies and initialize
488
+ // const service = app.resolve('myService');
489
+ }
490
+
491
+ async shutdown(): Promise<void> {
492
+ // Clean up resources
493
+ }
494
+ }
495
+ `;_i(i,o),this.success(`Plugin created: src/lib/shared/plugins/${s}.ts`)}};import{writeFileSync as ji,mkdirSync as qi,existsSync as Ui}from"fs";import{join as Nr}from"path";var Nt=class extends p{name="make:task";description="Create a new scheduled task class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a task name.");return}let s=(t.endsWith("Task"),t),r=Nr(process.cwd(),"src","lib","shared","scheduler");qi(r,{recursive:!0});let i=Nr(r,`${s}.ts`);if(Ui(i)){this.warn(`Task ${s} already exists.`);return}let n=`import { ScheduledTask } from '@beeblock/svelar/scheduler';
496
+
497
+ export class ${s} extends ScheduledTask {
498
+ name = '${this.toKebabCase(s)}';
499
+
500
+ schedule() {
501
+ return this.daily(); // Run daily at midnight
502
+ // Other options:
503
+ // return this.everyMinute();
504
+ // return this.everyFiveMinutes();
505
+ // return this.everyMinutes(30);
506
+ // return this.hourly();
507
+ // return this.daily();
508
+ // return this.dailyAt('03:00');
509
+ // return this.weekly();
510
+ // return this.weeklyOn(1, '08:00'); // Monday at 8am
511
+ // return this.monthly();
512
+ // return this.cron('0 */6 * * *'); // Every 6 hours
513
+ }
514
+
515
+ async handle(): Promise<void> {
516
+ // Implement your scheduled task logic here
517
+ console.log('Running ${s}...');
518
+ }
519
+
520
+ onSuccess(): void {
521
+ // Called after successful execution (optional)
522
+ }
523
+
524
+ onFailure(error: Error): void {
525
+ console.error('${s} failed:', error.message);
526
+ }
527
+ }
528
+ `;ji(i,n),this.success(`Scheduled task created: src/lib/shared/scheduler/${s}.ts`)}toKebabCase(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase().replace(/^-/,"")}};import{writeFileSync as Hi,mkdirSync as Fi,existsSync as Bi}from"fs";import{join as Dr}from"path";var Dt=class extends p{name="make:job";description="Create a new queue job class";arguments=["name"];flags=[];async handle(e){let t=e[0];if(!t){this.error("Please provide a job name.");return}let s=(t.endsWith("Job"),t),r=Dr(process.cwd(),"src","lib","shared","jobs");Fi(r,{recursive:!0});let i=Dr(r,`${s}.ts`);if(Bi(i)){this.warn(`Job ${s} already exists.`);return}let n=`import { Job } from '@beeblock/svelar/queue';
529
+
530
+ export class ${s} extends Job {
531
+ maxAttempts = 3; // Retry up to 3 times
532
+ retryDelay = 60; // Wait 60 seconds between retries
533
+ queue = 'default'; // Queue name
534
+
535
+ constructor(private data: any) {
536
+ super();
537
+ }
538
+
539
+ async handle(): Promise<void> {
540
+ // Implement your job logic here
541
+ console.log('Processing ${s}...', this.data);
542
+ }
543
+
544
+ failed(error: Error): void {
545
+ console.error('${s} permanently failed:', error.message);
546
+ }
547
+
548
+ retrying(attempt: number): void {
549
+ console.log('${s} retrying, attempt', attempt);
550
+ }
551
+ }
552
+ `;Hi(i,n),this.success(`Job created: src/lib/shared/jobs/${s}.ts`)}};import{writeFileSync as Wi,mkdirSync as Ki,existsSync as Ji}from"fs";import{join as Mr}from"path";var Mt=class extends p{name="make:command";description="Create a new custom CLI command";arguments=["name"];flags=[{name:"command",description:'The terminal command name (e.g. "app:sync")',type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a command class name. Example: npx svelar make:command SyncUsers");return}let r=s.endsWith("Command")?s:`${s}Command`,i=Mr(process.cwd(),"src","lib","shared","commands");Ki(i,{recursive:!0});let n=Mr(i,`${r}.ts`);if(Ji(n)){this.warn(`Command ${r} already exists.`);return}let o=t.command??this.deriveCommandName(r),a=`import { Command } from '@beeblock/svelar/cli';
553
+
554
+ export class ${r} extends Command {
555
+ name = '${o}';
556
+ description = 'TODO: Describe your command';
557
+ arguments = ['name']; // Positional args your command accepts
558
+ flags = [
559
+ // { name: 'force', alias: 'f', description: 'Force the operation', type: 'boolean' as const },
560
+ // { name: 'limit', description: 'Limit results', type: 'string' as const, default: '10' },
561
+ ];
562
+
563
+ async handle(args: string[], flags: Record<string, any>): Promise<void> {
564
+ const name = args[0];
565
+
566
+ this.info('Running ${o}...');
567
+
568
+ // Your command logic here
569
+ // Use this.bootstrap() if you need database access
570
+ // await this.bootstrap();
571
+
572
+ this.success('Done!');
573
+ }
574
+ }
575
+ `;Wi(n,a),this.success(`Command created: src/lib/shared/commands/${r}.ts`),this.info(`Command name: ${o}`),this.newLine(),this.info("Your command will be auto-discovered. Run it with:"),this.log(` npx svelar ${o}`)}deriveCommandName(e){return`app:${e.replace(/Command$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}`}};import{writeFileSync as zi,mkdirSync as Vi,existsSync as Qi}from"fs";import{join as Or}from"path";var Ot=class extends p{name="make:config";description="Create a new config file";arguments=["name"];flags=[];templates={app:`import { env } from 'svelar/config';
576
+
577
+ export default {
578
+ name: env('APP_NAME', 'Svelar'),
579
+ env: env('APP_ENV', 'development'),
580
+ debug: env<boolean>('APP_DEBUG', false),
581
+ url: env('APP_URL', 'http://localhost:5173'),
582
+ key: env('APP_KEY', ''),
583
+ timezone: 'UTC',
584
+ locale: 'en',
585
+ };
586
+ `,database:`import { env } from 'svelar/config';
587
+
588
+ export default {
589
+ default: env('DB_DRIVER', 'sqlite'),
590
+
591
+ connections: {
592
+ sqlite: {
593
+ driver: 'sqlite' as const,
594
+ filename: env('DB_PATH', 'database.db'),
595
+ },
596
+
597
+ postgres: {
598
+ driver: 'postgresql' as const,
599
+ host: env('DB_HOST', 'localhost'),
600
+ port: env<number>('DB_PORT', 5432),
601
+ database: env('DB_NAME', 'svelar'),
602
+ user: env('DB_USER', 'postgres'),
603
+ password: env('DB_PASSWORD', ''),
604
+ },
605
+
606
+ mysql: {
607
+ driver: 'mysql2' as const,
608
+ host: env('DB_HOST', 'localhost'),
609
+ port: env<number>('DB_PORT', 3306),
610
+ database: env('DB_NAME', 'svelar'),
611
+ user: env('DB_USER', 'root'),
612
+ password: env('DB_PASSWORD', ''),
613
+ },
614
+ },
615
+
616
+ migrations: {
617
+ table: 'migrations',
618
+ path: 'src/lib/database/migrations',
619
+ },
620
+ };
621
+ `,auth:`import { env } from 'svelar/config';
622
+
623
+ export default {
624
+ guard: env('AUTH_GUARD', 'session'),
625
+
626
+ session: {
627
+ lifetime: 60 * 60 * 24, // 24 hours
628
+ cookie: 'svelar_session',
629
+ },
630
+
631
+ jwt: {
632
+ secret: env('JWT_SECRET', ''),
633
+ ttl: 60 * 60, // 1 hour
634
+ refreshTtl: 60 * 60 * 24 * 7, // 7 days
635
+ },
636
+
637
+ passwords: {
638
+ expire: 60, // Reset token expires in 60 minutes
639
+ },
640
+ };
641
+ `,mail:`import { env } from 'svelar/config';
642
+
643
+ export default {
644
+ driver: env('MAIL_DRIVER', 'log'),
645
+
646
+ from: {
647
+ address: env('MAIL_FROM', 'hello@example.com'),
648
+ name: env('MAIL_FROM_NAME', 'Svelar'),
649
+ },
650
+
651
+ smtp: {
652
+ host: env('MAIL_HOST', 'localhost'),
653
+ port: env<number>('MAIL_PORT', 587),
654
+ user: env('MAIL_USER', ''),
655
+ password: env('MAIL_PASSWORD', ''),
656
+ secure: env<boolean>('MAIL_SECURE', false),
657
+ },
658
+ };
659
+ `,cache:`import { env } from 'svelar/config';
660
+
661
+ export default {
662
+ default: env('CACHE_DRIVER', 'memory'),
663
+
664
+ stores: {
665
+ memory: {
666
+ driver: 'memory' as const,
667
+ },
668
+
669
+ database: {
670
+ driver: 'database' as const,
671
+ table: 'cache',
672
+ ttl: 60 * 60, // 1 hour default
673
+ },
674
+ },
675
+
676
+ prefix: 'svelar_cache_',
677
+ };
678
+ `,queue:`import { env } from 'svelar/config';
679
+
680
+ export default {
681
+ default: env('QUEUE_DRIVER', 'sync'),
682
+
683
+ connections: {
684
+ sync: {
685
+ driver: 'sync' as const,
686
+ },
687
+
688
+ memory: {
689
+ driver: 'memory' as const,
690
+ },
691
+
692
+ database: {
693
+ driver: 'database' as const,
694
+ table: 'svelar_jobs',
695
+ },
696
+
697
+ redis: {
698
+ driver: 'redis' as const,
699
+ host: env('REDIS_HOST', 'localhost'),
700
+ port: env<number>('REDIS_PORT', 6379),
701
+ password: env('REDIS_PASSWORD', ''),
702
+ db: env<number>('REDIS_DB', 0),
703
+ prefix: 'svelar',
704
+ defaultJobOptions: {
705
+ removeOnComplete: 100,
706
+ removeOnFail: 500,
707
+ },
708
+ },
709
+ },
710
+ };
711
+ `,storage:`import { env } from 'svelar/config';
712
+
713
+ export default {
714
+ default: env('STORAGE_DISK', 'local'),
715
+
716
+ disks: {
717
+ local: {
718
+ driver: 'local' as const,
719
+ root: 'storage',
720
+ },
721
+
722
+ public: {
723
+ driver: 'local' as const,
724
+ root: 'storage/public',
725
+ urlPrefix: '/storage',
726
+ },
727
+
728
+ s3: {
729
+ driver: 's3' as const,
730
+ bucket: env('S3_BUCKET', 'svelar'),
731
+ region: env('S3_REGION', 'us-east-1'),
732
+ endpoint: env('S3_ENDPOINT', 'http://localhost:9000'),
733
+ accessKeyId: env('S3_ACCESS_KEY', 'svelar'),
734
+ secretAccessKey: env('S3_SECRET_KEY', 'svelarsecret'),
735
+ forcePathStyle: true, // Required for RustFS/MinIO
736
+ },
737
+ },
738
+ };
739
+ `,broadcasting:`import { env } from 'svelar/config';
740
+
741
+ export default {
742
+ default: env('BROADCAST_DRIVER', 'pusher'),
743
+
744
+ drivers: {
745
+ pusher: {
746
+ driver: 'pusher' as const,
747
+ key: env('PUSHER_KEY', 'svelar-key'),
748
+ secret: env('PUSHER_SECRET', 'svelar-secret'),
749
+ appId: env('PUSHER_APP_ID', 'svelar-app'),
750
+ cluster: env('PUSHER_CLUSTER', 'mt1'),
751
+ // Soketi (included in docker-compose by default):
752
+ host: env('PUSHER_HOST', 'localhost'),
753
+ port: env<number>('PUSHER_PORT', 6001),
754
+ useTLS: env<boolean>('PUSHER_TLS', false),
755
+ },
756
+
757
+ sse: {
758
+ driver: 'sse' as const,
759
+ },
760
+
761
+ log: {
762
+ driver: 'log' as const,
763
+ },
764
+ },
765
+ };
766
+ `,logging:`import { env } from 'svelar/config';
767
+
768
+ export default {
769
+ default: env('LOG_CHANNEL', 'console'),
770
+
771
+ channels: {
772
+ console: {
773
+ driver: 'console' as const,
774
+ level: env('LOG_LEVEL', 'info'),
775
+ },
776
+
777
+ file: {
778
+ driver: 'file' as const,
779
+ path: 'storage/logs/svelar.log',
780
+ level: 'debug',
781
+ },
782
+ },
783
+ };
784
+ `};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=Or(process.cwd(),"config");Vi(s,{recursive:!0});let r=t.toLowerCase().replace(/\s+/g,"-"),i=Or(s,`${r}.ts`);if(Qi(i)){this.warn(`Config file config/${r}.ts already exists.`);return}let n=this.templates[r]??this.blankTemplate(r);zi(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';
785
+
786
+ export default {
787
+ // Add your ${e} configuration here
788
+ // Use env() to read from environment variables:
789
+ // env('MY_VAR', 'default')
790
+ // env<number>('MY_PORT', 3000)
791
+ // env<boolean>('MY_FLAG', false)
792
+ };
793
+ `}};import{writeFileSync as Gi,mkdirSync as Yi,existsSync as Xi}from"fs";import{join as _r}from"path";var _t=class extends p{name="make:channel";description="Create a new broadcast channel authorization";arguments=["name"];flags=[{name:"presence",alias:"p",description:"Create a presence channel",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a channel name. Example: npx svelar make:channel OrderChannel");return}let r=s.endsWith("Channel")?s:`${s}Channel`,i=_r(process.cwd(),"src","lib","shared","channels");Yi(i,{recursive:!0});let n=_r(i,`${r}.ts`);if(Xi(n)){this.warn(`Channel ${r} already exists.`);return}let o=r.replace(/Channel$/,""),a=o.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),l=o.charAt(0).toLowerCase()+o.slice(1)+"Id",u=t.presence,h=`${u?"presence":"private"}-${a}.{${l}}`,g=u?this.presenceTemplate(r,h,l):this.privateTemplate(r,h,l);Gi(n,g),this.success(`Channel created: src/lib/shared/channels/${r}.ts`),this.info(`Channel pattern: ${h}`),this.newLine(),this.info("Register it in src/app.ts or a service provider:"),this.log(` import { register${r} } from './lib/shared/channels/${r}.js';`),this.log(` register${r}();`)}privateTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
794
+
795
+ /**
796
+ * ${e}
797
+ *
798
+ * Authorization for the '${t}' private channel.
799
+ * Return true to allow access, false to deny.
800
+ */
801
+ export function register${e}(): void {
802
+ Broadcast.channel('${t}', async (user, { ${s} }) => {
803
+ // TODO: Check if the user is authorized to access this channel
804
+ // Example:
805
+ // const ${r.toLowerCase()} = await ${r}.findOrFail(${s});
806
+ // return ${r.toLowerCase()}.user_id === user.id;
807
+
808
+ return !!user;
809
+ });
810
+ }
811
+ `}presenceTemplate(e,t,s){let r=e.replace(/Channel$/,"");return`import { Broadcast } from '@beeblock/svelar/broadcasting';
812
+
813
+ /**
814
+ * ${e}
815
+ *
816
+ * Authorization for the '${t}' presence channel.
817
+ * Return false to deny, or an object with user info to share with other members.
818
+ */
819
+ export function register${e}(): void {
820
+ Broadcast.channel('${t}', async (user, { ${s} }) => {
821
+ // TODO: Check if the user is authorized to join this channel
822
+ // Example:
823
+ // const ${r.toLowerCase()} = await ${r}.findOrFail(${s});
824
+ // if (!${r.toLowerCase()}.hasMember(user.id)) return false;
825
+
826
+ if (!user) return false;
827
+
828
+ // Return user info visible to other presence members
829
+ return {
830
+ id: user.id,
831
+ name: user.name,
832
+ // avatar: user.avatar,
833
+ };
834
+ });
835
+ }
836
+ `}};import{writeFileSync as Zi,mkdirSync as eo,existsSync as to}from"fs";import{join as pe}from"path";var Lt=class extends p{name="make:docker";description="Scaffold Docker deployment files (Dockerfile, docker-compose.yml, PM2 config)";arguments=[];flags=[{name:"db",alias:"d",description:"Database driver: postgres, mysql, sqlite (default: postgres)",type:"string"},{name:"soketi",alias:"s",description:"Include Soketi WebSocket server",type:"boolean"},{name:"redis",alias:"r",description:"Include Redis service",type:"boolean"},{name:"gotenberg",alias:"g",description:"Include Gotenberg PDF service (default: true)",type:"boolean"},{name:"rustfs",description:"Include RustFS S3-compatible object storage (default: true)",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.db??"postgres",i=t.soketi??!0,n=t.redis??!0,o=t.gotenberg??!0,a=t.rustfs??!0,l=t.force??!1,u=["postgres","mysql","sqlite"];if(!u.includes(r)){this.error(`Unknown database driver: ${r}. Use one of: ${u.join(", ")}`);return}let d=[{path:pe(s,"Dockerfile"),content:this.dockerfileTemplate(),label:"Dockerfile"},{path:pe(s,"docker-compose.yml"),content:this.composeTemplate(r,i,n,o,a),label:"docker-compose.yml"},{path:pe(s,".dockerignore"),content:this.dockerignoreTemplate(),label:".dockerignore"},{path:pe(s,"ecosystem.config.cjs"),content:this.pm2Template(),label:"ecosystem.config.cjs"}],h=0,g=0;for(let y of d){if(to(y.path)&&!l){this.warn(`${y.label} already exists (use --force to overwrite)`),g++;continue}Zi(y.path,y.content),this.success(`Created ${y.label}`),h++}if(r!=="sqlite"){let y=pe(s,"docker");eo(y,{recursive:!0})}this.newLine(),h>0?this.info(`${h} file(s) created${g>0?`, ${g} 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
837
+ # Multi-stage build for a lean production image.
838
+
839
+ # Stage 1: Install dependencies & build
840
+ FROM node:20-alpine AS builder
841
+
842
+ WORKDIR /app
843
+
844
+ # Copy package files first for better layer caching
845
+ COPY package*.json ./
846
+ RUN npm ci
847
+
848
+ # Copy source and build
849
+ COPY . .
850
+ RUN npm run build
851
+
852
+ # Prune dev dependencies
853
+ RUN npm prune --production
854
+
855
+ # \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
856
+ # Stage 2: Production image
857
+ FROM node:20-alpine AS production
858
+
859
+ WORKDIR /app
860
+
861
+ # Install PM2 globally for process management
862
+ RUN npm install -g pm2
863
+
864
+ # Copy built app and production deps from builder
865
+ COPY --from=builder /app/build ./build
866
+ COPY --from=builder /app/node_modules ./node_modules
867
+ COPY --from=builder /app/package.json ./
868
+ COPY --from=builder /app/ecosystem.config.cjs ./
869
+
870
+ # Copy Svelar CLI + migrations/seeders (needed at runtime)
871
+ COPY --from=builder /app/src/lib/database ./src/lib/database
872
+
873
+ # Create storage directories
874
+ RUN mkdir -p storage/logs storage/public
875
+
876
+ # Environment
877
+ ENV NODE_ENV=production
878
+ ENV HOST=0.0.0.0
879
+ ENV PORT=3000
880
+
881
+ EXPOSE 3000
882
+
883
+ # Health check
884
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \\
885
+ CMD wget -qO- http://localhost:3000/api/health || exit 1
886
+
887
+ # Start with PM2
888
+ CMD ["pm2-runtime", "ecosystem.config.cjs"]
889
+ `}composeTemplate(e,t,s,r,i=!0){let n=[];n.push("# \u2500\u2500 Svelar Docker Compose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),n.push("# Generated by: npx svelar make:docker"),n.push("#"),n.push("# Usage:"),n.push("# docker compose up -d --build # Start all services"),n.push("# docker compose exec app npx svelar migrate # Run migrations"),n.push("# docker compose logs -f app # View app logs"),n.push("# docker compose down # Stop all services"),n.push(""),n.push("services:"),n.push(" app:"),n.push(" build: ."),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${APP_PORT:-3000}:3000"'),n.push(" env_file: .env"),n.push(" environment:"),n.push(" - NODE_ENV=production"),e==="postgres"?(n.push(" - DB_HOST=postgres"),n.push(" - DB_PORT=5432")):e==="mysql"&&(n.push(" - DB_HOST=mysql"),n.push(" - DB_PORT=3306")),s&&(n.push(" - REDIS_HOST=redis"),n.push(" - REDIS_PORT=6379"),n.push(" - QUEUE_DRIVER=redis")),t&&(n.push(" - PUSHER_HOST=soketi"),n.push(" - PUSHER_PORT=6001")),r&&n.push(" - GOTENBERG_URL=http://gotenberg:3000"),i&&(n.push(" - S3_ENDPOINT=http://rustfs:9000"),n.push(" - S3_ACCESS_KEY=${RUSTFS_ROOT_USER:-svelar}"),n.push(" - S3_SECRET_KEY=${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),n.push(" - S3_BUCKET=${S3_BUCKET:-svelar}"),n.push(" - S3_REGION=us-east-1"),n.push(" - STORAGE_DISK=s3"));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"),o.length>0){n.push(" depends_on:");for(let a of o)n.push(` ${a}:`),n.push(" condition: service_healthy")}return n.push(" volumes:"),n.push(" - app_storage:/app/storage"),e==="postgres"&&(n.push(""),n.push(" postgres:"),n.push(" image: postgres:16-alpine"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${DB_PORT:-5432}:5432"'),n.push(" environment:"),n.push(" POSTGRES_DB: ${DB_NAME:-svelar}"),n.push(" POSTGRES_USER: ${DB_USER:-svelar}"),n.push(" POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}"),n.push(" volumes:"),n.push(" - pgdata:/var/lib/postgresql/data"),n.push(" healthcheck:"),n.push(' test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-svelar}"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5")),e==="mysql"&&(n.push(""),n.push(" mysql:"),n.push(" image: mysql:8.0"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${DB_PORT:-3306}:3306"'),n.push(" environment:"),n.push(" MYSQL_DATABASE: ${DB_NAME:-svelar}"),n.push(" MYSQL_USER: ${DB_USER:-svelar}"),n.push(" MYSQL_PASSWORD: ${DB_PASSWORD:-secret}"),n.push(" MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}"),n.push(" volumes:"),n.push(" - mysqldata:/var/lib/mysql"),n.push(" healthcheck:"),n.push(' test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5")),s&&(n.push(""),n.push(" redis:"),n.push(" image: redis:7-alpine"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${REDIS_PORT:-6379}:6379"'),n.push(" volumes:"),n.push(" - redisdata:/data"),n.push(" healthcheck:"),n.push(' test: ["CMD", "redis-cli", "ping"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5")),t&&(n.push(""),n.push(" soketi:"),n.push(" image: quay.io/soketi/soketi:1.6-16-debian"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${SOKETI_PORT:-6001}:6001"'),n.push(' - "9601:9601" # Metrics'),n.push(" environment:"),n.push(' SOKETI_DEBUG: "${SOKETI_DEBUG:-0}"'),n.push(" SOKETI_DEFAULT_APP_ID: ${PUSHER_APP_ID}"),n.push(" SOKETI_DEFAULT_APP_KEY: ${PUSHER_KEY}"),n.push(" SOKETI_DEFAULT_APP_SECRET: ${PUSHER_SECRET}"),n.push(' SOKETI_DEFAULT_APP_MAX_CONNS: "${SOKETI_MAX_CONNS:-1000}"'),n.push(' SOKETI_DEFAULT_APP_ENABLE_CLIENT_MESSAGES: "true"'),n.push(' SOKETI_DEFAULT_APP_MAX_BACKEND_EVENTS_PER_SEC: "-1"'),n.push(" healthcheck:"),n.push(' test: ["CMD", "wget", "-qO-", "http://localhost:6001"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 3")),r&&(n.push(""),n.push(" gotenberg:"),n.push(" image: gotenberg/gotenberg:8"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${GOTENBERG_PORT:-3001}:3000"'),n.push(" environment:"),n.push(' CHROMIUM_DISABLE_JAVASCRIPT: "false"'),n.push(' CHROMIUM_ALLOW_LIST: "file:///tmp/.*"'),n.push(' API_TIMEOUT: "${GOTENBERG_TIMEOUT:-60s}"'),n.push(' LOG_LEVEL: "${GOTENBERG_LOG_LEVEL:-info}"'),n.push(" healthcheck:"),n.push(' test: ["CMD", "curl", "-f", "http://localhost:3000/health"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5")),i&&(n.push(""),n.push(" rustfs:"),n.push(" image: rustfs/rustfs:latest"),n.push(" restart: unless-stopped"),n.push(" ports:"),n.push(' - "${RUSTFS_API_PORT:-9000}:9000" # S3 API'),n.push(' - "${RUSTFS_CONSOLE_PORT:-9001}:9001" # Web Console'),n.push(" environment:"),n.push(" RUSTFS_ROOT_USER: ${RUSTFS_ROOT_USER:-svelar}"),n.push(" RUSTFS_ROOT_PASSWORD: ${RUSTFS_ROOT_PASSWORD:-svelarsecret}"),n.push(' command: server /data --console-address ":9001"'),n.push(" volumes:"),n.push(" - rustfs_data:/data"),n.push(" healthcheck:"),n.push(' test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]'),n.push(" interval: 10s"),n.push(" timeout: 5s"),n.push(" retries: 5")),n.push(""),n.push("volumes:"),n.push(" app_storage:"),e==="postgres"&&n.push(" pgdata:"),e==="mysql"&&n.push(" mysqldata:"),s&&n.push(" redisdata:"),i&&n.push(" rustfs_data:"),n.push(""),n.join(`
890
+ `)}dockerignoreTemplate(){return`# Dependencies
891
+ node_modules
892
+
893
+ # Build output (rebuilt in Docker)
894
+ build
895
+ .svelte-kit
896
+
897
+ # Environment files (mount or use env_file in compose)
898
+ .env
899
+ .env.local
900
+ .env.*.local
901
+
902
+ # Git
903
+ .git
904
+ .gitignore
905
+
906
+ # IDE
907
+ .vscode
908
+ .idea
909
+ *.swp
910
+ *.swo
911
+
912
+ # OS
913
+ .DS_Store
914
+ Thumbs.db
915
+
916
+ # Docker (prevent recursive context)
917
+ Dockerfile
918
+ docker-compose*.yml
919
+ .dockerignore
920
+
921
+ # Database files (use volume mounts)
922
+ *.db
923
+ *.sqlite
924
+ *.sqlite3
925
+
926
+ # Logs
927
+ storage/logs/*
928
+ *.log
929
+
930
+ # Test & Coverage
931
+ coverage
932
+ .nyc_output
933
+ __tests__
934
+ *.test.ts
935
+ *.spec.ts
936
+ `}pm2Template(){return`// \u2500\u2500 PM2 Ecosystem Config \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
937
+ // Manages multiple Svelar processes in production.
938
+ //
939
+ // Processes:
940
+ // 1. web \u2014 SvelteKit production server (port 3000)
941
+ // 2. worker \u2014 Queue job processor
942
+ // 3. scheduler \u2014 Scheduled task runner
943
+ //
944
+ // Usage:
945
+ // pm2 start ecosystem.config.cjs
946
+ // pm2 logs
947
+ // pm2 monit
948
+
949
+ module.exports = {
950
+ apps: [
951
+ {
952
+ name: 'web',
953
+ script: 'build/index.js',
954
+ instances: 'max', // Use all available CPU cores
955
+ exec_mode: 'cluster',
956
+ env: {
957
+ NODE_ENV: 'production',
958
+ PORT: 3000,
959
+ },
960
+
961
+ // Graceful restart
962
+ kill_timeout: 5000,
963
+ listen_timeout: 10000,
964
+ wait_ready: true,
965
+
966
+ // Auto-restart on memory threshold
967
+ max_memory_restart: '512M',
968
+
969
+ // Logging
970
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
971
+ error_file: 'storage/logs/web-error.log',
972
+ out_file: 'storage/logs/web-out.log',
973
+ merge_logs: true,
974
+ },
975
+ {
976
+ name: 'worker',
977
+ script: 'node_modules/.bin/svelar',
978
+ args: 'queue:work --max-time=3600',
979
+ instances: 2, // Parallel workers
980
+ exec_mode: 'fork',
981
+ autorestart: true, // Restart when max-time reached
982
+ env: {
983
+ NODE_ENV: 'production',
984
+ },
985
+
986
+ // Logging
987
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
988
+ error_file: 'storage/logs/worker-error.log',
989
+ out_file: 'storage/logs/worker-out.log',
990
+ merge_logs: true,
991
+ },
992
+ {
993
+ name: 'scheduler',
994
+ script: 'node_modules/.bin/svelar',
995
+ args: 'schedule:run',
996
+ instances: 1, // Only ONE scheduler instance!
997
+ exec_mode: 'fork',
998
+ autorestart: true,
999
+ cron_restart: '0 */6 * * *', // Restart every 6h for safety
1000
+ env: {
1001
+ NODE_ENV: 'production',
1002
+ },
1003
+
1004
+ // Logging
1005
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
1006
+ error_file: 'storage/logs/scheduler-error.log',
1007
+ out_file: 'storage/logs/scheduler-out.log',
1008
+ merge_logs: true,
1009
+ },
1010
+ ],
1011
+ };
1012
+ `}};import{writeFileSync as so,mkdirSync as ro,existsSync as Lr}from"fs";import{join as M}from"path";var It=class extends p{name="make:broadcasting";description="Scaffold broadcasting routes (Pusher auth, SSE stream, client init)";arguments=[];flags=[{name:"sse",description:"Only scaffold SSE routes (no Pusher auth)",type:"boolean"},{name:"pusher",description:"Only scaffold Pusher/Soketi routes",type:"boolean"},{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,i=t.sse??!1,n=t.pusher??!1,o=!i&&!n,a=[];(o||n)&&a.push({path:M(s,"src/routes/api/broadcasting/auth/+server.ts"),content:this.pusherAuthRoute(),label:"src/routes/api/broadcasting/auth/+server.ts",dirs:[M(s,"src/routes/api/broadcasting/auth")]}),(o||i)&&a.push({path:M(s,"src/routes/api/broadcasting/[channel]/+server.ts"),content:this.sseRoute(),label:"src/routes/api/broadcasting/[channel]/+server.ts",dirs:[M(s,"src/routes/api/broadcasting/[channel]")]}),a.push({path:M(s,"src/lib/broadcasting.ts"),content:o||n?this.clientPusher():this.clientSSE(),label:"src/lib/broadcasting.ts",dirs:[M(s,"src/lib")]});let l=M(s,"config/broadcasting.ts");Lr(l)||a.push({path:l,content:this.configTemplate(),label:"config/broadcasting.ts",dirs:[M(s,"config")]});let u=0,d=0;for(let h of a){if(Lr(h.path)&&!r){this.warn(`${h.label} already exists (use --force to overwrite)`),d++;continue}for(let g of h.dirs)ro(g,{recursive:!0});so(h.path,h.content),this.success(`Created ${h.label}`),u++}this.newLine(),u>0?this.info(`${u} file(s) created${d>0?`, ${d} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Next steps:"),o||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`/**
1013
+ * Pusher/Soketi Channel Authorization Endpoint
1014
+ *
1015
+ * This route authenticates channel subscriptions from pusher-js.
1016
+ * When a client subscribes to a private- or presence- channel,
1017
+ * pusher-js sends a POST here with socket_id and channel_name.
1018
+ *
1019
+ * Generated by: npx svelar make:broadcasting
1020
+ */
1021
+
1022
+ import type { RequestHandler } from '@sveltejs/kit';
1023
+ import { Broadcast } from 'svelar/broadcasting';
1024
+
1025
+ export const POST: RequestHandler = async ({ request, locals }) => {
1026
+ // Require authenticated user
1027
+ const user = (locals as any).user;
1028
+ if (!user) {
1029
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), {
1030
+ status: 401,
1031
+ headers: { 'Content-Type': 'application/json' },
1032
+ });
1033
+ }
1034
+
1035
+ // Parse the request (pusher-js sends form-encoded data)
1036
+ const form = await request.formData();
1037
+ const socketId = form.get('socket_id') as string;
1038
+ const channelName = form.get('channel_name') as string;
1039
+
1040
+ if (!socketId || !channelName) {
1041
+ return new Response(JSON.stringify({ error: 'Missing socket_id or channel_name' }), {
1042
+ status: 400,
1043
+ headers: { 'Content-Type': 'application/json' },
1044
+ });
1045
+ }
1046
+
1047
+ // Authenticate the channel subscription
1048
+ const auth = await Broadcast.authenticatePusher(channelName, socketId, user);
1049
+
1050
+ if (!auth) {
1051
+ return new Response(JSON.stringify({ error: 'Forbidden' }), {
1052
+ status: 403,
1053
+ headers: { 'Content-Type': 'application/json' },
1054
+ });
1055
+ }
1056
+
1057
+ return new Response(JSON.stringify(auth), {
1058
+ headers: { 'Content-Type': 'application/json' },
1059
+ });
1060
+ };
1061
+ `}sseRoute(){return`/**
1062
+ * SSE Broadcasting Stream Endpoint
1063
+ *
1064
+ * This route creates a Server-Sent Events stream for real-time
1065
+ * event broadcasting without WebSockets. Handles public, private,
1066
+ * and presence channels.
1067
+ *
1068
+ * Client usage:
1069
+ * const events = new EventSource('/api/broadcasting/private-orders.123');
1070
+ * events.addEventListener('OrderShipped', (e) => console.log(JSON.parse(e.data)));
1071
+ *
1072
+ * Generated by: npx svelar make:broadcasting
1073
+ */
1074
+
1075
+ import type { RequestHandler } from '@sveltejs/kit';
1076
+ import { Broadcast } from 'svelar/broadcasting';
1077
+
1078
+ export const GET: RequestHandler = async ({ params, locals }) => {
1079
+ const channelName = params.channel;
1080
+ if (!channelName) {
1081
+ return new Response('Channel name required', { status: 400 });
1082
+ }
1083
+
1084
+ const user = (locals as any).user;
1085
+
1086
+ // Check authorization for private/presence channels
1087
+ if (channelName.startsWith('private-') || channelName.startsWith('presence-')) {
1088
+ if (!user) {
1089
+ return new Response('Unauthorized', { status: 401 });
1090
+ }
1091
+
1092
+ const auth = await Broadcast.authorize(channelName, user);
1093
+ if (auth === false) {
1094
+ return new Response('Forbidden', { status: 403 });
1095
+ }
1096
+
1097
+ // For presence channels, pass user info for member tracking
1098
+ const userInfo = typeof auth === 'object' ? auth : undefined;
1099
+ return Broadcast.subscribe(channelName, user.id, userInfo);
1100
+ }
1101
+
1102
+ // Public channel \u2014 no auth needed
1103
+ return Broadcast.subscribe(channelName, user?.id);
1104
+ };
1105
+ `}clientPusher(){return`/**
1106
+ * Broadcasting Client Initialization
1107
+ *
1108
+ * Import this file in your root +layout.svelte to set up
1109
+ * real-time broadcasting via Pusher/Soketi.
1110
+ *
1111
+ * Generated by: npx svelar make:broadcasting
1112
+ */
1113
+
1114
+ import { usePusher } from 'svelar/broadcasting/client';
1115
+
1116
+ // Initialize the Pusher connection.
1117
+ // These values should match your .env / docker-compose config.
1118
+ export const echo = usePusher({
1119
+ key: import.meta.env.VITE_PUSHER_KEY ?? 'svelar-key',
1120
+ wsHost: import.meta.env.VITE_PUSHER_HOST ?? 'localhost',
1121
+ wsPort: Number(import.meta.env.VITE_PUSHER_PORT ?? 6001),
1122
+ forceTLS: false,
1123
+ authEndpoint: '/api/broadcasting/auth',
1124
+ enabledTransports: ['ws', 'wss'],
1125
+ });
1126
+
1127
+ // Re-export channel helpers for convenience
1128
+ export { useChannel, usePresenceChannel, leaveChannel } from 'svelar/broadcasting/client';
1129
+ `}clientSSE(){return`/**
1130
+ * Broadcasting Client Initialization (SSE)
1131
+ *
1132
+ * Import this file in your root +layout.svelte to set up
1133
+ * real-time broadcasting via Server-Sent Events.
1134
+ *
1135
+ * Generated by: npx svelar make:broadcasting
1136
+ */
1137
+
1138
+ // Re-export the SSE helper for convenience
1139
+ export { useSSE } from 'svelar/broadcasting/client';
1140
+ `}configTemplate(){return`import { env } from 'svelar/config';
1141
+
1142
+ export default {
1143
+ default: env('BROADCAST_DRIVER', 'pusher'),
1144
+
1145
+ drivers: {
1146
+ pusher: {
1147
+ driver: 'pusher' as const,
1148
+ key: env('PUSHER_KEY', 'svelar-key'),
1149
+ secret: env('PUSHER_SECRET', 'svelar-secret'),
1150
+ appId: env('PUSHER_APP_ID', 'svelar-app'),
1151
+ cluster: env('PUSHER_CLUSTER', 'mt1'),
1152
+ host: env('PUSHER_HOST', 'localhost'),
1153
+ port: env<number>('PUSHER_PORT', 6001),
1154
+ useTLS: env<boolean>('PUSHER_TLS', false),
1155
+ },
1156
+
1157
+ sse: {
1158
+ driver: 'sse' as const,
1159
+ },
1160
+
1161
+ log: {
1162
+ driver: 'log' as const,
1163
+ },
1164
+ },
1165
+ };
1166
+ `}};import{writeFileSync as no,mkdirSync as io,existsSync as oo}from"fs";import{join as P}from"path";var jt=class extends p{name="make:dashboard";description="Scaffold admin dashboard routes (health, queue, scheduler, logs)";arguments=[];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"}];async handle(e,t){let s=process.cwd(),r=t.force??!1,i=[{path:P(s,"src/routes/api/admin/health/+server.ts"),content:this.healthServerTemplate(),label:"api/admin/health/+server.ts"},{path:P(s,"src/routes/api/admin/queue/+server.ts"),content:this.queueServerTemplate(),label:"api/admin/queue/+server.ts"},{path:P(s,"src/routes/api/admin/queue/[id]/retry/+server.ts"),content:this.queueRetryServerTemplate(),label:"api/admin/queue/[id]/retry/+server.ts"},{path:P(s,"src/routes/api/admin/queue/[id]/+server.ts"),content:this.queueDeleteServerTemplate(),label:"api/admin/queue/[id]/+server.ts"},{path:P(s,"src/routes/api/admin/scheduler/+server.ts"),content:this.schedulerServerTemplate(),label:"api/admin/scheduler/+server.ts"},{path:P(s,"src/routes/api/admin/scheduler/[name]/run/+server.ts"),content:this.schedulerRunServerTemplate(),label:"api/admin/scheduler/[name]/run/+server.ts"},{path:P(s,"src/routes/api/admin/scheduler/[name]/toggle/+server.ts"),content:this.schedulerToggleServerTemplate(),label:"api/admin/scheduler/[name]/toggle/+server.ts"},{path:P(s,"src/routes/api/admin/logs/+server.ts"),content:this.logsServerTemplate(),label:"api/admin/logs/+server.ts"},{path:P(s,"src/routes/api/admin/logs/tail/+server.ts"),content:this.logsTailServerTemplate(),label:"api/admin/logs/tail/+server.ts"},{path:P(s,"src/routes/api/admin/stats/+server.ts"),content:this.statsServerTemplate(),label:"api/admin/stats/+server.ts"},{path:P(s,"src/routes/admin/dashboard/+page.server.ts"),content:this.dashboardPageServerTemplate(),label:"admin/dashboard/+page.server.ts"},{path:P(s,"src/routes/admin/dashboard/+page.svelte"),content:this.dashboardPageSvelteTemplate(),label:"admin/dashboard/+page.svelte"}],n=0,o=0;for(let a of i){let l=a.path.substring(0,a.path.lastIndexOf("/"));if(io(l,{recursive:!0}),oo(a.path)&&!r){this.warn(`${a.label} already exists (use --force to overwrite)`),o++;continue}no(a.path,a.content),this.success(`Created ${a.label}`),n++}this.newLine(),n>0?this.info(`${n} file(s) created${o>0?`, ${o} skipped`:""}`):this.info("No files created (all exist already)"),this.newLine(),this.info("Setup instructions:"),this.log(" 1. Import dashboard modules in your app:"),this.log(' import { ScheduleMonitor } from "svelar/scheduler/ScheduleMonitor";'),this.log(' import { JobMonitor } from "svelar/queue/JobMonitor";'),this.log(' import { LogViewer } from "svelar/logging/LogViewer";'),this.newLine(),this.log(" 2. Configure auth middleware on admin routes:"),this.log(' - Replace "// TODO: Add admin middleware check" with your auth logic'),this.log(' - Example: if (!event.locals.user?.isAdmin) return error(403, "Forbidden");'),this.newLine(),this.log(" 3. Access the dashboard:"),this.log(" - Navigate to: /admin/dashboard"),this.newLine(),this.log(" 4. API endpoints available at:"),this.log(" - GET /api/admin/health"),this.log(" - GET /api/admin/queue"),this.log(" - GET /api/admin/scheduler"),this.log(" - GET /api/admin/logs"),this.log(" - GET /api/admin/stats"),this.newLine()}healthServerTemplate(){return`import { json } from '@sveltejs/kit';
1167
+ import type { RequestHandler } from '@sveltejs/kit';
1168
+
1169
+ /**
1170
+ * GET /api/admin/health
1171
+ * Returns system health status
1172
+ */
1173
+ export const GET: RequestHandler = async (event) => {
1174
+ // TODO: Add admin middleware check
1175
+
1176
+ const health = {
1177
+ status: 'ok',
1178
+ timestamp: new Date().toISOString(),
1179
+ uptime: process.uptime(),
1180
+ memory: process.memoryUsage(),
1181
+ version: '0.1.0',
1182
+ };
1183
+
1184
+ return json(health);
1185
+ };
1186
+ `}queueServerTemplate(){return`import { json } from '@sveltejs/kit';
1187
+ import type { RequestHandler } from '@sveltejs/kit';
1188
+
1189
+ /**
1190
+ * GET /api/admin/queue
1191
+ * List jobs from the queue
1192
+ *
1193
+ * Query params:
1194
+ * - status: 'completed' | 'failed' | 'delayed' | 'active' | 'waiting'
1195
+ * - queue: queue name (default: 'default')
1196
+ * - limit: number of jobs (default: 50)
1197
+ * - offset: pagination offset (default: 0)
1198
+ */
1199
+ export const GET: RequestHandler = async (event) => {
1200
+ // TODO: Add admin middleware check
1201
+
1202
+ const { searchParams } = event.url;
1203
+ const status = searchParams.get('status') || 'all';
1204
+ const queueName = searchParams.get('queue') || 'default';
1205
+ const limit = parseInt(searchParams.get('limit') || '50');
1206
+ const offset = parseInt(searchParams.get('offset') || '0');
1207
+
1208
+ try {
1209
+ const { JobMonitor } = await import('svelar/queue/JobMonitor');
1210
+
1211
+ const jobs = await JobMonitor.listJobs({
1212
+ queue: queueName,
1213
+ status: status === 'all' ? undefined : status as any,
1214
+ limit,
1215
+ offset,
1216
+ });
1217
+
1218
+ const counts = await JobMonitor.getCounts(queueName);
1219
+
1220
+ return json({
1221
+ jobs,
1222
+ counts,
1223
+ queueName,
1224
+ });
1225
+ } catch (error: any) {
1226
+ return json(
1227
+ {
1228
+ error: error.message || 'Failed to fetch queue jobs',
1229
+ },
1230
+ { status: 500 }
1231
+ );
1232
+ }
1233
+ };
1234
+ `}queueRetryServerTemplate(){return`import { json } from '@sveltejs/kit';
1235
+ import type { RequestHandler } from '@sveltejs/kit';
1236
+
1237
+ /**
1238
+ * POST /api/admin/queue/[id]/retry
1239
+ * Retry a failed job
1240
+ */
1241
+ export const POST: RequestHandler = async (event) => {
1242
+ // TODO: Add admin middleware check
1243
+
1244
+ const { id } = event.params;
1245
+
1246
+ try {
1247
+ const { JobMonitor } = await import('svelar/queue/JobMonitor');
1248
+ await JobMonitor.retryJob(id);
1249
+
1250
+ return json({ success: true, message: 'Job queued for retry' });
1251
+ } catch (error: any) {
1252
+ return json(
1253
+ {
1254
+ error: error.message || 'Failed to retry job',
1255
+ },
1256
+ { status: 500 }
1257
+ );
1258
+ }
1259
+ };
1260
+ `}queueDeleteServerTemplate(){return`import { json } from '@sveltejs/kit';
1261
+ import type { RequestHandler } from '@sveltejs/kit';
1262
+
1263
+ /**
1264
+ * DELETE /api/admin/queue/[id]
1265
+ * Remove a job from the queue
1266
+ */
1267
+ export const DELETE: RequestHandler = async (event) => {
1268
+ // TODO: Add admin middleware check
1269
+
1270
+ const { id } = event.params;
1271
+
1272
+ try {
1273
+ const { JobMonitor } = await import('svelar/queue/JobMonitor');
1274
+ await JobMonitor.deleteJob(id);
1275
+
1276
+ return json({ success: true, message: 'Job removed' });
1277
+ } catch (error: any) {
1278
+ return json(
1279
+ {
1280
+ error: error.message || 'Failed to remove job',
1281
+ },
1282
+ { status: 500 }
1283
+ );
1284
+ }
1285
+ };
1286
+ `}schedulerServerTemplate(){return`import { json } from '@sveltejs/kit';
1287
+ import type { RequestHandler } from '@sveltejs/kit';
1288
+
1289
+ /**
1290
+ * GET /api/admin/scheduler
1291
+ * List all scheduled tasks
1292
+ */
1293
+ export const GET: RequestHandler = async (event) => {
1294
+ // TODO: Add admin middleware check
1295
+
1296
+ try {
1297
+ const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1298
+
1299
+ const tasks = await ScheduleMonitor.listTasks();
1300
+ const health = await ScheduleMonitor.getHealth();
1301
+
1302
+ return json({
1303
+ tasks,
1304
+ health,
1305
+ });
1306
+ } catch (error: any) {
1307
+ return json(
1308
+ {
1309
+ error: error.message || 'Failed to fetch scheduled tasks',
1310
+ },
1311
+ { status: 500 }
1312
+ );
1313
+ }
1314
+ };
1315
+ `}schedulerRunServerTemplate(){return`import { json } from '@sveltejs/kit';
1316
+ import type { RequestHandler } from '@sveltejs/kit';
1317
+
1318
+ /**
1319
+ * POST /api/admin/scheduler/[name]/run
1320
+ * Manually trigger a scheduled task
1321
+ */
1322
+ export const POST: RequestHandler = async (event) => {
1323
+ // TODO: Add admin middleware check
1324
+
1325
+ const { name } = event.params;
1326
+
1327
+ try {
1328
+ const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1329
+ await ScheduleMonitor.runTask(name);
1330
+
1331
+ return json({ success: true, message: \`Task '\${name}' triggered\` });
1332
+ } catch (error: any) {
1333
+ return json(
1334
+ {
1335
+ error: error.message || 'Failed to run task',
1336
+ },
1337
+ { status: 500 }
1338
+ );
1339
+ }
1340
+ };
1341
+ `}schedulerToggleServerTemplate(){return`import { json } from '@sveltejs/kit';
1342
+ import type { RequestHandler } from '@sveltejs/kit';
1343
+
1344
+ /**
1345
+ * POST /api/admin/scheduler/[name]/toggle
1346
+ * Enable or disable a scheduled task
1347
+ */
1348
+ export const POST: RequestHandler = async (event) => {
1349
+ // TODO: Add admin middleware check
1350
+
1351
+ const { name } = event.params;
1352
+ const body = await event.request.json();
1353
+ const enabled = body.enabled ?? true;
1354
+
1355
+ try {
1356
+ const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1357
+ if (enabled) {
1358
+ ScheduleMonitor.enableTask(name);
1359
+ } else {
1360
+ ScheduleMonitor.disableTask(name);
1361
+ }
1362
+
1363
+ return json({ success: true, message: \`Task '\${name}' \${enabled ? 'enabled' : 'disabled'}\` });
1364
+ } catch (error: any) {
1365
+ return json(
1366
+ {
1367
+ error: error.message || 'Failed to toggle task',
1368
+ },
1369
+ { status: 500 }
1370
+ );
1371
+ }
1372
+ };
1373
+ `}logsServerTemplate(){return`import { json } from '@sveltejs/kit';
1374
+ import type { RequestHandler } from '@sveltejs/kit';
1375
+
1376
+ /**
1377
+ * GET /api/admin/logs
1378
+ * Retrieve logs with filtering
1379
+ *
1380
+ * Query params:
1381
+ * - level: 'debug' | 'info' | 'warn' | 'error'
1382
+ * - channel: log channel name
1383
+ * - search: search term
1384
+ * - limit: number of logs (default: 100)
1385
+ * - offset: pagination offset (default: 0)
1386
+ */
1387
+ export const GET: RequestHandler = async (event) => {
1388
+ // TODO: Add admin middleware check
1389
+
1390
+ const { searchParams } = event.url;
1391
+ const level = searchParams.get('level');
1392
+ const channel = searchParams.get('channel');
1393
+ const search = searchParams.get('search');
1394
+ const limit = parseInt(searchParams.get('limit') || '100');
1395
+ const offset = parseInt(searchParams.get('offset') || '0');
1396
+
1397
+ try {
1398
+ const { LogViewer } = await import('svelar/logging/LogViewer');
1399
+
1400
+ const logs = LogViewer.query({
1401
+ level: level as any,
1402
+ channel: channel ?? undefined,
1403
+ search: search ?? undefined,
1404
+ limit,
1405
+ offset,
1406
+ });
1407
+
1408
+ const stats = LogViewer.getStats();
1409
+
1410
+ return json({
1411
+ logs,
1412
+ total: stats.totalEntries,
1413
+ limit,
1414
+ offset,
1415
+ });
1416
+ } catch (error: any) {
1417
+ return json(
1418
+ {
1419
+ error: error.message || 'Failed to fetch logs',
1420
+ },
1421
+ { status: 500 }
1422
+ );
1423
+ }
1424
+ };
1425
+ `}logsTailServerTemplate(){return`import type { RequestHandler } from '@sveltejs/kit';
1426
+
1427
+ /**
1428
+ * GET /api/admin/logs/tail
1429
+ * Server-Sent Events stream of live logs
1430
+ *
1431
+ * Returns a text/event-stream response with real-time log entries
1432
+ */
1433
+ export const GET: RequestHandler = async (event) => {
1434
+ // TODO: Add admin middleware check
1435
+
1436
+ const { LogViewer } = await import('svelar/logging/LogViewer');
1437
+
1438
+ // Set up SSE headers
1439
+ const headers = {
1440
+ 'Content-Type': 'text/event-stream',
1441
+ 'Cache-Control': 'no-cache',
1442
+ Connection: 'keep-alive',
1443
+ };
1444
+
1445
+ // Create a readable stream using the tail() subscription
1446
+ const stream = new ReadableStream({
1447
+ start(controller) {
1448
+ const encoder = new TextEncoder();
1449
+ const unsubscribe = LogViewer.tail((entry) => {
1450
+ try {
1451
+ controller.enqueue(encoder.encode(\`data: \${JSON.stringify(entry)}
1452
+
1453
+ \`));
1454
+ } catch {
1455
+ unsubscribe();
1456
+ }
1457
+ });
1458
+
1459
+ // Clean up when the client disconnects
1460
+ event.request.signal.addEventListener('abort', () => {
1461
+ unsubscribe();
1462
+ controller.close();
1463
+ });
1464
+ },
1465
+ });
1466
+
1467
+ return new Response(stream, { headers });
1468
+ };
1469
+ `}statsServerTemplate(){return`import { json } from '@sveltejs/kit';
1470
+ import type { RequestHandler } from '@sveltejs/kit';
1471
+
1472
+ /**
1473
+ * GET /api/admin/stats
1474
+ * Dashboard overview statistics
1475
+ */
1476
+ export const GET: RequestHandler = async (event) => {
1477
+ // TODO: Add admin middleware check
1478
+
1479
+ try {
1480
+ const { JobMonitor } = await import('svelar/queue/JobMonitor');
1481
+ const { ScheduleMonitor } = await import('svelar/scheduler/ScheduleMonitor');
1482
+ const { LogViewer } = await import('svelar/logging/LogViewer');
1483
+
1484
+ const [queueHealth, recentErrors] = await Promise.all([
1485
+ JobMonitor.getHealth(),
1486
+ Promise.resolve(LogViewer.getRecentErrors(10)),
1487
+ ]);
1488
+
1489
+ const schedulerHealth = await ScheduleMonitor.getHealth();
1490
+ const logStats = LogViewer.getStats();
1491
+
1492
+ return json({
1493
+ queue: queueHealth,
1494
+ scheduler: schedulerHealth,
1495
+ logs: logStats,
1496
+ recentErrors,
1497
+ timestamp: new Date().toISOString(),
1498
+ });
1499
+ } catch (error: any) {
1500
+ return json(
1501
+ {
1502
+ error: error.message || 'Failed to fetch stats',
1503
+ },
1504
+ { status: 500 }
1505
+ );
1506
+ }
1507
+ };
1508
+ `}dashboardPageServerTemplate(){return`import type { PageServerLoad } from './$types';
1509
+
1510
+ export const load: PageServerLoad = async ({ fetch }) => {
1511
+ try {
1512
+ // Fetch initial dashboard data
1513
+ const statsRes = await fetch('/api/admin/stats');
1514
+ const stats = await statsRes.json();
1515
+
1516
+ const healthRes = await fetch('/api/admin/health');
1517
+ const health = await healthRes.json();
1518
+
1519
+ return {
1520
+ stats,
1521
+ health,
1522
+ };
1523
+ } catch (error) {
1524
+ console.error('Failed to load dashboard:', error);
1525
+ return {
1526
+ stats: null,
1527
+ health: null,
1528
+ error: 'Failed to load dashboard data',
1529
+ };
1530
+ }
1531
+ };
1532
+ `}dashboardPageSvelteTemplate(){return`<script lang="ts">
1533
+ import type { PageData } from './$types';
1534
+
1535
+ export let data: PageData;
1536
+
1537
+ let selectedTab: 'overview' | 'queue' | 'scheduler' | 'logs' = 'overview';
1538
+ let loading = false;
1539
+
1540
+ async function refreshData() {
1541
+ loading = true;
1542
+ try {
1543
+ const response = await fetch('/api/admin/stats');
1544
+ const newStats = await response.json();
1545
+ data.stats = newStats;
1546
+ } catch (error) {
1547
+ console.error('Failed to refresh:', error);
1548
+ } finally {
1549
+ loading = false;
1550
+ }
1551
+ }
1552
+ </script>
1553
+
1554
+ <div class="dashboard">
1555
+ <header class="dashboard-header">
1556
+ <h1>Admin Dashboard</h1>
1557
+ <button on:click={refreshData} disabled={loading}>
1558
+ {loading ? 'Refreshing...' : 'Refresh'}
1559
+ </button>
1560
+ </header>
1561
+
1562
+ <nav class="tabs">
1563
+ <button
1564
+ class:active={selectedTab === 'overview'}
1565
+ on:click={() => (selectedTab = 'overview')}
1566
+ >
1567
+ Overview
1568
+ </button>
1569
+ <button
1570
+ class:active={selectedTab === 'queue'}
1571
+ on:click={() => (selectedTab = 'queue')}
1572
+ >
1573
+ Queue
1574
+ </button>
1575
+ <button
1576
+ class:active={selectedTab === 'scheduler'}
1577
+ on:click={() => (selectedTab = 'scheduler')}
1578
+ >
1579
+ Scheduler
1580
+ </button>
1581
+ <button
1582
+ class:active={selectedTab === 'logs'}
1583
+ on:click={() => (selectedTab = 'logs')}
1584
+ >
1585
+ Logs
1586
+ </button>
1587
+ </nav>
1588
+
1589
+ <main class="dashboard-content">
1590
+ {#if selectedTab === 'overview'}
1591
+ <section class="overview">
1592
+ <h2>System Overview</h2>
1593
+
1594
+ {#if data.health}
1595
+ <div class="health-card">
1596
+ <h3>System Health</h3>
1597
+ <p>Status: <strong>{data.health.status}</strong></p>
1598
+ <p>Uptime: {(data.health.uptime / 3600).toFixed(2)} hours</p>
1599
+ <p>Memory: {(data.health.memory.heapUsed / 1024 / 1024).toFixed(2)} MB</p>
1600
+ </div>
1601
+ {/if}
1602
+
1603
+ {#if data.stats}
1604
+ <div class="stats-grid">
1605
+ <div class="stat-card">
1606
+ <h3>Queue Jobs</h3>
1607
+ <p class="stat-number">{data.stats.queue?.total || 0}</p>
1608
+ <small>Active: {data.stats.queue?.active || 0}</small>
1609
+ </div>
1610
+
1611
+ <div class="stat-card">
1612
+ <h3>Scheduled Tasks</h3>
1613
+ <p class="stat-number">{data.stats.scheduler?.total || 0}</p>
1614
+ <small>Enabled: {data.stats.scheduler?.enabled || 0}</small>
1615
+ </div>
1616
+
1617
+ <div class="stat-card">
1618
+ <h3>Recent Errors</h3>
1619
+ <p class="stat-number">{data.stats.recentErrors?.length || 0}</p>
1620
+ <small>Last 24 hours</small>
1621
+ </div>
1622
+ </div>
1623
+ {/if}
1624
+ </section>
1625
+ {:else if selectedTab === 'queue'}
1626
+ <section class="queue">
1627
+ <h2>Job Queue</h2>
1628
+ <p>Queue management interface coming soon...</p>
1629
+ </section>
1630
+ {:else if selectedTab === 'scheduler'}
1631
+ <section class="scheduler">
1632
+ <h2>Scheduled Tasks</h2>
1633
+ <p>Task management interface coming soon...</p>
1634
+ </section>
1635
+ {:else if selectedTab === 'logs'}
1636
+ <section class="logs">
1637
+ <h2>Application Logs</h2>
1638
+ <p>Log viewer coming soon...</p>
1639
+ </section>
1640
+ {/if}
1641
+ </main>
1642
+ </div>
1643
+
1644
+ <style>
1645
+ .dashboard {
1646
+ padding: 2rem;
1647
+ max-width: 1200px;
1648
+ margin: 0 auto;
1649
+ }
1650
+
1651
+ .dashboard-header {
1652
+ display: flex;
1653
+ justify-content: space-between;
1654
+ align-items: center;
1655
+ margin-bottom: 2rem;
1656
+ }
1657
+
1658
+ .dashboard-header h1 {
1659
+ margin: 0;
1660
+ font-size: 2rem;
1661
+ }
1662
+
1663
+ .dashboard-header button {
1664
+ padding: 0.5rem 1rem;
1665
+ background: #0066cc;
1666
+ color: white;
1667
+ border: none;
1668
+ border-radius: 4px;
1669
+ cursor: pointer;
1670
+ font-size: 1rem;
1671
+ }
1672
+
1673
+ .dashboard-header button:hover:not(:disabled) {
1674
+ background: #0052a3;
1675
+ }
1676
+
1677
+ .dashboard-header button:disabled {
1678
+ opacity: 0.6;
1679
+ cursor: not-allowed;
1680
+ }
1681
+
1682
+ .tabs {
1683
+ display: flex;
1684
+ gap: 1rem;
1685
+ margin-bottom: 2rem;
1686
+ border-bottom: 1px solid #e0e0e0;
1687
+ }
1688
+
1689
+ .tabs button {
1690
+ padding: 0.75rem 1.5rem;
1691
+ background: none;
1692
+ border: none;
1693
+ border-bottom: 3px solid transparent;
1694
+ cursor: pointer;
1695
+ font-size: 1rem;
1696
+ color: #666;
1697
+ transition: all 0.3s ease;
1698
+ }
1699
+
1700
+ .tabs button:hover {
1701
+ color: #0066cc;
1702
+ }
1703
+
1704
+ .tabs button.active {
1705
+ color: #0066cc;
1706
+ border-bottom-color: #0066cc;
1707
+ }
1708
+
1709
+ .dashboard-content {
1710
+ animation: fadeIn 0.3s ease;
1711
+ }
1712
+
1713
+ @keyframes fadeIn {
1714
+ from {
1715
+ opacity: 0;
1716
+ transform: translateY(10px);
1717
+ }
1718
+ to {
1719
+ opacity: 1;
1720
+ transform: translateY(0);
1721
+ }
1722
+ }
1723
+
1724
+ .overview {
1725
+ display: flex;
1726
+ flex-direction: column;
1727
+ gap: 2rem;
1728
+ }
1729
+
1730
+ .health-card {
1731
+ padding: 1.5rem;
1732
+ background: #f5f5f5;
1733
+ border-radius: 8px;
1734
+ border-left: 4px solid #00aa00;
1735
+ }
1736
+
1737
+ .health-card h3 {
1738
+ margin-top: 0;
1739
+ }
1740
+
1741
+ .health-card p {
1742
+ margin: 0.5rem 0;
1743
+ }
1744
+
1745
+ .stats-grid {
1746
+ display: grid;
1747
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1748
+ gap: 1.5rem;
1749
+ }
1750
+
1751
+ .stat-card {
1752
+ padding: 1.5rem;
1753
+ background: white;
1754
+ border: 1px solid #e0e0e0;
1755
+ border-radius: 8px;
1756
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1757
+ }
1758
+
1759
+ .stat-card h3 {
1760
+ margin-top: 0;
1761
+ font-size: 0.9rem;
1762
+ color: #666;
1763
+ text-transform: uppercase;
1764
+ }
1765
+
1766
+ .stat-number {
1767
+ margin: 0.5rem 0;
1768
+ font-size: 2rem;
1769
+ font-weight: bold;
1770
+ color: #0066cc;
1771
+ }
1772
+
1773
+ .stat-card small {
1774
+ display: block;
1775
+ color: #999;
1776
+ font-size: 0.85rem;
1777
+ }
1778
+
1779
+ section h2 {
1780
+ margin-top: 0;
1781
+ }
1782
+ </style>
1783
+ `}};import{writeFileSync as Ir,mkdirSync as ao,existsSync as jr}from"fs";import{join as qt}from"path";var Ut=class extends p{name="make:resource";description="Create a new API resource (response transformer)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"},{name:"model",alias:"m",description:"Model name to transform",type:"string"},{name:"collection",alias:"c",description:"Also generate a collection resource",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a resource name.");return}let r=s.endsWith("Resource")?s:`${s}Resource`,i=t.module||this.deriveModuleName(r);t.module||this.warn(`No --module specified, using "${i}". Use --module=<name> to target a specific module.`);let n=qt(process.cwd(),"src","lib","modules",i);ao(n,{recursive:!0});let o=qt(n,`${r}.ts`);if(jr(o)){this.warn(`Resource ${r} already exists.`);return}let a=t.model||this.inferModelName(r),l=this.generateResource(r,a);if(Ir(o,l),this.success(`Resource created: src/lib/modules/${i}/${r}.ts`),t.collection){let u=r.replace("Resource","CollectionResource"),d=qt(n,`${u}.ts`);if(!jr(d)){let h=this.generateCollectionResource(u,r,a);Ir(d,h),this.success(`Collection resource created: src/lib/modules/${i}/${u}.ts`)}}}generateResource(e,t){let s=`${t}Data`;return`import { Resource } from '@beeblock/svelar/routing';
1784
+ import type { ${t} } from './${t}.js';
1785
+
1786
+ // \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
1787
+ // Define the shape once \u2014 import this type on the frontend.
1788
+ //
1789
+ // import type { ${s} } from '$lib/modules/.../${e}';
1790
+ //
1791
+
1792
+ export interface ${s} {
1793
+ id: number;
1794
+ // Add your fields here
1795
+ // name: string;
1796
+ // email: string;
1797
+ // created_at: string;
1798
+ }
1799
+
1800
+ // \u2500\u2500 Resource \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\u2500\u2500\u2500
1801
+
1802
+ export class ${e} extends Resource<${t}, ${s}> {
1803
+ toJSON(): ${s} {
1804
+ return {
1805
+ id: this.data.id,
1806
+ // Map model fields to the API contract
1807
+ // name: this.data.name,
1808
+ // email: this.data.email,
1809
+ // created_at: this.data.created_at,
1810
+ };
1811
+ }
1812
+
1813
+ // Override toWith() to include top-level data in every response
1814
+ // (roles, permissions, related context). Can be async.
1815
+ //
1816
+ // async toWith() {
1817
+ // return {
1818
+ // roles: await this.data.getRoleNames(),
1819
+ // permissions: await this.data.getAllPermissions(),
1820
+ // };
1821
+ // }
1822
+
1823
+ // Override toAdditional() to include metadata under "meta"
1824
+ //
1825
+ // toAdditional() {
1826
+ // return { comments_count: this.data.comments_count ?? 0 };
1827
+ // }
1828
+ }
1829
+ `}generateCollectionResource(e,t,s){return`import { Resource } from '@beeblock/svelar/routing';
1830
+ import { ${t} } from './${t}.js';
1831
+ import type { ${s} } from './${s}.js';
1832
+
1833
+ /**
1834
+ * ${e}
1835
+ *
1836
+ * Wraps a collection of ${s} with additional metadata.
1837
+ * Use this when you need custom collection-level data (pagination, aggregates, etc.)
1838
+ */
1839
+ export class ${e} {
1840
+ constructor(
1841
+ private items: ${s}[],
1842
+ private meta: Record<string, any> = {}
1843
+ ) {}
1844
+
1845
+ static make(items: ${s}[], meta?: Record<string, any>) {
1846
+ return new ${e}(items, meta ?? {});
1847
+ }
1848
+
1849
+ toResponse(): Response {
1850
+ return ${t}.collection(this.items)
1851
+ .additional(this.meta)
1852
+ .toResponse();
1853
+ }
1854
+
1855
+ toObject() {
1856
+ return ${t}.collection(this.items)
1857
+ .additional(this.meta)
1858
+ .toObject();
1859
+ }
1860
+ }
1861
+ `}deriveModuleName(e){return e.replace(/Resource$/,"").replace(/Collection$/,"").toLowerCase()}inferModelName(e){return e.replace(/Resource$/,"")||"Model"}};import{writeFileSync as co,mkdirSync as lo,existsSync as uo}from"fs";import{join as qr}from"path";var Ht=class extends p{name="make:schema";description="Create a contract schema (Zod schemas + shared types)";arguments=["name"];flags=[{name:"module",description:"Module name (e.g. auth, billing)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a schema name (e.g. User, Post, Invoice).");return}let r=s.charAt(0).toUpperCase()+s.slice(1),i=this.toKebab(s)+".schema",n=t.module||s.toLowerCase(),o=qr(process.cwd(),"src","lib","modules",n);lo(o,{recursive:!0});let a=qr(o,`${i}.ts`);if(uo(a)){this.warn(`Schema already exists: src/lib/modules/${n}/${i}.ts`);return}let l=this.generateSchema(r);co(a,l),this.success(`Schema created: src/lib/modules/${n}/${i}.ts`),this.info(""),this.info(" Use this schema across your entire stack:"),this.info(""),this.info(` Resource: extends Resource<${r}, ${r}Data>`),this.info(` FormRequest: uses create${r}Schema / update${r}Schema`),this.info(` Frontend: import type { ${r}Data } from '$lib/modules/${n}/${i}'`)}generateSchema(e){let t=e.charAt(0).toLowerCase()+e.slice(1),s=this.toKebab(e);return`import { z } from 'zod';
1862
+
1863
+ // \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
1864
+ //
1865
+ // Single source of truth for validation, API responses, and frontend types.
1866
+ // Import the Zod schemas for validation, the types for everything else.
1867
+ //
1868
+ // Usage:
1869
+ // Resource: import type { ${e}Data } from './${s}.schema.js';
1870
+ // FormRequest: import { create${e}Schema } from './${s}.schema.js';
1871
+ // Frontend: import type { ${e}Data, Create${e}Input } from '$lib/modules/.../${s}.schema';
1872
+
1873
+ // \u2500\u2500 Response schema (what the API returns) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1874
+
1875
+ export const ${t}Schema = z.object({
1876
+ id: z.number(),
1877
+ // name: z.string(),
1878
+ // email: z.string().email(),
1879
+ // created_at: z.string(),
1880
+ });
1881
+
1882
+ // \u2500\u2500 Input schemas (what the API accepts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1883
+
1884
+ export const create${e}Schema = z.object({
1885
+ // name: z.string().min(2, 'Name must be at least 2 characters'),
1886
+ // email: z.string().email('Please enter a valid email'),
1887
+ });
1888
+
1889
+ export const update${e}Schema = create${e}Schema.partial();
1890
+
1891
+ // \u2500\u2500 Inferred types \u2014 shared between server and frontend \u2500\u2500\u2500\u2500\u2500
1892
+
1893
+ export type ${e}Data = z.infer<typeof ${t}Schema>;
1894
+ export type Create${e}Input = z.infer<typeof create${e}Schema>;
1895
+ export type Update${e}Input = z.infer<typeof update${e}Schema>;
1896
+ `}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 ho,mkdirSync as po,existsSync as mo}from"fs";import{join as Ur}from"path";var Ft=class extends p{name="make:observer";description="Create a new model observer class";arguments=["name"];flags=[{name:"model",alias:"m",description:"The model class to observe",type:"string"},{name:"module",description:"Module name (e.g. users, posts)",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an observer name (e.g. UserObserver).");return}let r=t.model||s.replace(/Observer$/,""),i=t.module||this.toSnakeCase(this.pluralize(r)),n=Ur(process.cwd(),"src","lib","modules",i);po(n,{recursive:!0});let o=Ur(n,`${s}.ts`);if(mo(o)){this.warn(`Observer ${s} already exists at ${o}`);return}let a=`import { ModelObserver } from '@beeblock/svelar/orm';
1897
+ import type { ${r} } from './${r}.js';
1898
+
1899
+ export class ${s} extends ModelObserver {
1900
+ // Fires before a new ${r} is inserted
1901
+ // async creating(${r.toLowerCase()}: ${r}) {
1902
+ // }
1903
+
1904
+ // Fires after a new ${r} is inserted
1905
+ // async created(${r.toLowerCase()}: ${r}) {
1906
+ // await sendWelcomeEmail(${r.toLowerCase()});
1907
+ // }
1908
+
1909
+ // Fires before an existing ${r} is updated
1910
+ // async updating(${r.toLowerCase()}: ${r}) {
1911
+ // }
1912
+
1913
+ // Fires after an existing ${r} is updated
1914
+ // async updated(${r.toLowerCase()}: ${r}) {
1915
+ // }
1916
+
1917
+ // Fires before any save (create or update)
1918
+ // async saving(${r.toLowerCase()}: ${r}) {
1919
+ // }
1920
+
1921
+ // Fires after any save (create or update)
1922
+ // async saved(${r.toLowerCase()}: ${r}) {
1923
+ // }
1924
+
1925
+ // Fires before deletion
1926
+ // async deleting(${r.toLowerCase()}: ${r}) {
1927
+ // await ${r.toLowerCase()}.posts().query().delete();
1928
+ // }
1929
+
1930
+ // Fires after deletion
1931
+ // async deleted(${r.toLowerCase()}: ${r}) {
1932
+ // }
1933
+ }
1934
+ `;ho(o,a),this.success(`Observer created: src/lib/modules/${i}/${s}.ts`),this.info(`Register it in your app: ${r}.observe(new ${s}());`)}toSnakeCase(e){return e.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}pluralize(e){return e.endsWith("y")?e.slice(0,-1)+"ies":e.endsWith("s")||e.endsWith("x")||e.endsWith("z")||e.endsWith("ch")||e.endsWith("sh")?e+"es":e+"s"}};import{writeFileSync as go,mkdirSync as fo,existsSync as yo}from"fs";import{join as Hr}from"path";var Bt=class extends p{name="make:event";description="Create a new event class";arguments=["name"];flags=[];async handle(e,t){let s=e[0];if(!s){this.error("Please provide an event name (e.g. UserRegistered).");return}let r=Hr(process.cwd(),"src","lib","events");fo(r,{recursive:!0});let i=Hr(r,`${s}.ts`);if(yo(i)){this.warn(`Event ${s} already exists at ${i}`);return}let n=`/**
1935
+ * ${s} Event
1936
+ *
1937
+ * Dispatched when ... (describe when this event fires).
1938
+ *
1939
+ * Register listeners in your EventServiceProvider:
1940
+ * protected listen = {
1941
+ * [${s}.name]: [MyListener],
1942
+ * };
1943
+ */
1944
+
1945
+ export class ${s} {
1946
+ constructor(
1947
+ // Add your event data here, e.g.:
1948
+ // public readonly user: User,
1949
+ // public readonly metadata?: Record<string, any>,
1950
+ ) {}
1951
+ }
1952
+ `;go(i,n),this.success(`Event created: src/lib/events/${s}.ts`)}};import{writeFileSync as wo,mkdirSync as bo,existsSync as vo}from"fs";import{join as Fr}from"path";var Wt=class extends p{name="make:listener";description="Create a new event listener class";arguments=["name"];flags=[{name:"event",alias:"e",description:"The event class this listener handles",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a listener name (e.g. SendWelcomeEmail).");return}let r=Fr(process.cwd(),"src","lib","listeners");bo(r,{recursive:!0});let i=Fr(r,`${s}.ts`);if(vo(i)){this.warn(`Listener ${s} already exists at ${i}`);return}let n=t.event||"any",o=t.event?`import type { ${t.event} } from '../events/${t.event}.js';
1953
+
1954
+ `:"",a=t.event||"any",l=`import { Listener } from '@beeblock/svelar/events';
1955
+ ${o}export class ${s} extends Listener<${a}> {
1956
+ async handle(event: ${a}): Promise<void> {
1957
+ // Handle the event
1958
+ // e.g. await Mail.to(event.user.email).send(new WelcomeEmail());
1959
+ }
1960
+
1961
+ // Optionally filter which events to handle:
1962
+ // shouldHandle(event: ${a}): boolean {
1963
+ // return true;
1964
+ // }
1965
+ }
1966
+ `;wo(i,l),this.success(`Listener created: src/lib/listeners/${s}.ts`),t.event&&(this.info("Don't forget to register it in your EventServiceProvider:"),this.info(` [${t.event}.name]: [${s}]`))}};import{writeFileSync as To,mkdirSync as xo,existsSync as Eo}from"fs";import{join as Br}from"path";var Kt=class extends p{name="make:route";description="Create route files with controller bindings";arguments=["path"];flags=[{name:"controller",alias:"c",description:"Controller class name",type:"string"},{name:"resource",alias:"r",description:"Generate full CRUD resource routes",type:"boolean"},{name:"api",description:"Prefix path with /api",type:"boolean"},{name:"methods",alias:"m",description:"HTTP methods (comma-separated: GET,POST,PUT,DELETE)",type:"string"},{name:"module",description:"Module name for controller import path",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a route path (e.g. posts, users/[id], admin/settings).");return}let r=s.replace(/^\//,"");t.api&&!r.startsWith("api/")&&(r="api/"+r);let i=t.controller||this.inferControllerName(r),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(o=>o.trim().toUpperCase()):["GET"]).map(o=>({method:o,handler:this.defaultHandler(o)}));this.generateRouteFile(e,t,s,n)}generateRouteFile(e,t,s,r){let i=Br(process.cwd(),"src","routes",...e.split("/"));xo(i,{recursive:!0});let n=Br(i,"+server.ts");if(Eo(n)){this.warn(`Route already exists: src/routes/${e}/+server.ts (skipped)`);return}let o=`$lib/modules/${s}/${t}.js`,a=r.map(u=>`export const ${u.method} = ctrl.handle('${u.handler}');`).join(`
1967
+ `),l=`import { ${t} } from '${o}';
1968
+
1969
+ const ctrl = new ${t}();
1970
+ ${a}
1971
+ `;To(n,l),this.success(`Route created: src/routes/${e}/+server.ts`);for(let u of r)this.info(` ${u.method} /${e} \u2192 ${t}.${u.handler}()`)}inferControllerName(e){let t=e.replace(/^api\//,"").split("/").filter(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 Wr,relative as Jt,sep as zt}from"path";import{existsSync as So,readdirSync as Co,readFileSync as Kr,statSync as Po}from"fs";var Vt=class extends p{name="routes:list";description="List all registered routes";arguments=[];flags=[{name:"json",description:"Output as JSON",type:"boolean"},{name:"api",description:"Show only API routes",type:"boolean"},{name:"method",alias:"m",description:"Filter by HTTP method (GET, POST, etc.)",type:"string"}];async handle(e,t){let s=Wr(process.cwd(),"src","routes");if(!So(s)){this.error("No src/routes/ directory found.");return}let i=this.scanRoutes(s,s);if(t.api&&(i=i.filter(u=>u.path.startsWith("/api"))),t.method){let u=t.method.toUpperCase();i=i.filter(d=>d.method===u)}if(i.sort((u,d)=>u.path.localeCompare(d.path)||u.method.localeCompare(d.method)),i.length===0){this.warn("No routes found.");return}if(t.json){this.log(JSON.stringify(i,null,2));return}this.log(""),this.log(` \x1B[1mApplication Routes\x1B[0m (${i.length} routes)
1972
+ `);let n=Math.max(6,...i.map(u=>u.method.length)),o=Math.max(4,...i.map(u=>u.path.length)),a=Math.max(7,...i.map(u=>u.handler.length)),l=` ${"METHOD".padEnd(n)} ${"PATH".padEnd(o)} ${"HANDLER".padEnd(a)} FILE`;this.log(`\x1B[2m${l}\x1B[0m`),this.log(`\x1B[2m ${"\u2500".repeat(n)} ${"\u2500".repeat(o)} ${"\u2500".repeat(a)} ${"\u2500".repeat(20)}\x1B[0m`);for(let u of i){let h=`${this.getMethodColor(u.method)}${u.method.padEnd(n)}\x1B[0m`,g=u.path.padEnd(o),y=`\x1B[2m${u.handler.padEnd(a)}\x1B[0m`,x=`\x1B[2m${u.file}\x1B[0m`;this.log(` ${h} ${g} ${y} ${x}`)}this.log("")}scanRoutes(e,t){let s=[],r=Co(e);for(let i of r){let n=Wr(e,i);if(Po(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=Kr(e,"utf-8"),i=this.filePathToUrl(e,t),n=Jt(process.cwd(),e).split(zt).join("/"),o=/export\s+(?:const|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g,a;for(;(a=o.exec(r))!==null;){let l=a[1],u=this.extractHandler(r,l);s.push({method:l,path:i,handler:u,file:n})}return s}parsePageServerFile(e,t){let s=[],r=Kr(e,"utf-8"),i=this.filePathToUrl(e,t),n=Jt(process.cwd(),e).split(zt).join("/");/export\s+(const|async\s+function)\s+load\b/.test(r)&&s.push({method:"GET",path:i,handler:"load()",file:n});let o=r.match(/export\s+const\s+actions\s*=\s*\{([^}]+)\}/);if(o){let a=o[1].split(",").map(l=>l.trim().split(":")[0].split("(")[0].trim()).filter(Boolean);for(let l of a)s.push({method:"POST",path:l==="default"?i:`${i}?/${l}`,handler:`actions.${l}()`,file:n})}return s}filePathToUrl(e,t){let s=Jt(t,e).split(zt).join("/");return s=s.replace(/\/?\+(?:server|page\.server)\.[tj]s$/,""),s=s.replace(/\[\.\.\.(\w+)\]/g,"*$1").replace(/\[\[(\w+)\]\]/g,":$1?").replace(/\[(\w+)\]/g,":$1"),s=s.replace(/\([^)]+\)\//g,""),"/"+s||"/"}extractHandler(e,t){let s=new RegExp(`export\\s+const\\s+${t}\\s*=\\s*(\\w+)\\.handle\\(['"]([^'"]+)['"]\\)`),r=e.match(s);if(r)return`${r[1]}.${r[2]}()`;let i=new RegExp(`const\\s*\\{[^}]*${t}[^}]*\\}\\s*=\\s*resource\\(\\s*(\\w+)`),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 Vr}from"path";import{pathToFileURL as $o}from"url";var Xt=class extends p{name="migrate";description="Run pending database migrations";flags=[{name:"rollback",description:"Rollback the last batch of migrations",type:"boolean"},{name:"reset",description:"Reset all migrations",type:"boolean"},{name:"refresh",description:"Reset and re-run all migrations",type:"boolean"},{name:"fresh",description:"Drop all tables and re-run all migrations",type:"boolean"},{name:"status",description:"Show migration status",type:"boolean"},{name:"seed",description:"Run seeders after migrating",type:"boolean"},{name:"force",description:"Force destructive operations in production",type:"boolean"}];destructiveFlags=["reset","refresh","fresh"];async handle(e,t){await this.bootstrap();let s=this.destructiveFlags.find(l=>t[l]);s&&this.isProduction()&&!t.force&&(this.error(`The --${s} flag is destructive and cannot be run in production.`),this.error(`Use --force to run this command in production: npx svelar migrate --${s} --force`),process.exit(1));let{Migrator:r}=await Promise.resolve().then(()=>(Yt(),zr)),i=new r,n=Vr(process.cwd(),"src","lib","database","migrations"),o=await this.loadMigrations(n);if(t.status){let l=await i.status(o);this.table(["Migration","Status","Batch"],l.map(u=>[u.name,u.ran?"\x1B[32mRan\x1B[0m":"\x1B[33mPending\x1B[0m",u.batch?.toString()??"-"]));return}if(t.rollback){this.info("Rolling back last batch...");let l=await i.rollback(o);if(l.length===0)this.info("Nothing to rollback.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.reset){this.warnDestructive("reset"),this.info("Resetting all migrations...");let l=await i.reset(o);if(l.length===0)this.info("Nothing to reset.");else for(let u of l)this.success(`Rolled back: ${u}`);return}if(t.refresh){this.warnDestructive("refresh"),this.info("Refreshing migrations...");let l=await i.refresh(o);for(let u of l.reset)this.success(`Rolled back: ${u}`);for(let u of l.migrated)this.success(`Migrated: ${u}`);return}if(t.fresh){this.warnDestructive("fresh"),this.info("Dropping all tables...");let l=await i.fresh(o);if(l.dropped.length>0)for(let u of l.dropped)this.success(`Dropped table: ${u}`);this.newLine(),this.info("Re-running all migrations...");for(let u of l.migrated)this.success(`Migrated: ${u}`);return}this.info("Running migrations...");let a=await i.run(o);if(a.length===0)this.info("Nothing to migrate.");else for(let l of a)this.success(`Migrated: ${l}`)}isProduction(){return(process.env.NODE_ENV||process.env.APP_ENV||"development")==="production"}warnDestructive(e){this.isProduction()&&this.warn(`Running --${e} in PRODUCTION with --force.`)}async loadMigrations(e){let t;try{t=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=Vr(e,r);try{let n=await import($o(i).href),o=n.default??Object.values(n).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.up=="function");o?s.push({name:r.replace(/\.(ts|js)$/,""),timestamp:r.split("_")[0],path:i,migration:new o}):this.warn(`No migration class found in: ${r}`)}catch(n){let o;try{o=n instanceof Error?n.message:String(n)}catch{o=JSON.stringify(n)??"Unknown error (non-stringifiable object)"}this.error(`Failed to load migration ${r}: ${o}`)}}return s}};import{join as Zt}from"path";import{pathToFileURL as ko}from"url";import{existsSync as Qr}from"fs";var es=class extends p{name="seed:run";description="Run database seeders";flags=[{name:"class",description:"Specific seeder class to run",type:"string"}];async handle(e,t){await this.bootstrap();let s=Zt(process.cwd(),"src","lib","database","seeders"),r=t.class?Zt(s,`${t.class}.ts`):Zt(s,"DatabaseSeeder.ts"),i=r;Qr(i)||(i=i.replace(/\.ts$/,".js")),Qr(i)||(this.error(`Seeder not found: ${r}`),process.exit(1)),this.info("Running seeders...");try{let n=await import(ko(i).href),o=n.default??n.DatabaseSeeder??Object.values(n).find(l=>typeof l=="function"&&l.prototype&&typeof l.prototype.run=="function");(!o||typeof o!="function")&&(this.error("No seeder class found in file."),process.exit(1)),await new o().run(),this.success("Database seeded successfully.")}catch(n){let o=n instanceof Error?n.message:String(n);this.error(`Seeding failed: ${o}`),n?.stack&&console.error(n.stack),process.exit(1)}}};import{readdirSync as Mo}from"fs";import{join as en}from"path";import{pathToFileURL as Oo}from"url";var rs=class extends p{name="schedule:run";description="Run the task scheduler";flags=[{name:"once",description:"Run due tasks once and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Scheduler:s}=await Promise.resolve().then(()=>(Zr(),Xr)),r=new s;r.persistToDatabase();let i=en(process.cwd(),"src","lib","scheduler"),n=await this.loadTasks(i);if(n.length===0){this.warn("No scheduled tasks found in src/lib/scheduler/");return}for(let l of n)r.register(l),this.info(`Registered task: ${l.name}`);if(this.newLine(),t.once){this.info("Running due tasks (once)...");let l=await r.run();if(l.length===0)this.info("No tasks were due.");else for(let u of l)u.success?this.success(`${u.task}: completed in ${u.duration}ms`):this.error(`${u.task}: failed \u2014 ${u.error}`);return}this.info("Scheduler running. Press Ctrl+C to stop."),this.newLine();let o=async()=>{let l=await r.run();for(let u of l){let d=new Date().toISOString().replace("T"," ").slice(0,19);u.success?this.success(`[${d}] ${u.task}: completed in ${u.duration}ms`):this.error(`[${d}] ${u.task}: failed \u2014 ${u.error}`)}};await o();let a=6e4-Date.now()%6e4;this.info(`Next tick aligned to minute boundary in ${Math.round(a/1e3)}s.`),await new Promise(l=>setTimeout(l,a)),await o(),setInterval(o,6e4),await new Promise(()=>{})}async loadTasks(e){let t;try{t=Mo(e).filter(r=>(r.endsWith(".ts")||r.endsWith(".js"))&&!r.startsWith("index")).sort()}catch{return[]}let s=[];for(let r of t){let i=en(e,r);try{let n=await import(Oo(i).href),o=n.default??Object.values(n).find(a=>typeof a=="function"&&a.prototype&&typeof a.prototype.handle=="function");if(o){let a=new o;a.schedule(),s.push(a)}}catch(n){this.error(`Failed to load task ${r}: ${n.message??n}`)}}return s}};var ds=class extends p{name="queue:work";description="Process queued jobs";flags=[{name:"queue",description:'Queue name to process (default: "default")',type:"string",default:"default"},{name:"max-jobs",description:"Stop after processing N jobs",type:"string"},{name:"max-time",description:"Stop after N seconds",type:"string"},{name:"sleep",description:"Sleep N milliseconds between polls (default: 1000)",type:"string",default:"1000"},{name:"once",description:"Process a single job and exit",type:"boolean"}];async handle(e,t){await this.bootstrap();let{Queue:s}=await Promise.resolve().then(()=>(us(),tn)),r=t.queue??"default",i=t["max-jobs"]?parseInt(t["max-jobs"]):void 0,n=t["max-time"]?parseInt(t["max-time"]):void 0,o=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 u=await s.work({queue:r,maxJobs:1,sleep:0});u===0?this.info("No jobs to process."):this.success(`Processed ${u} job(s).`);return}this.info(`Worker running on "${r}". Press Ctrl+C to stop.`),this.newLine();let a=Date.now(),l=0;for(;;){if(n&&(Date.now()-a)/1e3>=n){this.info(`Max time (${n}s) reached. Stopping.`);break}if(i&&l>=i){this.info(`Max jobs (${i}) reached. Stopping.`);break}let u=await s.work({queue:r,maxJobs:1,sleep:0});if(u>0){l+=u;let d=new Date().toISOString().replace("T"," ").slice(0,19);this.success(`[${d}] Processed ${u} job(s) (total: ${l})`)}else await new Promise(d=>setTimeout(d,o))}this.newLine(),this.info(`Worker stopped. Total jobs processed: ${l}`)}};var cr=class extends p{name="tinker";description="Start an interactive REPL with Svelar preloaded";flags=[];async handle(){this.info("Starting Svelar Tinker..."),this.log(`Type .exit to quit. All Svelar modules are available.
1973
+ `);let t=(await import("repl")).start({prompt:"\x1B[36msvelar>\x1B[0m ",useGlobal:!0});try{let s=await Promise.resolve().then(()=>(Zn(),Xn));for(let[r,i]of Object.entries(s))t.context[r]=i;t.context.DB=s.Connection,t.context.Schema=s.Schema,this.log("Available: Model, QueryBuilder, Connection, Schema, Hash, Cache, Event, Log, ..."),this.log("")}catch(s){this.warn(`Could not preload all modules: ${s.message}`)}try{let{readdirSync:s}=await import("fs"),{join:r}=await import("path"),{pathToFileURL:i}=await import("url"),n=r(process.cwd(),"src","lib","models"),o=s(n).filter(a=>a.endsWith(".ts")||a.endsWith(".js"));for(let a of o)try{let l=await import(i(r(n,a)).href);for(let[u,d]of Object.entries(l))typeof d=="function"&&(t.context[u]=d)}catch{}o.length>0&&this.log(`Loaded models: ${o.map(a=>a.replace(/\.(ts|js)$/,"")).join(", ")}`)}catch{}await new Promise(s=>{t.on("exit",s)})}};var dr=class extends p{name="plugin:list";description="List all discovered and enabled plugins";arguments=[];flags=[];async handle(e,t){try{let{PluginRegistry:s}=await Promise.resolve().then(()=>(dt(),ur)),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"],o=i.map(a=>[a.name,a.version,a.description||"-",a.enabled?"\u2713 Enabled":" Disabled",a.hasConfig?"\u2713":"-",a.hasMigrations?"\u2713":"-"]);this.newLine(),this.table(n,o),this.newLine(),this.info(`Total: ${i.length} plugin(s)`)}catch(s){this.error(`Failed to list plugins: ${s?.message??String(s)}`)}}};var gr=class extends p{name="plugin:publish";description="Publish a plugin's config and migration files";arguments=["name"];flags=[{name:"force",alias:"f",description:"Overwrite existing files",type:"boolean"},{name:"only",alias:"o",description:"Publish only config|migrations|assets",type:"string"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a plugin name.");return}try{let{PluginRegistry:r}=await Promise.resolve().then(()=>(dt(),ur)),{PluginPublisher:i}=await Promise.resolve().then(()=>(mr(),ei)),n=r,o=i;await n.discover();let a=n.get(s);if(!a){this.error(`Plugin "${s}" not found.`);return}let l=await this.loadPluginClass(a.packageName);if(!l){this.error(`Failed to load plugin class for "${s}".`);return}let u=new l,d={force:t.force||!1,only:t.only};this.info(`Publishing plugin: ${s}`);let h=await o.publish(u,d);this.newLine(),h.configs.length>0&&(this.success(`${h.configs.length} config file(s) published:`),h.configs.forEach(g=>this.log(` - ${g}`))),h.migrations.length>0&&(this.success(`${h.migrations.length} migration file(s) published:`),h.migrations.forEach(g=>this.log(` - ${g}`))),h.assets.length>0&&(this.success(`${h.assets.length} asset file(s) published:`),h.assets.forEach(g=>this.log(` - ${g}`))),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 yr=class extends p{name="plugin:install";description="Install a plugin from npm";arguments=["package"];flags=[{name:"no-publish",alias:"n",description:"Skip auto-publishing plugin assets",type:"boolean"}];async handle(e,t){let s=e[0];if(!s){this.error("Please provide a package name.");return}try{let{PluginInstaller:r}=await Promise.resolve().then(()=>(si(),ti)),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)}`)}}};export{ft as Cli,p as Command,$t as MakeActionCommand,It as MakeBroadcastingCommand,_t as MakeChannelCommand,Mt as MakeCommandCommand,Ot as MakeConfigCommand,xt as MakeControllerCommand,jt as MakeDashboardCommand,Lt as MakeDockerCommand,Bt as MakeEventCommand,Dt as MakeJobCommand,Wt as MakeListenerCommand,Et as MakeMiddlewareCommand,Tt as MakeMigrationCommand,vt as MakeModelCommand,Ft as MakeObserverCommand,At as MakePluginCommand,St as MakeProviderCommand,Rt as MakeRepositoryCommand,kt as MakeRequestCommand,Ut as MakeResourceCommand,Kt as MakeRouteCommand,Ht as MakeSchemaCommand,Ct as MakeSeederCommand,Pt as MakeServiceCommand,Nt as MakeTaskCommand,Xt as MigrateCommand,yr as PluginInstallCommand,dr as PluginListCommand,gr as PluginPublishCommand,ds as QueueWorkCommand,Vt as RoutesListCommand,rs as ScheduleRunCommand,es as SeedCommand,cr as TinkerCommand};