nucleus-core-ts 0.8.142 → 0.8.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,7 +57,7 @@ var I2=Object.create;var{getPrototypeOf:p2,defineProperty:$i,getOwnPropertyNames
|
|
|
57
57
|
</div>
|
|
58
58
|
</body>
|
|
59
59
|
</html>
|
|
60
|
-
`}getActiveAlerts(){return Array.from(this.state.activeAlerts.values())}acknowledgeAlert(n){for(let[r,t]of this.state.activeAlerts)if(t.id===n)return t.acknowledged=!0,!0;return!1}clearAlert(n){this.state.activeAlerts.delete(n)}}class j0{config;requestCount=0;responseTimes=[];errorCount=0;rateLimitBlocks=0;byEndpoint={};byMethod={};byStatus={};byErrorType={};lastCollectTime=Date.now();constructor(n){this.config=n}recordRequest(n){if(!this.config?.enabled)return;if(this.requestCount++,this.config.metrics?.responseTime!==!1){if(this.responseTimes.push(n.responseTimeMs),this.responseTimes.length>1e4)this.responseTimes=this.responseTimes.slice(-5000)}if(this.config.metrics?.requests!==!1)this.byEndpoint[n.endpoint]=(this.byEndpoint[n.endpoint]||0)+1,this.byMethod[n.method]=(this.byMethod[n.method]||0)+1,this.byStatus[String(n.status)]=(this.byStatus[String(n.status)]||0)+1;if(this.config.metrics?.errors!==!1&&n.isError){if(this.errorCount++,n.errorType)this.byErrorType[n.errorType]=(this.byErrorType[n.errorType]||0)+1}}recordRateLimitBlock(){if(!this.config?.enabled||this.config.metrics?.rateLimits===!1)return;this.rateLimitBlocks++}collect(){if(!this.config?.enabled)return null;let r=(Date.now()-this.lastCollectTime)/1000/60,t=r>0?Math.round(this.requestCount/r):0,o=r>0?Math.round(this.rateLimitBlocks/r):0,c=[...this.responseTimes].sort((e,s)=>e-s),i=c.length;return{requests:{total:this.requestCount,perMinute:t,byEndpoint:{...this.byEndpoint},byMethod:{...this.byMethod},byStatus:{...this.byStatus}},responseTime:{avg:i>0?Math.round(c.reduce((e,s)=>e+s,0)/i*100)/100:0,min:i>0?c[0]??0:0,max:i>0?c[i-1]??0:0,p50:i>0?c[Math.floor(i*0.5)]??0:0,p95:i>0?c[Math.floor(i*0.95)]??0:0,p99:i>0?c[Math.floor(i*0.99)]??0:0},errors:{total:this.errorCount,rate:this.requestCount>0?Math.round(this.errorCount/this.requestCount*100*100)/100:0,byType:{...this.byErrorType}},rateLimits:{blocked:this.rateLimitBlocks,blockedPerMinute:o}}}reset(){this.requestCount=0,this.responseTimes=[],this.errorCount=0,this.rateLimitBlocks=0,this.byEndpoint={},this.byMethod={},this.byStatus={},this.byErrorType={},this.lastCollectTime=Date.now()}getRequestsPerMinute(){let n=(Date.now()-this.lastCollectTime)/1000/60;return n>0?Math.round(this.requestCount/n):0}getErrorRate(){return this.requestCount>0?this.errorCount/this.requestCount*100:0}getRateLimitBlocksPerMinute(){let n=(Date.now()-this.lastCollectTime)/1000/60;return n>0?Math.round(this.rateLimitBlocks/n):0}getAvgResponseTime(){if(this.responseTimes.length===0)return 0;return this.responseTimes.reduce((n,r)=>n+r,0)/this.responseTimes.length}}import*as Lu from"fs";import*as Eo from"os";class K0{config;lastCpuInfo=null;constructor(n){this.config=n}async collect(){if(!this.config?.enabled)return null;let n={cpu:{usage:0,cores:0},memory:{total:0,used:0,free:0,usagePercent:0,heapUsed:0,heapTotal:0},disk:{total:0,used:0,free:0,usagePercent:0},network:{bytesIn:0,bytesOut:0},process:{uptime:0,pid:0,eventLoopLag:0}};if(this.config.metrics?.cpu!==!1)n.cpu=this.collectCpu();if(this.config.metrics?.memory!==!1)n.memory=this.collectMemory();if(this.config.metrics?.disk!==!1)n.disk=await this.collectDisk();if(this.config.metrics?.network)n.network=this.collectNetwork();if(this.config.metrics?.process!==!1)n.process=await this.collectProcess();return n}collectCpu(){let n=Eo.cpus(),r=n.length,t=0,o=0;for(let i of n)t+=i.times.idle,o+=i.times.user+i.times.nice+i.times.sys+i.times.idle+i.times.irq;let c=0;if(this.lastCpuInfo){let i=t-this.lastCpuInfo.idle,a=o-this.lastCpuInfo.total;c=a>0?Math.round((1-i/a)*100*100)/100:0}return this.lastCpuInfo={idle:t,total:o},{usage:c,cores:r}}collectMemory(){let n=Eo.totalmem(),r=Eo.freemem(),t=n-r,o=Math.round(t/n*100*100)/100,c=process.memoryUsage();return{total:n,used:t,free:r,usagePercent:o,heapUsed:c.heapUsed,heapTotal:c.heapTotal}}async collectDisk(){try{let n=Lu.statfsSync("/"),r=n.blocks*n.bsize,t=n.bfree*n.bsize,o=r-t,c=Math.round(o/r*100*100)/100;return{total:r,used:o,free:t,usagePercent:c}}catch{return{total:0,used:0,free:0,usagePercent:0}}}collectNetwork(){let n=Eo.networkInterfaces(),r=0,t=0;for(let o in n){let c=n[o];if(c){for(let i of c)if(!i.internal)r+=0,t+=0}}return{bytesIn:r,bytesOut:t}}async collectProcess(){let n=process.uptime(),r=process.pid,t=Date.now(),o=await new Promise((c)=>{setImmediate(()=>{c(Date.now()-t)})});return{uptime:n,pid:r,eventLoopLag:o}}}var Qu=()=>{};import{randomUUID as Gu}from"crypto";import*as Ou from"os";class Ta{store;memoryInterval=null;cpuInterval=null;lastCpuInfo=null;isRunning=!1;constructor(n){let r={...T5,...n};this.store={requests:[],configs:{logMemory:r.logMemory,logCpu:r.logCpu,logDapr:r.logDapr,logWebSocket:r.logWebSocket,cpuLogInterval:r.cpuLogInterval,memoryLogInterval:r.memoryLogInterval},logs:{memory:[],cpu:[],dapr:[],ws:[]},logLimits:{memory:r.memoryLogLimit,cpu:r.cpuLogLimit,dapr:r.daprLogLimit,ws:r.wsLogLimit,request:r.requestLogLimit},worker:{pid:process.pid,workerId:null,memory:null,cpu:null,updatedAt:Date.now()},allWorkers:[],daprEvents:[],wsEvents:[]}}start(){if(this.isRunning)return;if(this.isRunning=!0,this.store.configs.logMemory)this.startMemoryCollector();if(this.store.configs.logCpu)this.startCpuCollector()}stop(){if(!this.isRunning)return;if(this.isRunning=!1,this.memoryInterval)clearInterval(this.memoryInterval),this.memoryInterval=null;if(this.cpuInterval)clearInterval(this.cpuInterval),this.cpuInterval=null}startMemoryCollector(){if(this.memoryInterval)clearInterval(this.memoryInterval);let n=()=>{if(!this.store.configs.logMemory)return;let r=process.memoryUsage(),t={timestamp:Date.now(),rss:r.rss,heapUsed:r.heapUsed,heapTotal:r.heapTotal};if(this.store.logs.memory.push(t),this.store.logs.memory.length>this.store.logLimits.memory*2)this.store.logs.memory=this.store.logs.memory.slice(-this.store.logLimits.memory);this.store.worker.memory=t,this.store.worker.updatedAt=Date.now()};n(),this.memoryInterval=setInterval(n,this.store.configs.memoryLogInterval)}startCpuCollector(){if(this.cpuInterval)clearInterval(this.cpuInterval);let n=()=>{if(!this.store.configs.logCpu)return;let r=Ou.cpus(),t=0,o=0,c=0,i=0;for(let f of r)t+=f.times.user,o+=f.times.sys,c+=f.times.idle,i+=f.times.user+f.times.nice+f.times.sys+f.times.idle+f.times.irq;let a=0,e=0;if(this.lastCpuInfo){let f=i-this.lastCpuInfo.total,d=c-this.lastCpuInfo.idle;if(f>0){let l=f-d;a=Math.round((t-0)/(l||1)*100*100)/100,e=Math.round((o-0)/(l||1)*100*100)/100;let b=Math.round((1-d/f)*100*100)/100;a=Math.round(b*0.7*100)/100,e=Math.round(b*0.3*100)/100}}this.lastCpuInfo={idle:c,total:i};let s={timestamp:Date.now(),user:a,system:e};if(this.store.logs.cpu.push(s),this.store.logs.cpu.length>this.store.logLimits.cpu*2)this.store.logs.cpu=this.store.logs.cpu.slice(-this.store.logLimits.cpu);this.store.worker.cpu=s,this.store.worker.updatedAt=Date.now()};n(),this.cpuInterval=setInterval(n,this.store.configs.cpuLogInterval)}recordRequest(n){if(this.store.requests.push(n),this.store.requests.length>this.store.logLimits.request*2)this.store.requests=this.store.requests.slice(-this.store.logLimits.request)}recordDaprEvent(n,r){if(!this.store.configs.logDapr)return;let t={id:Gu(),type:n,timestamp:Date.now(),...r};if(this.store.logs.dapr.push(t),this.store.daprEvents.push(t),this.store.logs.dapr.length>this.store.logLimits.dapr*2)this.store.logs.dapr=this.store.logs.dapr.slice(-this.store.logLimits.dapr);if(this.store.daprEvents.length>this.store.logLimits.dapr*2)this.store.daprEvents=this.store.daprEvents.slice(-this.store.logLimits.dapr)}recordWsEvent(n,r){if(!this.store.configs.logWebSocket)return;let t={id:Gu(),type:n,timestamp:Date.now(),...r};if(this.store.logs.ws.push(t),this.store.wsEvents.push(t),this.store.logs.ws.length>this.store.logLimits.ws*2)this.store.logs.ws=this.store.logs.ws.slice(-this.store.logLimits.ws);if(this.store.wsEvents.length>this.store.logLimits.ws*2)this.store.wsEvents=this.store.wsEvents.slice(-this.store.logLimits.ws)}getSnapshot(){return{memory:this.store.logs.memory.slice(-this.store.logLimits.memory),cpu:this.store.logs.cpu.slice(-this.store.logLimits.cpu),requests:this.store.requests.slice(-this.store.logLimits.request),dapr:this.store.logs.dapr.slice(-this.store.logLimits.dapr),ws:this.store.logs.ws.slice(-this.store.logLimits.ws),workers:this.store.allWorkers.length?this.store.allWorkers:[this.store.worker],logLimits:{...this.store.logLimits},configs:{...this.store.configs}}}getUpdatesSince(n){let r=this.store.logs.memory.filter((e)=>e.timestamp>n.memory),t=this.store.logs.cpu.filter((e)=>e.timestamp>n.cpu),o=this.store.requests.filter((e)=>e.timestamp>n.request),c=this.store.logs.dapr.filter((e)=>e.timestamp>n.dapr),i=this.store.logs.ws.filter((e)=>e.timestamp>n.ws);if(!(r.length>0||t.length>0||o.length>0||c.length>0||i.length>0))return null;return{memory:r,cpu:t,requests:o,dapr:c,ws:i,timestamp:Date.now()}}getLogs(){return{memory:this.store.logs.memory,cpu:this.store.logs.cpu,requests:this.store.requests,dapr:this.store.logs.dapr,ws:this.store.logs.ws,daprEvents:this.store.daprEvents,wsEvents:this.store.wsEvents,configs:{logMemory:this.store.configs.logMemory,logCpu:this.store.configs.logCpu,logDapr:this.store.configs.logDapr,logWebSocket:this.store.configs.logWebSocket},limits:{...this.store.logLimits}}}getSettings(){return{configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}changeSettings(n){if(n.logMemory!==void 0)this.store.configs.logMemory=n.logMemory;if(n.logCpu!==void 0)this.store.configs.logCpu=n.logCpu;if(n.logDapr!==void 0)this.store.configs.logDapr=n.logDapr;if(n.logWebSocket!==void 0)this.store.configs.logWebSocket=n.logWebSocket;if(n.cpuLogInterval!==void 0){if(this.store.configs.cpuLogInterval=n.cpuLogInterval,this.isRunning&&this.store.configs.logCpu)this.startCpuCollector()}if(n.memoryLogInterval!==void 0){if(this.store.configs.memoryLogInterval=n.memoryLogInterval,this.isRunning&&this.store.configs.logMemory)this.startMemoryCollector()}if(n.memoryLogLimit!==void 0)this.store.logLimits.memory=n.memoryLogLimit;if(n.cpuLogLimit!==void 0)this.store.logLimits.cpu=n.cpuLogLimit;if(n.daprLogLimit!==void 0)this.store.logLimits.dapr=n.daprLogLimit;if(n.wsLogLimit!==void 0)this.store.logLimits.ws=n.wsLogLimit;if(n.requestLogLimit!==void 0)this.store.logLimits.request=n.requestLogLimit;return{message:"Settings updated successfully",configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}getStore(){return this.store}isEnabled(){return this.isRunning}}var T5;var Nu=g(()=>{T5={enabled:!0,logMemory:!0,logCpu:!0,logDapr:!0,logWebSocket:!0,memoryLogInterval:1000,cpuLogInterval:1000,memoryLogLimit:100,cpuLogLimit:100,daprLogLimit:100,wsLogLimit:100,requestLogLimit:100,streamInterval:150}});class v0{redis;logger;config;appId;flushToDb;systemCollector;applicationCollector;alertService;collectInterval=null;flushInterval=null;pendingMetrics=[];isRunning=!1;constructor(n){this.redis=n.redis,this.logger=n.logger,this.config=this.mergeConfig(n.config),this.appId=n.appId,this.flushToDb=n.flushToDb,this.systemCollector=new K0(this.config.system),this.applicationCollector=new j0(this.config.application),this.alertService=new ya({logger:n.logger,gmail:n.gmail,config:this.config,appId:n.appId})}mergeConfig(n){return{enabled:n.enabled??Un.enabled,system:{enabled:n.system?.enabled??Un.system.enabled,collectInterval:n.system?.collectInterval??Un.system.collectInterval,metrics:{cpu:n.system?.metrics?.cpu??Un.system.metrics.cpu,memory:n.system?.metrics?.memory??Un.system.metrics.memory,disk:n.system?.metrics?.disk??Un.system.metrics.disk,network:n.system?.metrics?.network??Un.system.metrics.network,process:n.system?.metrics?.process??Un.system.metrics.process}},application:{enabled:n.application?.enabled??Un.application.enabled,metrics:{requests:n.application?.metrics?.requests??Un.application.metrics.requests,responseTime:n.application?.metrics?.responseTime??Un.application.metrics.responseTime,errors:n.application?.metrics?.errors??Un.application.metrics.errors,rateLimits:n.application?.metrics?.rateLimits??Un.application.metrics.rateLimits}},database:{enabled:n.database?.enabled??Un.database.enabled,metrics:{connections:n.database?.metrics?.connections??Un.database.metrics.connections,queryTime:n.database?.metrics?.queryTime??Un.database.metrics.queryTime,slowQueryThreshold:n.database?.metrics?.slowQueryThreshold??Un.database.metrics.slowQueryThreshold}},redis:{enabled:n.redis?.enabled??Un.redis.enabled},persistence:{enabled:n.persistence?.enabled??Un.persistence.enabled,flushInterval:n.persistence?.flushInterval??Un.persistence.flushInterval,retentionDays:n.persistence?.retentionDays??Un.persistence.retentionDays},alerts:{enabled:n.alerts?.enabled??Un.alerts.enabled,email:{enabled:n.alerts?.email?.enabled??Un.alerts.email.enabled,recipients:n.alerts?.email?.recipients??Un.alerts.email.recipients},thresholds:{cpuPercent:n.alerts?.thresholds?.cpuPercent??Un.alerts.thresholds.cpuPercent,memoryPercent:n.alerts?.thresholds?.memoryPercent??Un.alerts.thresholds.memoryPercent,diskPercent:n.alerts?.thresholds?.diskPercent??Un.alerts.thresholds.diskPercent,errorRatePercent:n.alerts?.thresholds?.errorRatePercent??Un.alerts.thresholds.errorRatePercent,responseTimeMs:n.alerts?.thresholds?.responseTimeMs??Un.alerts.thresholds.responseTimeMs,rateLimitBlocksPerMinute:n.alerts?.thresholds?.rateLimitBlocksPerMinute??Un.alerts.thresholds.rateLimitBlocksPerMinute},cooldown:n.alerts?.cooldown??Un.alerts.cooldown}}}parseTimeToMs(n){let r=n.match(/^(\d+)(ms|s|m|h|d)$/);if(!r||!r[1]||!r[2])return 1e4;let t=parseInt(r[1],10);switch(r[2]){case"ms":return t;case"s":return t*1000;case"m":return t*60*1000;case"h":return t*60*60*1000;case"d":return t*24*60*60*1000;default:return 1e4}}start(){if(!this.config.enabled||this.isRunning)return;this.isRunning=!0,this.logger.info("[Monitoring] Starting monitoring service");let n=this.parseTimeToMs(this.config.system.collectInterval);if(this.collectInterval=setInterval(()=>{this.collect()},n),this.config.persistence.enabled&&this.flushToDb){let r=this.parseTimeToMs(this.config.persistence.flushInterval);this.flushInterval=setInterval(()=>{this.flush()},r)}this.collect()}stop(){if(!this.isRunning)return;if(this.isRunning=!1,this.logger.info("[Monitoring] Stopping monitoring service"),this.collectInterval)clearInterval(this.collectInterval),this.collectInterval=null;if(this.flushInterval)clearInterval(this.flushInterval),this.flushInterval=null;this.flush()}async collect(){let n=Date.now(),r={timestamp:n};if(this.config.system.enabled){let t=await this.systemCollector.collect();if(t)r.system=t,this.addMetricPoints("system",t,n)}if(this.config.application.enabled){let t=this.applicationCollector.collect();if(t)r.application=t,this.addMetricPoints("application",t,n)}if(await this.storeSnapshot(r),this.config.alerts.enabled)await this.alertService.checkAndAlert(r)}addMetricPoints(n,r,t){let o=(c,i="")=>{for(let a in c){let e=c[a],s=i?`${i}.${a}`:a;if(typeof e==="number")this.pendingMetrics.push({timestamp:t,metricType:n,metricName:s,value:e});else if(typeof e==="object"&&e!==null&&!Array.isArray(e))o(e,s)}};o(r)}async storeSnapshot(n){let r=`monitoring:${this.appId}:latest`;await this.redis.create(r,n,3600);let t=`monitoring:${this.appId}:history`,o=await this.redis.read(t),c=o.success&&o.data?o.data:[];c.push(n);let i=Date.now()-3600000,a=c.filter((e)=>e.timestamp>i);await this.redis.create(t,a,3600)}async flush(){if(this.pendingMetrics.length===0)return;if(!this.flushToDb)return;let n=[...this.pendingMetrics];this.pendingMetrics=[];try{await this.flushToDb(n),this.logger.debug(`[Monitoring] Flushed ${n.length} metrics to database`)}catch(r){this.logger.error(`[Monitoring] Failed to flush metrics: ${r}`),this.pendingMetrics=[...n,...this.pendingMetrics]}}recordRequest(n){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRequest(n)}recordRateLimitBlock(){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRateLimitBlock()}async getLatestSnapshot(){let n=`monitoring:${this.appId}:latest`,r=await this.redis.read(n);return r.success?r.data:null}async getHistory(n=60){let r=`monitoring:${this.appId}:history`,t=await this.redis.read(r);if(!t.success||!t.data)return[];let o=Date.now()-n*60000;return t.data.filter((c)=>c.timestamp>o)}getActiveAlerts(){return this.alertService.getActiveAlerts()}acknowledgeAlert(n){return this.alertService.acknowledgeAlert(n)}isEnabled(){return this.config.enabled}getConfig(){return this.config}}var Un;var xu=g(()=>{Qu();Nu();Un={enabled:!1,system:{enabled:!0,collectInterval:"10s",metrics:{cpu:!0,memory:!0,disk:!0,network:!1,process:!0}},application:{enabled:!0,metrics:{requests:!0,responseTime:!0,errors:!0,rateLimits:!0}},database:{enabled:!1,metrics:{connections:!0,queryTime:!0,slowQueryThreshold:"100ms"}},redis:{enabled:!1},persistence:{enabled:!0,flushInterval:"1m",retentionDays:30},alerts:{enabled:!1,email:{enabled:!1,recipients:[]},thresholds:{cpuPercent:80,memoryPercent:85,diskPercent:90,errorRatePercent:5,responseTimeMs:1000,rateLimitBlocksPerMinute:100},cooldown:"5m"}}});var Pu=()=>{};import{and as Hc,desc as Cu,eq as er}from"drizzle-orm";function Z0(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());r[c]=o}return r}function n$(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/[A-Z]/g,(i)=>`_${i.toLowerCase()}`);r[c]=o}return r}class I0{db;schemaTables;config;logger;gmailService;constructor(n){this.db=n.db,this.schemaTables=n.schemaTables,this.config=n.config,this.logger=n.logger,this.gmailService=n.gmailService}getTable(n){return this.schemaTables[n]}getCol(n,r){return n[r]}isChannelEnabled(n){let r=this.config.channels;if(!r)return n==="portal";switch(n){case"portal":return r.portal!==!1;case"email":return r.email===!0;case"sms":return r.sms?.enabled===!0;case"telegram":return r.telegram?.enabled===!0;case"webhook":return r.webhook?.enabled===!0;default:return!1}}interpolateTemplate(n,r){let t=n;for(let[o,c]of Object.entries(r))t=t.replace(new RegExp(`{{${o}}}`,"g"),String(c??""));for(let[o,c]of Object.entries(this.config.templateVariables||{}))t=t.replace(new RegExp(`{{${o}}}`,"g"),c);return t}async triggerNotifications(n){let{trigger:r,flow_id:t,entity_name:o,entity_id:c,node_id:i,context:a={}}=n,e=this.getTable("verificationNotificationRules"),s=this.getTable("verificationNotificationRecipients"),f=this.getTable("verificationNotificationChannels");if(!e||!s){this.logger.warn("[Notification] Notification tables not found");return}let d=new Date,b=await this.db.select().from(e).where(Hc(er(this.getCol(e,"flowId"),t),er(this.getCol(e,"trigger"),r)));this.logger.info(`[Notification] Found ${b.length} rules for trigger=${r} flow_id=${t}`);let w=b.filter((u)=>{if(i&&u.nodeId!==i)return!1;if(u.startsAt&&new Date(u.startsAt)>d)return!1;if(u.expiresAt&&new Date(u.expiresAt)<d)return!1;return!0});for(let u of w){let m=await this.db.select().from(s).where(er(this.getCol(s,"ruleId"),u.id)),_=["portal"];if(f){let H=await this.db.select().from(f).where(er(this.getCol(f,"ruleId"),u.id));if(H.length>0)_=H.map((D)=>D.channel)}let S=_.filter((H)=>this.isChannelEnabled(H));if(S.length===0)continue;this.logger.info(`[Notification] Rule ${u.id}: ${m.length} recipients, ${S.length} channels (${S.join(",")})`);let $=await this.resolveRecipients(m,n.verifier_id,t,o,c);this.logger.info(`[Notification] Rule ${u.id}: resolved ${$.length} user IDs: ${$.join(", ")}`);let E={...a,entity_name:o,entity_id:c,trigger:r,decision:n.decision};this.logger.info(`[Notification] Rule ${u.id}: titleTemplate=${JSON.stringify(u.titleTemplate)}, bodyTemplate=${JSON.stringify(u.bodyTemplate)}, context=${JSON.stringify(E)}`);let W=u.titleTemplate?this.interpolateTemplate(u.titleTemplate,E):`Verification ${r.replace("on_","").replace("_"," ")}`,Y=u.bodyTemplate?this.interpolateTemplate(u.bodyTemplate,E):void 0;this.logger.info(`[Notification] Rule ${u.id}: final title="${W}", body="${Y}"`);for(let H of $)await this.send({user_id:H,title:W,body:Y,entity_name:o,entity_id:c,type:"verification",source:`flow:${t}`,channels:S})}this.logger.debug(`[Notification] Triggered ${w.length} rules for ${r} on ${o}:${c}`)}async resolveRecipients(n,r,t,o,c){let i=new Set,a=this.getTable("user_roles"),e=this.getTable("roles");for(let s of n)switch(s.recipientType){case"user":if(s.recipientUserId)i.add(s.recipientUserId);break;case"role":if(s.recipientRole&&a&&e){let f=e,d=a,b=(await this.db.select().from(e).where(er(f.name,s.recipientRole)).limit(1))[0];if(b){let w=await this.db.select({user_id:d.userId}).from(a).where(er(d.roleId,b.id));for(let u of w)i.add(u.user_id)}}break;case"step_verifier":if(r)i.add(r);break;case"entity_creator":{if(o&&c){let f=this.getTable("verificationInstances");if(f){let l=(await this.db.select().from(f).where(Hc(er(this.getCol(f,"entityName"),o),er(this.getCol(f,"entityId"),c))).orderBy(Cu(this.getCol(f,"createdAt"))).limit(1))[0];if(l?.startedBy)i.add(l.startedBy)}}break}case"all_verifiers":{if(t){let f=this.getTable("verificationVerifierConfigs");if(f){let d=await this.db.select().from(f).where(er(this.getCol(f,"flowId"),t));for(let l of d){let b=l;if(b.verifierUserId)i.add(b.verifierUserId);if(b.verifierType==="role"&&b.verifierRole&&a&&e){let w=e,u=a,_=(await this.db.select().from(e).where(er(w.name,b.verifierRole)).limit(1))[0];if(_){let S=await this.db.select({user_id:u.userId}).from(a).where(er(u.roleId,_.id));for(let $ of S)i.add($.user_id)}}}}}break}}return Array.from(i)}async send(n){let{user_id:r,title:t,body:o,entity_name:c,entity_id:i,type:a,source:e,channels:s}=n;for(let f of s)switch(f){case"portal":await this.sendPortalNotification(r,t,o,c,i,a,e);break;case"email":await this.sendEmailNotification(r,t,o);break;case"sms":this.logger.debug(`[Notification] SMS channel not yet implemented for user ${r}`);break;case"telegram":this.logger.debug(`[Notification] Telegram channel not yet implemented for user ${r}`);break;case"webhook":this.logger.debug(`[Notification] Webhook channel not yet implemented for user ${r}`);break}}async sendPortalNotification(n,r,t,o,c,i,a){let e=this.getTable("notifications");if(!e){this.logger.warn("[Notification] notifications table not found");return}await this.db.insert(e).values(Z0({user_id:n,title:r,body:t||null,entity_name:o||null,entity_id:c||null,type:i||"system",source:a||null,is_seen:!1})),this.logger.debug(`[Notification] Portal notification sent to ${n}: ${r}`)}async sendEmailNotification(n,r,t){if(!this.gmailService?.isAvailable()){this.logger.warn("[Notification] Gmail service not available for email notification");return}let o=this.getTable("users");if(!o){this.logger.warn("[Notification] users table not found");return}let i=(await this.db.select({email:this.getCol(o,"email")}).from(o).where(er(this.getCol(o,"id"),n)).limit(1))[0];if(!i?.email){this.logger.warn(`[Notification] No email found for user ${n}`);return}await this.gmailService.sendEmail({to:i.email,subject:r,html:t||r}),this.logger.debug(`[Notification] Email notification sent to ${i.email}: ${r}`)}async getNotifications(n,r){let t=this.getTable("notifications");if(!t)return[];let o=[er(this.getCol(t,"userId"),n)];if(r?.type)o.push(er(this.getCol(t,"type"),r.type));return(await this.db.select().from(t).where(Hc(...o)).orderBy(Cu(this.getCol(t,"createdAt"))).limit(r?.limit||50).offset(r?.offset||0)).map((a)=>n$(a))}async getUnseenCount(n){let r=this.getTable("notifications");if(!r)return 0;return(await this.db.select().from(r).where(Hc(er(this.getCol(r,"userId"),n),er(this.getCol(r,"isSeen"),!1)))).length}async markAsSeen(n,r){let t=this.getTable("notifications");if(!t)return!1;return await this.db.update(t).set(Z0({is_seen:!0,seen_at:new Date})).where(Hc(er(this.getCol(t,"id"),n),er(this.getCol(t,"userId"),r))),!0}async markAllAsSeen(n){let r=this.getTable("notifications");if(!r)return 0;return(await this.db.update(r).set(Z0({is_seen:!0,seen_at:new Date})).where(Hc(er(this.getCol(r,"userId"),n),er(this.getCol(r,"isSeen"),!1))).returning()).length}}var p0=g(()=>{Pu()});function qu(n,r){if(!n.authorizationUrl)throw Error("Generic OAuth provider requires authorizationUrl");let t=n.scopes??[],o=new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",state:r,...t.length>0?{scope:t.join(" ")}:{},...n.extraAuthParams});return`${n.authorizationUrl}?${o.toString()}`}async function Fu(n,r){if(!r.tokenUrl)throw Error("Generic OAuth provider requires tokenUrl");let t=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Generic OAuth token exchange failed: ${s}`)}let o=await t.json();if(o.error)throw Error(`OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope};if(!r.userInfoUrl)return{profile:{providerAccountId:o.access_token,rawProfile:o},tokens:c};let i=await fetch(r.userInfoUrl,{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch user info from generic OAuth provider");let a=await i.json();return{profile:{providerAccountId:a.id??a.sub??a.user_id??o.access_token,email:a.email,name:a.name??a.display_name??a.username,avatarUrl:a.avatar_url??a.picture??a.photo,rawProfile:a},tokens:c}}function ju(n,r){let t=n.scopes??["read:user","user:email"];return`https://github.com/login/oauth/authorize?${new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,scope:t.join(" "),state:r,...n.extraAuthParams}).toString()}`}async function Ku(n,r){let t=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri}).toString()});if(!t.ok){let f=await t.text();throw Error(`GitHub token exchange failed: ${f}`)}let o=await t.json();if(o.error)throw Error(`GitHub OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${o.access_token}`,Accept:"application/vnd.github+json"}});if(!i.ok)throw Error("Failed to fetch GitHub user info");let a=await i.json(),e=a.email;if(!e)try{let f=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${o.access_token}`,Accept:"application/vnd.github+json"}});if(f.ok){let d=await f.json();e=d.find((b)=>b.primary&&b.verified)?.email??d[0]?.email}}catch{}return{profile:{providerAccountId:String(a.id),email:e,name:a.name??a.login,avatarUrl:a.avatar_url,rawProfile:a},tokens:c}}function vu(n,r){let t=n.scopes??["openid","email","profile"];return`https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",scope:t.join(" "),state:r,access_type:"offline",prompt:"select_account",...n.extraAuthParams}).toString()}`}async function Zu(n,r){let t=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Google token exchange failed: ${s}`)}let o=await t.json(),c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://www.googleapis.com/oauth2/v3/userinfo",{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch Google user info");let a=await i.json();return{profile:{providerAccountId:a.sub,email:a.email,name:a.name,avatarUrl:a.picture,rawProfile:a},tokens:c}}function Iu(n){return`https://login.microsoftonline.com/${n.tenantId??"common"}/oauth2/v2.0`}function pu(n,r){let t=n.scopes??["openid","email","profile","User.Read"],o=new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",scope:t.join(" "),state:r,response_mode:"query",...n.extraAuthParams});return`${Iu(n)}/authorize?${o.toString()}`}async function yu(n,r){let t=await fetch(`${Iu(r)}/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Microsoft token exchange failed: ${s}`)}let o=await t.json();if(o.error)throw Error(`Microsoft OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://graph.microsoft.com/v1.0/me",{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch Microsoft user info");let a=await i.json();return{profile:{providerAccountId:a.id,email:a.mail??a.userPrincipalName,name:a.displayName,avatarUrl:void 0,rawProfile:a},tokens:c}}import{randomBytes as r$}from"crypto";class ne{config;stateStore=new Map;cleanupInterval=null;constructor(n){this.config=n;let r=(n.stateTtlSeconds??600)*1000;this.cleanupInterval=setInterval(()=>{let t=Date.now();for(let[o,c]of this.stateStore.entries())if(c.expiresAt<t)this.stateStore.delete(o)},r)}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isProviderEnabled(n){return!!(this.config.enabled&&this.config.providers[n])}getEnabledProviders(){if(!this.config.enabled)return[];return Object.keys(this.config.providers)}buildAuthorizationUrl(n,r,t){let o=this.config.providers[n];if(!o)throw Error(`OAuth provider "${n}" is not configured`);let c={provider:n,linkUserId:r,redirectUrl:t,createdAt:Date.now()},i=r$(32).toString("hex"),a=(this.config.stateTtlSeconds??600)*1000;switch(this.stateStore.set(i,{payload:c,expiresAt:Date.now()+a}),n){case"google":return vu(o,i);case"github":return ju(o,i);case"microsoft":return pu(o,i);default:return qu(o,i)}}consumeState(n){let r=this.stateStore.get(n);if(!r)return null;if(r.expiresAt<Date.now())return this.stateStore.delete(n),null;return this.stateStore.delete(n),r.payload}async exchangeCode(n,r){let t=this.config.providers[n];if(!t)throw Error(`OAuth provider "${n}" is not configured`);switch(n){case"google":return Zu(r,t);case"github":return Ku(r,t);case"microsoft":return yu(r,t);default:return Fu(r,t)}}get allowAccountLinking(){return this.config.allowAccountLinking??!0}get autoCreateUser(){return this.config.autoCreateUser??!0}get successRedirectUrl(){return this.config.successRedirectUrl??"/"}get errorRedirectUrl(){return this.config.errorRedirectUrl??"/login"}get sendInviteOnCreate(){return this.config.sendInviteOnCreate??!1}get basePath(){return this.config.basePath??"/auth/oauth"}}var Tu=()=>{};var y0=g(()=>{Tu()});class T0{redis;logger;config;constructor(n){this.redis=n.redis,this.logger=n.logger,this.config=this.mergeConfig(n.config)}mergeConfig(n){return{enabled:n.enabled??$r.enabled,strategy:n.strategy??$r.strategy,keyPrefix:n.keyPrefix??$r.keyPrefix,authRoutes:{window:n.authRoutes?.window??$r.authRoutes.window,max:n.authRoutes?.max??$r.authRoutes.max,login:{window:n.authRoutes?.login?.window??re.window,max:n.authRoutes?.login?.max??re.max,blockDuration:n.authRoutes?.login?.blockDuration??re.blockDuration},register:{window:n.authRoutes?.register?.window??te.window,max:n.authRoutes?.register?.max??te.max,blockDuration:n.authRoutes?.register?.blockDuration??te.blockDuration},passwordReset:{window:n.authRoutes?.passwordReset?.window??oe.window,max:n.authRoutes?.passwordReset?.max??oe.max,blockDuration:n.authRoutes?.passwordReset?.blockDuration??oe.blockDuration},magicLink:{window:n.authRoutes?.magicLink?.window??ce.window,max:n.authRoutes?.magicLink?.max??ce.max,blockDuration:n.authRoutes?.magicLink?.blockDuration??ce.blockDuration}},publicRoutes:{window:n.publicRoutes?.window??$r.publicRoutes.window,max:n.publicRoutes?.max??$r.publicRoutes.max},privateRoutes:{window:n.privateRoutes?.window??$r.privateRoutes.window,max:n.privateRoutes?.max??$r.privateRoutes.max},byIp:n.byIp??$r.byIp,byUserId:n.byUserId??$r.byUserId,byEndpoint:n.byEndpoint??$r.byEndpoint,skipSuccessfulRequests:n.skipSuccessfulRequests??$r.skipSuccessfulRequests,headers:{remaining:n.headers?.remaining??$r.headers.remaining,reset:n.headers?.reset??$r.headers.reset,limit:n.headers?.limit??$r.headers.limit},whitelist:n.whitelist??$r.whitelist,blacklist:n.blacklist??$r.blacklist}}parseTimeToMs(n){let r=n.match(/^(\d+)(ms|s|m|h|d)$/);if(!r||!r[1]||!r[2])return 60000;let t=parseInt(r[1],10);switch(r[2]){case"ms":return t;case"s":return t*1000;case"m":return t*60*1000;case"h":return t*60*60*1000;case"d":return t*24*60*60*1000;default:return 60000}}buildKey(n){let r=[this.config.keyPrefix,n.category];if(n.authType&&n.authType!=="other")r.push(n.authType);if(this.config.byIp&&n.ip)r.push(`ip:${n.ip}`);if(this.config.byUserId&&n.userId)r.push(`user:${n.userId}`);if(this.config.byEndpoint&&n.endpoint)r.push(`ep:${n.endpoint.replace(/\//g,"_")}`);return r.join(":")}getLimits(n,r){if(n==="auth"){if(r&&r!=="other"){let t=this.config.authRoutes[r];if(t)return t}return{window:this.config.authRoutes.window,max:this.config.authRoutes.max}}if(n==="public")return this.config.publicRoutes;return this.config.privateRoutes}isWhitelisted(n){return this.config.whitelist.some((r)=>{if(r.includes("*"))return new RegExp(`^${r.replace(/\*/g,".*")}$`).test(n);return r===n})}isBlacklisted(n){return this.config.blacklist.some((r)=>{if(r.includes("*"))return new RegExp(`^${r.replace(/\*/g,".*")}$`).test(n);return r===n})}async readRedis(n){let r=await this.redis.read(n);if(r.success)return r.data;return null}async check(n){if(!this.config.enabled)return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isWhitelisted(n.ip))return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isBlacklisted(n.ip))return this.logger.warn(`[RateLimit] Blacklisted IP: ${n.ip}`),{allowed:!1,remaining:0,resetAt:Date.now()+86400000,limit:0,retryAfter:86400};let r=this.buildKey(n),t=this.getLimits(n.category,n.authType),o=this.parseTimeToMs(t.window),c=`${r}:blocked`,i=await this.readRedis(c);if(i&&i.until>Date.now()){let a=Math.ceil((i.until-Date.now())/1000);return this.logger.warn(`[RateLimit] Blocked: ${r}, retry after ${a}s`),{allowed:!1,remaining:0,resetAt:i.until,limit:t.max,retryAfter:a}}if(this.config.strategy==="sliding-window")return this.slidingWindowCheck(r,t.max,o,t.blockDuration);if(this.config.strategy==="fixed-window")return this.fixedWindowCheck(r,t.max,o,t.blockDuration);return this.tokenBucketCheck(r,t.max,o)}async slidingWindowCheck(n,r,t,o){let c=Date.now(),i=c-t,a=`${n}:sw`,s=(await this.readRedis(a))?.timestamps||[];s=s.filter((b)=>b>i);let f=s.length,d=s[0],l=d!==void 0?d+t:c+t;if(f>=r){if(o){let b=this.parseTimeToMs(o);await this.redis.create(`${n}:blocked`,{until:c+b},Math.ceil(b/1000))}return{allowed:!1,remaining:0,resetAt:l,limit:r,retryAfter:Math.ceil((l-c)/1000)}}return s.push(c),await this.redis.create(a,{timestamps:s},Math.ceil(t/1000)+1),{allowed:!0,remaining:r-s.length,resetAt:l,limit:r}}async fixedWindowCheck(n,r,t,o){let c=Date.now(),i=Math.floor(c/t),a=`${n}:fw:${i}`,e=(i+1)*t,f=(await this.readRedis(a))?.count||0;if(f>=r){if(o){let d=this.parseTimeToMs(o);await this.redis.create(`${n}:blocked`,{until:c+d},Math.ceil(d/1000))}return{allowed:!1,remaining:0,resetAt:e,limit:r,retryAfter:Math.ceil((e-c)/1000)}}return await this.redis.create(a,{count:f+1},Math.ceil(t/1000)+1),{allowed:!0,remaining:r-(f+1),resetAt:e,limit:r}}async tokenBucketCheck(n,r,t){let o=Date.now(),c=r/t,i=`${n}:tb`,a=await this.readRedis(i),e=a?.tokens??r,s=a?.lastRefill??o,d=(o-s)*c;if(e=Math.min(r,e+d),e<1){let l=Math.ceil((1-e)/c);return{allowed:!1,remaining:0,resetAt:o+l,limit:r,retryAfter:Math.ceil(l/1000)}}return e-=1,await this.redis.create(i,{tokens:e,lastRefill:o},Math.ceil(t/1000)*2),{allowed:!0,remaining:Math.floor(e),resetAt:o+t,limit:r}}async decrement(n){if(!this.config.skipSuccessfulRequests)return;let r=this.buildKey(n);if(this.config.strategy==="sliding-window"){let t=`${r}:sw`,o=await this.readRedis(t);if(o?.timestamps?.length){o.timestamps.pop();let c=this.parseTimeToMs(this.getLimits(n.category,n.authType).window);await this.redis.create(t,o,Math.ceil(c/1000)+1)}}else if(this.config.strategy==="fixed-window"){let t=this.parseTimeToMs(this.getLimits(n.category,n.authType).window),o=Math.floor(Date.now()/t),c=`${r}:fw:${o}`,i=await this.readRedis(c);if(i?.count)await this.redis.create(c,{count:i.count-1},Math.ceil(t/1000)+1)}}getHeaders(n){let r={};return r[this.config.headers.remaining]=String(n.remaining),r[this.config.headers.reset]=String(Math.ceil(n.resetAt/1000)),r[this.config.headers.limit]=String(n.limit),r}isEnabled(){return this.config.enabled}}var re,te,oe,ce,$r;var nb=g(()=>{re={window:"15m",max:5,blockDuration:"30m"},te={window:"1h",max:3,blockDuration:"1h"},oe={window:"1h",max:3,blockDuration:"1h"},ce={window:"1h",max:5,blockDuration:"1h"},$r={enabled:!0,strategy:"sliding-window",keyPrefix:"rl:",authRoutes:{window:"1m",max:10,login:re,register:te,passwordReset:oe,magicLink:ce},publicRoutes:{window:"1m",max:100},privateRoutes:{window:"1m",max:60},byIp:!0,byUserId:!0,byEndpoint:!1,skipSuccessfulRequests:!1,headers:{remaining:"X-RateLimit-Remaining",reset:"X-RateLimit-Reset",limit:"X-RateLimit-Limit"},whitelist:[],blacklist:[]}});var rb=()=>{};import{and as Xt,desc as nf,eq as on,inArray as tb}from"drizzle-orm";function zr(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());r[c]=o}return r}function Sr(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/[A-Z]/g,(i)=>`_${i.toLowerCase()}`);r[c]=o}return r}class rf{db;schemaTables;config;logger;onNotificationTrigger;constructor(n){this.db=n.db,this.schemaTables=n.schemaTables,this.config=n.config,this.logger=n.logger}setNotificationHandler(n){this.onNotificationTrigger=n}getConnectedNotificationNodeIds(n,r,t){let o=[];for(let c of t){let{sourceNodeId:i,targetNodeId:a}=c;if(i===n||a===n){let e=i===n?a:i,s=r.find((f)=>f.nodeId===e&&f.nodeType==="notification");if(s)o.push(s.nodeId)}}return o}getTable(n){return this.schemaTables[n]}getCol(n,r){return n[r]}async listFlows(n){let r=this.getTable("verificationFlows");if(!r)return[];return(await(n?this.db.select().from(r).where(on(this.getCol(r,"entityName"),n)):this.db.select().from(r))).map((c)=>Sr(c))}async getFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationNotificationRules"),a=this.getTable("verificationNotificationRecipients"),e=this.getTable("verificationNotificationChannels");if(!r)return null;let f=(await this.db.select().from(r).where(on(this.getCol(r,"id"),n)).limit(1))[0];if(!f)return null;let d=Sr(f),b=(t?await this.db.select().from(t).where(on(this.getCol(t,"flowId"),n)):[]).map((R)=>Sr(R)),u=(o?await this.db.select().from(o).where(on(this.getCol(o,"flowId"),n)):[]).map((R)=>Sr(R)),_=(c?await this.db.select().from(c).where(on(this.getCol(c,"flowId"),n)):[]).map((R)=>Sr(R)),$=(i?await this.db.select().from(i).where(on(this.getCol(i,"flowId"),n)):[]).map((R)=>Sr(R)),E=$.map((R)=>R.id),Y=(a&&E.length>0?await this.db.select().from(a).where(tb(this.getCol(a,"ruleId"),E)):[]).map((R)=>Sr(R)),D=(e&&E.length>0?await this.db.select().from(e).where(tb(this.getCol(e,"ruleId"),E)):[]).map((R)=>Sr(R));return{flow:d,graph:{steps:b,edges:u,verifier_configs:_,notification_rules:$,notification_recipients:Y,notification_channels:D}}}async saveFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationNotificationRules"),a=this.getTable("verificationNotificationRecipients"),e=this.getTable("verificationNotificationChannels");if(!r||!t||!o)throw Error("Verification tables not configured");let s=await this.db.select().from(r).where(on(this.getCol(r,"id"),n.flow_id)).limit(1),f=n.flow_id;if(s.length>0)await this.db.update(r).set(zr({entity_name:n.entity_name,name:n.name,description:n.description||null,trigger_on:n.trigger_on,trigger_fields:n.trigger_fields||null,is_draft:n.is_draft,viewport:n.viewport||null})).where(on(this.getCol(r,"id"),f));else{let[l]=await this.db.insert(r).values(zr({id:f,entity_name:n.entity_name,name:n.name,description:n.description||null,trigger_on:n.trigger_on,trigger_fields:n.trigger_fields||null,is_draft:n.is_draft,viewport:n.viewport||null})).returning();f=l.id}if(await this.db.delete(t).where(on(this.getCol(t,"flowId"),f)),o)await this.db.delete(o).where(on(this.getCol(o,"flowId"),f));if(c)await this.db.delete(c).where(on(this.getCol(c,"flowId"),f));if(i)await this.db.delete(i).where(on(this.getCol(i,"flowId"),f));let{graph:d}=n;if(d.steps.length>0)await this.db.insert(t).values(d.steps.map((l)=>zr({flow_id:f,entity_name:n.entity_name,node_id:l.node_id,node_type:l.node_type,step_order:l.step_order,name:l.name||null,description:l.description||null,position_x:l.position_x,position_y:l.position_y,width:l.width||null,height:l.height||null,style:l.style||null,data:l.data||null})));if(d.edges.length>0&&o)await this.db.insert(o).values(d.edges.map((l)=>zr({flow_id:f,edge_id:l.edge_id,source_node_id:l.source_node_id,target_node_id:l.target_node_id,source_handle:l.source_handle||null,target_handle:l.target_handle||null,edge_type:l.edge_type,label:l.label||null,condition:l.condition||null,style:l.style||null,animated:l.animated})));if(d.verifier_configs.length>0&&c)await this.db.insert(c).values(d.verifier_configs.map((l)=>zr({flow_id:f,node_id:l.node_id,verifier_type:l.verifier_type,verifier_user_id:l.verifier_user_id||null,verifier_role:l.verifier_role||null,require_signature:l.require_signature,all_must_approve:l.all_must_approve})));if(d.notification_rules.length>0&&i)for(let l of d.notification_rules){this.logger.info(`[Verification] Saving notification rule: node_id=${l.node_id}, trigger=${l.trigger}, title_template=${JSON.stringify(l.title_template)}, body_template=${JSON.stringify(l.body_template)}`);let[b]=await this.db.insert(i).values(zr({flow_id:f,node_id:l.node_id,trigger:l.trigger,title_template:l.title_template||null,body_template:l.body_template||null,starts_at:l.starts_at||null,expires_at:l.expires_at||null})).returning(),w=b.id,u=d.notification_recipients.filter((_)=>_.rule_id===l.node_id);if(u.length>0&&a)await this.db.insert(a).values(u.map((_)=>zr({rule_id:w,recipient_type:_.recipient_type,recipient_user_id:_.recipient_user_id||null,recipient_role:_.recipient_role||null})));let m=d.notification_channels.filter((_)=>_.rule_id===l.node_id);if(m.length>0&&e)await this.db.insert(e).values(m.map((_)=>zr({rule_id:w,channel:_.channel})))}return this.logger.info(`[Verification] Flow saved: ${f} for ${n.entity_name}`),{success:!0,flow_id:f}}async publishFlow(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};return await this.db.update(r).set(zr({is_draft:!1,published_at:new Date})).where(on(this.getCol(r,"id"),n)),this.logger.info(`[Verification] Flow published: ${n}`),{success:!0,message:"Flow published"}}async deleteFlow(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};return await this.db.delete(r).where(on(this.getCol(r,"id"),n)),this.logger.info(`[Verification] Flow deleted: ${n}`),{success:!0,message:"Flow deleted"}}async startFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationInstances"),a=this.getTable("verificationRequirements"),e=this.getTable("user_roles");if(!r||!t||!o||!i||!a)return{success:!1,message:"Verification tables not configured"};let f=(await this.db.select().from(r).where(Xt(on(this.getCol(r,"id"),n.flow_id),on(this.getCol(r,"isDraft"),!1))).limit(1))[0];if(!f)return{success:!1,message:"Published flow not found"};if((await this.db.select().from(i).where(Xt(on(this.getCol(i,"entityName"),n.entity_name),on(this.getCol(i,"entityId"),n.entity_id),on(this.getCol(i,"status"),"active"))).limit(1)).length>0)return{success:!1,message:"An active verification instance already exists for this entity"};let l=await this.db.select().from(t).where(on(this.getCol(t,"flowId"),n.flow_id)),b=await this.db.select().from(o).where(on(this.getCol(o,"flowId"),n.flow_id)),w=l.filter((_)=>_.nodeType==="step");if(w.sort((_,S)=>_.stepOrder-S.stepOrder),w.length===0)return{success:!1,message:"Flow has no step nodes"};let[u]=await this.db.insert(i).values(zr({flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,started_by:n.started_by||null,status:"active",current_step_order:1,started_at:new Date})).returning(),m=u.id;if(await this.materializeRequirementsForStep(m,n.flow_id,n.entity_name,n.entity_id,1,l,b,c,a,e),this.onNotificationTrigger){let _=w[0],S=_?.nodeId,$=S?this.getConnectedNotificationNodeIds(S,l,b):[],E={flow_name:f.name,step_name:_?.name||"Step 1",step_order:1,total_steps:w.length};if($.length>0)for(let W of $)await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,node_id:W,context:E});else await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,context:E})}return this.logger.info(`[Verification] Flow started: instance ${m} for ${n.entity_name}:${n.entity_id}`),{success:!0,instance_id:m,message:"Flow started"}}async materializeRequirementsForStep(n,r,t,o,c,i,a,e,s,f){if(!s)return;let d=i.find((_)=>_.nodeType==="step"&&_.stepOrder===c);if(!d)return;let l=d.nodeId,w=a.filter((_)=>_.targetNodeId===l).map((_)=>_.sourceNodeId),u=i.filter((_)=>_.nodeType==="verifier"&&w.includes(_.nodeId));if(u.length===0)return;let m=[];if(e)m=await this.db.select().from(e).where(on(this.getCol(e,"flowId"),r));for(let _ of u){let S=_.nodeId,$=m.find((Y)=>Y.nodeId===S);if(!$)continue;let{verifierType:E,allMustApprove:W}=$;if(E==="role"&&W&&f){let Y=this.getTable("roles");if(Y){let H=Y,D=f,h=(await this.db.select().from(Y).where(on(H.name,$.verifierRole)).limit(1))[0];if(h){let A=await this.db.select({user_id:D.userId}).from(f).where(on(D.roleId,h.id));for(let M of A)await this.db.insert(s).values(zr({instance_id:n,step_node_id:l,verifier_node_id:S,entity_name:t,entity_id:o,verifier_type:"user",verifier_user_id:M.user_id,verifier_role:$.verifierRole||null,require_signature:$.requireSignature,all_must_approve:!0,step_order:c,status:"pending"}))}}}else await this.db.insert(s).values(zr({instance_id:n,step_node_id:l,verifier_node_id:S,entity_name:t,entity_id:o,verifier_type:E,verifier_user_id:$.verifierUserId||null,verifier_role:$.verifierRole||null,require_signature:$.requireSignature,all_must_approve:W,step_order:c,status:"pending"}))}if(this.onNotificationTrigger){let _=this.getConnectedNotificationNodeIds(l,i,a);if(_.length>0)for(let S of _)await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:r,entity_name:t,entity_id:o,node_id:S,context:{step_name:d.name||`Step ${c}`,step_order:c}});else await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:r,entity_name:t,entity_id:o,context:{step_name:d.name||`Step ${c}`,step_order:c}})}}async getStatus(n,r){let t=this.getTable("verificationInstances"),o=this.getTable("verificationFlows"),c=this.getTable("verificationSteps"),i=this.getTable("verifications"),a=this.getTable("verificationRequirements"),e={entity_name:n,entity_id:r,instance:null,flow:null,current_step:0,total_steps:0,is_completed:!1,is_rejected:!1,verifications:[],pending_requirements:[]};if(!t||!o||!i||!a)return this.logger.error("[Verification] Required tables not found"),e;let f=(await this.db.select().from(t).where(Xt(on(this.getCol(t,"entityName"),n),on(this.getCol(t,"entityId"),r))).orderBy(nf(this.getCol(t,"createdAt"))).limit(1))[0];if(!f)return e;let d=Sr(f),l=await this.db.select().from(o).where(on(this.getCol(o,"id"),d.flow_id)).limit(1),b=l[0]?Sr(l[0]):void 0,u=(c?await this.db.select().from(c).where(Xt(on(this.getCol(c,"flowId"),d.flow_id),on(this.getCol(c,"nodeType"),"step"))):[]).length,_=(await this.db.select().from(i).where(on(this.getCol(i,"instanceId"),d.id)).orderBy(nf(this.getCol(i,"createdAt")))).map((E)=>Sr(E)),$=(await this.db.select().from(a).where(Xt(on(this.getCol(a,"instanceId"),d.id),on(this.getCol(a,"status"),"pending")))).map((E)=>Sr(E));return{entity_name:n,entity_id:r,instance:d,flow:b||null,current_step:d.current_step_order,total_steps:u,is_completed:d.status==="completed",is_rejected:d.status==="rejected",verifications:_,pending_requirements:$}}async decide(n){let{entity_name:r,entity_id:t,user_id:o,decision:c,reason:i,signature_id:a,diff:e}=n,s=this.getTable("verifications"),f=this.getTable("verificationRequirements"),d=this.getTable("verificationInstances"),l=this.getTable("verificationSteps"),b=this.getTable("verificationEdges"),w=this.getTable("verificationVerifierConfigs"),u=this.getTable("user_roles"),m=this.getTable("roles");if(!s||!f||!d)return{success:!1,message:"Verification tables not configured"};let _=await this.getStatus(r,t);if(!_.instance||_.instance.status!=="active")return{success:!1,message:"No active verification instance"};let S=_.pending_requirements.filter((R)=>R.step_order===_.current_step);if(S.length===0)return{success:!1,message:"No pending requirements for current step"};let $=null;for(let R of S){if(R.verifier_type==="user"&&R.verifier_user_id===o){$=R;break}if(R.verifier_type==="role"&&R.verifier_role&&u&&m){let h=u,A=m;if((await this.db.select({role_name:A.name}).from(u).innerJoin(m,on(h.roleId,A.id)).where(on(h.userId,o))).some((V)=>V.role_name===R.verifier_role)){$=R;break}}}if(!$)return{success:!1,message:"User is not authorized to verify at this step"};if($.require_signature&&!a)return{success:!1,message:"Signature is required for this verification step"};let[E]=await this.db.insert(s).values(zr({instance_id:_.instance.id,requirement_id:$.id,verifier_id:o,signature_id:a||null,entity_name:r,entity_id:t,step_order:_.current_step,decision:c,reason:i||null,diff:e||null})).returning();if(await this.db.update(f).set({status:c}).where(on(this.getCol(f,"id"),$.id)),this.onNotificationTrigger&&_.instance){let R=`Step ${_.current_step}`,h=[],A=[];if(l){h=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id));let Q=h.find((B)=>B.nodeId===$.step_node_id);if(Q?.name)R=Q.name}if(b)A=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));let M=c==="approved"?"on_approved":"on_rejected",z={flow_name:_.flow?.name||"",step_name:R,step_order:_.current_step,total_steps:_.total_steps,decision:c},V=this.getConnectedNotificationNodeIds($.step_node_id,h,A);if(V.length>0)for(let Q of V)await this.onNotificationTrigger({trigger:M,flow_id:_.instance.flow_id,entity_name:r,entity_id:t,node_id:Q,verifier_id:o,decision:c,context:z});else await this.onNotificationTrigger({trigger:M,flow_id:_.instance.flow_id,entity_name:r,entity_id:t,verifier_id:o,decision:c,context:z})}if(c==="rejected"){await this.db.update(d).set(zr({status:"rejected",completed_at:new Date})).where(on(this.getCol(d,"id"),_.instance.id));let R;if(this.config.autoResetOnRejection){this.logger.info(`[Verification] Flow rejected for ${r}:${t}, auto-restarting from step 1`);let h=await this.startFlow({flow_id:_.instance.flow_id,entity_name:r,entity_id:t,started_by:_.instance.started_by});if(h.success)R=h.instance_id}return{success:!0,message:this.config.autoResetOnRejection?"Verification rejected \u2014 flow restarted from step 1":"Verification rejected",verification:E,flow_completed:!1,new_instance_id:R}}let W=$.id,Y=S.filter((R)=>R.id!==W);if(Y.length>0)return{success:!0,message:`Step ${_.current_step} partially approved, ${Y.length} verifier(s) remaining`,verification:E,flow_completed:!1};let H=_.current_step+1;if(H>_.total_steps){if(await this.db.update(d).set(zr({status:"completed",completed_at:new Date})).where(on(this.getCol(d,"id"),_.instance.id)),this.onNotificationTrigger){let R=[],h=[];if(l)R=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id));if(b)h=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));let A=$.step_node_id,M=this.getConnectedNotificationNodeIds(A,R,h),z={flow_name:_.flow?.name||"",step_order:_.current_step,total_steps:_.total_steps};if(M.length>0)for(let V of M)await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:_.instance.flow_id,entity_name:r,entity_id:t,node_id:V,context:z});else await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:_.instance.flow_id,entity_name:r,entity_id:t,context:z})}return{success:!0,message:"Verification flow completed",verification:E,flow_completed:!0}}if(await this.db.update(d).set(zr({current_step_order:H})).where(on(this.getCol(d,"id"),_.instance.id)),l&&b){let R=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id)),h=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));await this.materializeRequirementsForStep(_.instance.id,_.instance.flow_id,r,t,H,R,h,w,f,u)}return{success:!0,message:`Step ${_.current_step} approved, moving to step ${H}`,verification:E,flow_completed:!1,next_step:H}}async startFlowForEntity(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};let o=(await this.db.select().from(r).where(Xt(on(this.getCol(r,"entityName"),n.entity_name),on(this.getCol(r,"isDraft"),!1))).limit(1))[0];if(!o)return{success:!1,message:`No published flow found for entity '${n.entity_name}'`};return this.startFlow({flow_id:o.id,entity_name:n.entity_name,entity_id:n.entity_id,started_by:n.started_by})}async listEntityStatuses(n){let r=this.getTable("verificationInstances"),t=this.getTable("verificationFlows"),o=this.getTable("verificationSteps"),c={items:[],total:0,page:1,limit:20};if(!r||!t)return c;let i=n.page||1,a=n.limit||20,e=(i-1)*a,s=[on(this.getCol(r,"entityName"),n.entity_name)];if(n.status)s.push(on(this.getCol(r,"status"),n.status));let f=s.length===1?s[0]:Xt(...s),l=(await this.db.select().from(r).where(f).orderBy(nf(this.getCol(r,"createdAt")))).map((m)=>Sr(m)),b=l.length,w=l.slice(e,e+a),u=[];for(let m of w){let _=m.flow_id,S=await this.db.select().from(t).where(on(this.getCol(t,"id"),_)).limit(1),$=S[0]?Sr(S[0]):void 0,E=0;if(o)E=(await this.db.select().from(o).where(Xt(on(this.getCol(o,"flowId"),_),on(this.getCol(o,"nodeType"),"step")))).length;u.push({instance_id:m.id,entity_name:m.entity_name,entity_id:m.entity_id,flow_id:_,flow_name:$?.name||"Unknown",status:m.status,current_step_order:m.current_step_order,total_steps:E,started_by:m.started_by,started_at:m.started_at,completed_at:m.completed_at})}return{items:u,total:b,page:i,limit:a}}async getPending(n){let r=this.getTable("verificationRequirements"),t=this.getTable("verificationInstances"),o=this.getTable("verificationFlows"),c=this.getTable("verificationSteps"),i=this.getTable("user_roles"),a=this.getTable("roles");if(this.logger.info(`[Verification.getPending] userId=${n}, tables: req=${!!r} inst=${!!t} flow=${!!o} steps=${!!c} roles=${!!a} userRoles=${!!i}`),!r||!t||!o)return this.logger.warn("[Verification.getPending] Missing required tables, returning empty"),[];let e=i,s=a,d=(i&&a?await this.db.select({role_name:s.name}).from(i).innerJoin(a,on(e.roleId,s.id)).where(on(e.userId,n)):[]).map((u)=>u.role_name),b=(await this.db.select().from(r).where(on(this.getCol(r,"status"),"pending"))).map((u)=>Sr(u));this.logger.info(`[Verification.getPending] Found ${b.length} pending requirements, userRoles=${JSON.stringify(d)}`);for(let u of b)this.logger.info(`[Verification.getPending] Req: verifier_type=${u.verifier_type} verifier_user_id=${u.verifier_user_id} verifier_role=${u.verifier_role} step_order=${u.step_order} entity=${u.entity_name}/${u.entity_id}`);let w=[];for(let u of b){if(!(u.verifier_type==="user"&&u.verifier_user_id===n||u.verifier_type==="role"&&d.includes(u.verifier_role))){this.logger.info(`[Verification.getPending] Skipping req: canVerify=false (type=${u.verifier_type}, reqUserId=${u.verifier_user_id}, loggedInUserId=${n})`);continue}let _=await this.db.select().from(t).where(Xt(on(this.getCol(t,"id"),u.instance_id),on(this.getCol(t,"status"),"active"))).limit(1),S=_[0]?Sr(_[0]):void 0;if(!S)continue;if(S.current_step_order!==u.step_order)continue;let $=await this.db.select().from(o).where(on(this.getCol(o,"id"),S.flow_id)).limit(1),E=$[0]?Sr($[0]):void 0;if(!E)continue;let W;if(c&&u.step_node_id){let H=(await this.db.select().from(c).where(Xt(on(this.getCol(c,"flowId"),S.flow_id),on(this.getCol(c,"nodeId"),u.step_node_id))).limit(1))[0];if(H?.name)W=H.name}w.push({instance_id:S.id,entity_name:u.entity_name,entity_id:u.entity_id,flow_name:E.name,step_order:u.step_order,step_name:W,require_signature:u.require_signature,created_at:u.created_at})}return w}}var tf=g(()=>{rb()});var of=g(()=>{mu();x0();q0();Ju();Xu();xu();p0();y0();nb();tf()});import{access as $M,mkdir as a$}from"fs/promises";import{dirname as e$,resolve as cb}from"path";var Wi,ef,Vn=(n)=>{if(!n||typeof n!=="string")throw or("INVALID_PATH","Path must be a non-empty string",n,"resolvePath");return cb(n)},It=(n)=>{let r=Vn(n);return e$(r)},gt=async(n)=>{let r=cb(n);try{await a$(r,{recursive:!0})}catch(t){if(t.code!=="EEXIST")throw or("DIRECTORY_CREATE_FAILED",`Failed to create directory: ${r}`,r,"ensureDirectory")}},sf=(n)=>{let r=n,t=0;while(r>=1024&&t<ef.length-1)r/=1024,t++;return`${r.toFixed(2)} ${ef[t]}`},ib=(n,r)=>{return n.toLowerCase().endsWith(r.toLowerCase())},ff=(n,r)=>{let t=r.startsWith(".")?r:`.${r}`;if(ib(n,t))return n;return`${n}${t}`},or=(n,r,t,o)=>{return{code:n,message:r,path:t,operation:o||"unknown"}},ie=(n)=>{try{return JSON.stringify(n,null,2)}catch{return"{}"}},lf=async(n,r,t=Wi.maxConcurrency)=>{let o=[];for(let c=0;c<n.length;c+=t){let i=n.slice(c,c+t),a=[];for(let s of i)a.push(r(s));let e=await Promise.allSettled(a);o.push(...e)}return o},ae=(n,r={})=>{let t=[],o=[],c=r.strict??!0;if(n.defaultEncoding!==void 0){if(!["utf-8","utf8","ascii","base64","hex"].includes(n.defaultEncoding))t.push(`Invalid defaultEncoding: ${n.defaultEncoding}`)}if(n.maxConcurrency!==void 0){if(!Number.isInteger(n.maxConcurrency)||n.maxConcurrency<1)t.push("maxConcurrency must be a positive integer");if(n.maxConcurrency>50)o.push("maxConcurrency > 50 may cause performance issues")}if(n.defaultCreateDir!==void 0&&typeof n.defaultCreateDir!=="boolean")t.push("defaultCreateDir must be a boolean");if(n.defaultRecursive!==void 0&&typeof n.defaultRecursive!=="boolean")t.push("defaultRecursive must be a boolean");if(c&&!r.allowUnknownKeys){let i=["defaultEncoding","defaultCreateDir","defaultRecursive","maxConcurrency"],a=Object.keys(n);for(let e of a)if(!i.includes(e))t.push(`Unknown configuration key: ${e}`)}return{isValid:t.length===0,errors:t,warnings:o}},ab=(n,r=Wi)=>{let t=ae(n);if(!t.isValid)throw or("CONFIG_VALIDATION_FAILED",`Configuration validation failed: ${t.errors.join(", ")}`,void 0,"mergeConfig");return{...r,...n}},eb=(n)=>{let r=(i)=>({read:Boolean(i&4),write:Boolean(i&2),execute:Boolean(i&1)}),t=n>>6&7,o=n>>3&7,c=n&7;return{owner:r(t),group:r(o),others:r(c)}},sb=(n)=>{return Number.isInteger(n)&&n>=0&&n<=511};var zc=g(()=>{Wi={defaultEncoding:"utf-8",defaultCreateDir:!0,defaultRecursive:!0,maxConcurrency:5},ef=["B","KB","MB","GB","TB"]});import{copyFile as _f,rename as df,unlink as s$}from"fs/promises";import{basename as fb,dirname as lb,extname as f$,join as l$}from"path";var ee,_$=(n,r=".tmp")=>{let t=Vn(n),o=Date.now(),c=Math.random().toString(36).substring(2,8);return`${t}${r}.${o}.${c}`},_b=(n,r,t=!0)=>{let o=Vn(n),c=r?Vn(r):lb(o),i=fb(o),a=f$(i),e=fb(i,a),s=t?`.${new Date().toISOString().replace(/[:.]/g,"-")}`:"",f=`${e}.backup${s}${a}`;return l$(c,f)},Vi=async({path:n,data:r,tempSuffix:t=ee.tempSuffix,backup:o=ee.backup,sync:c=ee.sync})=>{let i=Vn(n),a=_$(i,t),e;try{if(await gt(It(i)),o){if(await Bun.file(i).exists())e=_b(i),await _f(i,e)}let s=await Bun.write(a,r);return await df(a,i),{success:!0,bytesWritten:s,tempPath:a,backupPath:e}}catch(s){try{await s$(a)}catch{}throw or("ATOMIC_WRITE_FAILED",`Atomic write failed: ${s}`,i,"atomicWrite")}},db=async(n,r,t={})=>{let o=JSON.stringify(r,null,2);return Vi({path:n,data:o,...t})},uf=async({sourcePath:n,backupDir:r,keepOriginal:t=!0,timestamp:o=ee.timestamp})=>{let c=Vn(n);if(!await Bun.file(c).exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,c,"createBackup");let a=_b(c,r,o);if(await gt(lb(a)),t)await _f(c,a);else await df(c,a);return a},bf=async(n,r,t=!1)=>{let o=Vn(n),c=Vn(r);if(!await Bun.file(o).exists())throw or("BACKUP_NOT_FOUND",`Backup file not found: ${n}`,o,"restoreFromBackup");try{if(await gt(It(c)),t)await df(o,c);else await _f(o,c);return!0}catch(a){return console.error(`Error restoring from backup ${n}:`,a),!1}},ub=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o),i;try{if(await c.exists())i=await uf({sourcePath:o,keepOriginal:!0,timestamp:!0});let a=await c.exists()?await c.text():"",e=await r(a),s=await Vi({path:o,data:e,backup:!1,...t});return{success:s.success,bytesWritten:s.bytesWritten,tempPath:s.tempPath,backupPath:i}}catch(a){if(i)try{await bf(i,o,!1)}catch(e){console.error("Rollback failed:",e)}throw a}},bb=async(n)=>{let r=[],t=[];for(let o of n)try{let c=await Vi(o);r.push(c)}catch(c){t.push({operation:o,error:c})}return{successful:r,failed:t}};var gb=g(()=>{zc();ee={tempSuffix:".tmp",backup:!1,sync:!0,timestamp:!0}});import{chmod as d$,stat as u$}from"fs/promises";var b$,So=async(n,r)=>{let t=Vn(n);if(!sb(r))throw or("INVALID_PERMISSION_MODE",`Invalid permission mode: ${r.toString(8)}`,t,"setFilePermissions");try{return await d$(t,r),!0}catch(o){return console.error(`Error setting permissions for ${n}:`,o),!1}},po=async(n)=>{let r=Vn(n);try{let o=(await u$(r)).mode&511,c=eb(o);return{path:r,mode:o,owner:c.owner,group:c.group,others:c.others}}catch(t){throw or("PERMISSION_READ_FAILED",`Failed to read permissions: ${t}`,r,"getFilePermissions")}},wb=async(n,r)=>{try{return((await po(n)).mode&r)===r}catch{return!1}},mb=async(n)=>{let t=(await po(n)).mode|256;return So(n,t)},$b=async(n)=>{let t=(await po(n)).mode|128;return So(n,t)},hb=async(n)=>{let t=(await po(n)).mode|64;return So(n,t)},Ab=async(n)=>{let t=(await po(n)).mode&-147;return So(n,t)},Eb=async(n,r)=>{let t=b$[r];return So(n,t)};var Sb=g(()=>{zc();b$={OWNER_READ_WRITE:384,OWNER_ALL:448,GROUP_READ:416,GROUP_READ_WRITE:432,ALL_READ:420,ALL_READ_WRITE:438,ALL_READ_EXECUTE:493,ALL_FULL:511,READ_ONLY:292,EXECUTABLE:493}});var g$,se=async(n,r={})=>{let t=Vn(n),o={...g$,...r};await gt(It(t));let i=Bun.file(t).writer({highWaterMark:o.highWaterMark}),a=!1;return{write:(s)=>{if(a)throw or("WRITER_CLOSED","Cannot write to closed writer",t,"streamWrite");try{let f=i.write(s);if(o.autoFlush)i.flush();return f}catch(f){throw or("WRITE_FAILED",`Failed to write chunk: ${f}`,t,"streamWrite")}},flush:()=>{if(a)return 0;try{return i.flush()}catch(s){throw or("FLUSH_FAILED",`Failed to flush writer: ${s}`,t,"streamFlush")}},end:async(s)=>{if(a)return 0;try{let f=await i.end(s);return a=!0,f}catch(f){throw a=!0,or("END_FAILED",`Failed to end writer: ${f}`,t,"streamEnd")}},ref:()=>{if(!a)i.ref()},unref:()=>{if(!a)i.unref()}}},gf=async(n,r,t={})=>{let o=await se(n,t),c=0;try{for(let i of r){let a=o.write(i);c+=a}return await o.flush(),await o.end(),c}catch(i){try{await o.end(i)}catch{}throw i}},Rb=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o),i=await c.exists()?await c.arrayBuffer():new ArrayBuffer(0),a=[];if(i.byteLength>0)a.push(i);return a.push(...r),gf(o,a,t)},Db=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o);if(!await c.exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,o,"copyFileStream");let i=c.stream(),a=await se(r,t),e=0;try{let s=i.getReader();while(!0){let{done:f,value:d}=await s.read();if(f)break;let l=a.write(d);e+=l}return await a.flush(),await a.end(),e}catch(s){try{await a.end(s)}catch{}throw s}},kb=async(n,r)=>{let t=Vn(n),o=Bun.file(t);if(!await o.exists())throw or("FILE_NOT_FOUND",`File not found: ${n}`,t,"readFileStream");let i=o.stream().getReader();try{while(!0){let{done:a,value:e}=await i.read();if(a)break;await r(e)}}finally{i.releaseLock()}};var Mb=g(()=>{zc();g$={highWaterMark:1048576,autoFlush:!0,closeOnEnd:!0}});import{readdir as w$,rm as m$,rmdir as $$,stat as h$}from"fs/promises";import{extname as A$,join as E$}from"path";class Ro{static instance;config;constructor(){this.config={...Wi}}static getInstance(){if(!Ro.instance)Ro.instance=new Ro;return Ro.instance}async createFile({dir:n,name:r,data:t,options:o={}}){let c=Vn(E$(n,r));if(o.createDir!==!1)await gt(It(c));let i=o.type?new Blob([t],{type:o.type}):t;return await Bun.write(c,i)}async createJsonFile(n,r,t){let o=ff(r,".json"),c=ie(t);return this.createFile({dir:n,name:o,data:c,options:{type:"application/json"}})}async createDirectory({path:n}){await gt(n)}async readFile({path:n,format:r="text"}){let t=Vn(n),o=Bun.file(t);if(!await o.exists())throw or("FILE_NOT_FOUND",`File not found: ${n}`,t,"readFile");switch(r){case"text":return await o.text();case"json":return await o.json();case"buffer":return await o.arrayBuffer();case"bytes":return await o.bytes();case"stream":return o.stream();default:return await o.text()}}async readJsonFile(n){return this.readFile({path:n,format:"json"})}async getFileInfo(n){let r=Vn(n),t=Bun.file(r),o=n.split("/").pop()||n,c=null;try{c=await h$(r)}catch{}return{name:o,path:r,size:t.size,type:t.type,exists:await t.exists(),extension:A$(o),createdAt:c?.birthtime,modifiedAt:c?.mtime}}async readDirectory({path:n,recursive:r=!1}){let t=Vn(n);return await w$(t,{recursive:r,encoding:"utf8"})}async getFilesByExtension(n,r){let t=await this.readDirectory({path:n}),o=r.startsWith(".")?r:`.${r}`;return t.filter((c)=>c.endsWith(o))}async updateFile({path:n,data:r,mode:t="overwrite"}){let o=Vn(n);if(t==="append"){let i=await this.readFile({path:n,format:"text"})+r;return await Bun.write(o,i)}return await Bun.write(o,r)}async updateJsonFile(n,r,t=!1){let o=r;if(t)try{let c=await this.readJsonFile(n);if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof r==="object"&&r!==null&&!Array.isArray(r))o={...c,...r}}catch{}return this.updateFile({path:n,data:ie(o),mode:"overwrite"})}async appendToFile(n,r){return this.updateFile({path:n,data:r,mode:"append"})}async deleteFile(n){try{let r=Vn(n);return await Bun.file(r).delete(),!0}catch(r){return console.error(`Error deleting file ${n}:`,r),!1}}async deleteDirectory({path:n,recursive:r=!1}){try{let t=Vn(n);if(r)await m$(t,{recursive:!0,force:!0});else await $$(t);return!0}catch(t){return console.error(`Error deleting directory ${n}:`,t),!1}}async deleteFiles(n){let r=await lf(n,async(c)=>{if(!await this.deleteFile(c))throw Error(`Failed to delete: ${c}`);return c}),t=[],o=[];for(let c=0;c<r.length;c++){let i=r[c],a=n[c];if(i?.status==="fulfilled")t.push(a||"");else o.push(a||"")}return{success:t,failed:o}}async exists(n){let r=Vn(n);return await Bun.file(r).exists()}async copyFile(n,r){let t=Vn(n),o=Vn(r),c=Bun.file(t);if(!await c.exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,t,"copyFile");return await gt(It(o)),await Bun.write(o,c)}async moveFile(n,r){try{return await this.copyFile(n,r),await this.deleteFile(n),!0}catch(t){return console.error(`Error moving file from ${n} to ${r}:`,t),!1}}getFormattedFileSize(n){return sf(n)}getConfig(){return{...this.config}}updateConfig(n){let r=ae(n);if(r.isValid){let t=ab(n,this.config);Object.assign(this.config,t)}return r}validateConfiguration(n){return ae(n)}async createStreamWriter(n,r={}){return se(n,r)}async writeStream(n,r,t={}){return gf(n,r,t)}async appendStream(n,r,t={}){return Rb(n,r,t)}async copyFileStream(n,r,t={}){return Db(n,r,t)}async readFileStream(n,r){return kb(n,r)}async setPermissions(n,r){return So(n,r)}async setPermissionsAdvanced(n){return So(n.path,n.mode)}async getPermissions(n){return po(n)}async checkPermissions(n,r){return wb(n,r)}async makeFileReadable(n){return mb(n)}async makeFileWritable(n){return $b(n)}async makeFileExecutable(n){return hb(n)}async makeFileReadOnly(n){return Ab(n)}async setCommonPermission(n,r){return Eb(n,r)}async atomicWrite(n){return Vi(n)}async atomicJsonWrite(n,r,t={}){return db(n,r,t)}async createFileBackup(n){return uf(n)}async restoreFileFromBackup(n,r,t=!1){return bf(n,r,t)}async safeFileUpdate(n,r,t={}){return ub(n,r,t)}async batchAtomicOperations(n){return bb(n)}}var wf=g(()=>{gb();Sb();Mb();zc()});var Lt;var fe=g(()=>{wf();zc();wf();Lt=Ro.getInstance()});import{Pool as KM}from"pg";var Hb=()=>{};var zb=g(()=>{z0();fe();Hb();Zt()});function $f(n,r){let t=(n.get("cookie")?.split(";")||[]).reduce((o,c)=>{let[i,a]=c.trim().split("=");if(i&&a)o[i]=a;return o},{});return{access_token:t[r.access_token]||n.get("authorization")?.split(" ")[1],refresh_token:t[r.refresh_token],session_token:t[r.session_token]}}function hf(n){if(!n.redis){console.log("Redis not configured, skipping");return}if(n.redis.withDapr){mf=new tr({withDapr:!0,stateStoreName:n.redis.stateStoreName});return}let r=n.redis.url?process.env[n.redis.url]:void 0,t=n.redis.host?process.env[n.redis.host]:void 0,o=n.redis.port?parseInt(process.env[n.redis.port]||"",10):void 0;mf=new tr({url:r,host:t,port:Number.isNaN(o)?void 0:o})}function le(){return mf}function wt(n){if(typeof n==="number")return n;if(!n||n.trim()==="")throw Error("Time string cannot be empty");let r=n.trim().match(/^(\d+(?:\.\d+)?)\s*([smhdwMy])$/);if(!r||!r[1]||!r[2])throw Error(`Invalid time format: "${n}". Expected format: "75s", "10m", "2h", "1d", "1w", "2M", "1y"`);let t=parseFloat(r[1]),o=r[2],i={s:1,m:60,h:3600,d:86400,w:604800,M:2592000,y:31536000}[o];if(i===void 0)throw Error(`Unknown time unit: "${o}"`);let a=Math.floor(t*i);if(a<=0)throw Error(`Time value must be positive: "${n}"`);return a}function Ub({sessionData:n,options:r,refreshTokenId:t,roles:o,claims:c}){let i=r.authentication?.accessToken?.secret;if(!i)throw Error("Access token secret env name is not configured");let a=process.env[i];if(!a)throw Error(`Access token secret env "${i}" is not set`);return Di({subject:n.userId,issuer:r.authentication?.accessToken?.issuer,audience:r.authentication?.accessToken?.audience,algorithm:r.authentication?.accessToken?.algorithm,expiresInSeconds:wt(r.authentication?.accessToken?.expiresIn??"15m"),sessionId:n.id,customClaims:{refreshTokenId:t,...o&&o.length>0?{roles:o}:{},...c&&c.length>0?{claims:c}:{}}},a)}function pt(n,r){return n?{entityName:n.entity_name,entityId:n.entity_id===" - "?null:n.entity_id,operation:n.operation_type,userId:n.user_id==="unknown"?null:n.user_id,summary:r,ipAddress:n.ip_address,userAgent:n.user_agent,path:n.path,query:n.query}:void 0}function S$(n){let r={},t={};for(let[o,c]of Object.entries(n)){let i=o.match(/^(\w+)\[\d*\]\[(\w+)\]$/),a=i?.[1],e=i?.[2];if(a&&e){if(!t[a])t[a]={};let s=t[a];if(!s[e])s[e]=[];let f=s[e];if(Array.isArray(c))for(let d of c)f.push(d);else f.push(c)}else r[o]=c}for(let[o,c]of Object.entries(t)){let i=Object.keys(c);if(i.length===0)continue;let a=Math.max(...i.map((s)=>(c[s]||[]).length)),e=[];for(let s=0;s<a;s++){let f={};for(let d of i)f[d]=(c[d]||[])[s];e.push(f)}r[o]=e}return r}function Af(n){let r=S$(n),t=(a)=>{if(a===void 0||a===null)return;if(typeof a==="object")return a;if(typeof a==="string")try{return JSON.parse(a)}catch{return}return},o=r.page?parseInt(r.page,10):1,c=r.limit?parseInt(r.limit,10):20,i=r.offset?parseInt(r.offset,10):(o-1)*c;return{page:o,limit:c,offset:i,search:r.search,searchFields:r.searchFields?r.searchFields.split(","):void 0,filters:t(r.filters),sort:t(r.sort),select:r.select?r.select.split(","):void 0,with:t(r.with),distinct:r.distinct==="true",distinctOn:r.distinctOn?r.distinctOn.split(","):void 0}}function Wb(n,r,t,o){let c=Math.ceil(o/r),i=n<c,a=n>1;return{page:n,limit:r,offset:t,totalItems:o,totalPages:c,hasNextPage:i,hasPrevPage:a,nextPage:i?n+1:null,prevPage:a?n-1:null}}function D$(n){let r=["varchar","char","text","uuid","citext","bit","varbit"],t=["integer","smallint","bigint","serial","smallserial","bigserial","real","doublePrecision","numeric","decimal"],o=["boolean"];if(r.includes(n))return(c)=>({valid:typeof c==="string",expectedType:"string"});if(t.includes(n))return(c)=>({valid:typeof c==="number",expectedType:"number"});if(o.includes(n))return(c)=>({valid:typeof c==="boolean",expectedType:"boolean"});if(n==="json"||n==="jsonb")return(c)=>({valid:typeof c==="object",expectedType:"object"});return()=>({valid:!0,expectedType:"any"})}function Do(n,r,t=!1){let o=[];for(let c of r){let i=n[c.name]??n[c.name.replace(/_([a-z])/g,(s,f)=>f.toUpperCase())],a=c.notNull&&!c.nullable&&c.default===void 0&&!c.defaultRaw;if(i===void 0||i===null){if(a&&!t)o.push({field:c.name,message:c.validation?.customMessage||`${c.name} is required`});continue}let e=D$(c.type)(i);if(!e.valid){o.push({field:c.name,message:c.validation?.customMessage||`${c.name} must be of type ${e.expectedType}`});continue}if(typeof i==="string"){let s=i.length;if(c.length&&s>c.length)o.push({field:c.name,message:c.validation?.customMessage||`${c.name} exceeds max length of ${c.length}`});if(c.validation?.minLength&&s<c.validation.minLength)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at least ${c.validation.minLength} characters`});if(c.validation?.maxLength&&s>c.validation.maxLength)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at most ${c.validation.maxLength} characters`});if(c.validation?.pattern){if(!new RegExp(c.validation.pattern).test(i))o.push({field:c.name,message:c.validation.customMessage||`${c.name} does not match required pattern`})}if(c.validation?.format){let f=R$[c.validation.format];if(f&&!f.test(i))o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be a valid ${c.validation.format}`})}}if(typeof i==="number"){if(c.validation?.min!==void 0&&i<c.validation.min)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at least ${c.validation.min}`});if(c.validation?.max!==void 0&&i>c.validation.max)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at most ${c.validation.max}`})}if(c.enumValues&&c.enumValues.length>0){if(!c.enumValues.includes(i))o.push({field:c.name,message:c.validation?.customMessage||`${c.name} must be one of: ${c.enumValues.join(", ")}`})}}return{valid:o.length===0,errors:o}}function M$(n){return n.replace(/[&<>"'`=/]/g,(r)=>k$[r]||r)}function H$(n){return n.replace(/<[^>]*>/g,"")}function z$(n){let r=n.split("@"),t=r[0],o=r[1];if(!t||!o)return n;let c=t.split("+")[0];if(!c)return n;return`${c.replace(/\./g,"")}@${o.toLowerCase()}`}function B$(n){return n.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}function U$(n,r){if(n===null||n===void 0)return n;switch(r){case"trim":return typeof n==="string"?n.trim():n;case"lowercase":return typeof n==="string"?n.toLowerCase():n;case"uppercase":return typeof n==="string"?n.toUpperCase():n;case"escapeHtml":return typeof n==="string"?M$(n):n;case"stripTags":return typeof n==="string"?H$(n):n;case"normalizeEmail":return typeof n==="string"?z$(n):n;case"toNumber":if(typeof n==="number")return n;if(typeof n==="string"){let t=Number(n);return Number.isNaN(t)?n:t}return n;case"toBoolean":if(typeof n==="boolean")return n;if(typeof n==="string"){let t=n.toLowerCase();if(t==="true"||t==="1"||t==="yes")return!0;if(t==="false"||t==="0"||t==="no")return!1}if(typeof n==="number")return n!==0;return n;case"slugify":return typeof n==="string"?B$(n):n;default:return n}}function ko(n,r){let t={},o=(c)=>c.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());for(let c of Object.keys(n)){let i=n[c],a=c.replace(/[A-Z]/g,(f)=>`_${f.toLowerCase()}`),e=r.find((f)=>f.name===c||f.name===a);if(e?.sanitize&&e.sanitize.length>0)for(let f of e.sanitize)i=U$(i,f);let s=c.includes("_")?o(c):c;t[s]=i}return t}async function Vb(n,r,t){let o=new tr,c=`${V$}${n}`,i=`${W$}${n}:${r}`,a=await o.read(i);if(a.success&&a.data)return{success:!0,accessToken:a.data,fromCache:!0};let e=await o.acquireLock(c,Y$);if(!e.success)return{success:!1,error:e.error};if(e.data)try{let l=t();return await o.create(i,l,Bb),{success:!0,accessToken:l,fromCache:!1}}finally{await o.releaseLock(c)}let s=await o.waitForLock(c,J$,50);if(!s.success)return{success:!1,error:s.error};if(!s.data)return{success:!1,error:"Lock wait timeout"};let f=await o.read(i);if(f.success&&f.data)return{success:!0,accessToken:f.data,fromCache:!0};let d=t();return await o.create(i,d,Bb),{success:!0,accessToken:d,fromCache:!1}}function Yb(n){let r=[],t={};if(n.database?.url){let o=process.env[n.database.url];if(!o)r.push({field:"database.url",envName:n.database.url,message:`Environment variable "${n.database.url}" is not set. Please set it in your .env file.`});else t.databaseUrl=o}if(n.redis&&!n.redis.withDapr)if(n.redis.url){let o=process.env[n.redis.url];if(!o)r.push({field:"redis.url",envName:n.redis.url,message:`Environment variable "${n.redis.url}" is not set. Please set it in your .env file.`});else t.redisUrl=o}else{if(n.redis.host){if(!process.env[n.redis.host])r.push({field:"redis.host",envName:n.redis.host,message:`Environment variable "${n.redis.host}" is not set. Please set it in your .env file.`})}if(n.redis.port){if(!process.env[n.redis.port])r.push({field:"redis.port",envName:n.redis.port,message:`Environment variable "${n.redis.port}" is not set. Please set it in your .env file.`})}}if(n.authentication?.enabled){if(!n.authentication.mode)r.push({field:"authentication.mode",envName:"",message:'authentication.mode is required when authentication is enabled. Use "full" for IDP/standalone services, "consumer" for resource servers.'});if(n.authentication.accessToken?.secret){let c=process.env[n.authentication.accessToken.secret];if(!c)r.push({field:"authentication.accessToken.secret",envName:n.authentication.accessToken.secret,message:`Environment variable "${n.authentication.accessToken.secret}" is not set. Please set it in your .env file.`});else t.accessTokenSecret=c}else r.push({field:"authentication.accessToken.secret",envName:"",message:"authentication.accessToken.secret is required when authentication is enabled."});let o=n.authentication.mode==="consumer";if(n.authentication.refreshToken?.secret){let c=process.env[n.authentication.refreshToken.secret];if(!c)r.push({field:"authentication.refreshToken.secret",envName:n.authentication.refreshToken.secret,message:`Environment variable "${n.authentication.refreshToken.secret}" is not set. Please set it in your .env file.`});else t.refreshTokenSecret=c}else if(!o)r.push({field:"authentication.refreshToken.secret",envName:"",message:"authentication.refreshToken.secret is required when authentication is enabled."});if(n.authentication.sessionToken?.secret){let c=process.env[n.authentication.sessionToken.secret];if(!c)r.push({field:"authentication.sessionToken.secret",envName:n.authentication.sessionToken.secret,message:`Environment variable "${n.authentication.sessionToken.secret}" is not set. Please set it in your .env file.`});else t.sessionTokenSecret=c}else if(!o)r.push({field:"authentication.sessionToken.secret",envName:"",message:"authentication.sessionToken.secret is required when authentication is enabled."})}if(n.authentication?.oauth?.enabled&&n.authentication.oauth.providers){let o={};for(let[c,i]of Object.entries(n.authentication.oauth.providers)){if(!i)continue;let{clientId:a,clientSecret:e,redirectUri:s}=i,f=process.env[a],d=process.env[e],l=process.env[s]??s;if(!f)r.push({field:`authentication.oauth.providers.${c}.clientId`,envName:a,message:`Environment variable "${a}" is not set (OAuth ${c} clientId).`});if(!d)r.push({field:`authentication.oauth.providers.${c}.clientSecret`,envName:e,message:`Environment variable "${e}" is not set (OAuth ${c} clientSecret).`});if(f&&d)o[c]={clientId:f,clientSecret:d,redirectUri:l,scopes:i.scopes,authorizationUrl:i.authorizationUrl,tokenUrl:i.tokenUrl,userInfoUrl:i.userInfoUrl,extraAuthParams:i.extraAuthParams}}if(Object.keys(o).length>0)t.oauthProviders=o}return{valid:r.length===0,errors:r,resolved:t}}async function Jb(n,r){let{Pool:t}=await import("pg"),c=new URL(n).pathname.replace("/","");if(!c)return;let i=new URL(n);i.pathname="/postgres";let a=new t({connectionString:i.toString()});try{if((await a.query("SELECT 1 FROM pg_database WHERE datname = $1",[c])).rowCount===0)r.info(`[Database] Creating database "${c}"...`),await a.query(`CREATE DATABASE "${c}" TEMPLATE template0`),r.info(`[Database] Database "${c}" created successfully`);else r.info(`[Database] Database "${c}" exists`)}catch(e){let s=e instanceof Error?e.message:String(e);r.warn(`[Database] Could not auto-create database: ${s}`)}finally{await a.end()}}var mf=null,R$,k$,W$="access_token:",V$="refresh_lock:",Y$=5,J$=3000,Bb=60;var _e=g(()=>{zb();of();R$={email:/^[^\s@]+@[^\s@]+\.[^\s@]+$/,url:/^https?:\/\/.+/,uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^\d{4}-\d{2}-\d{2}$/,datetime:/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,time:/^\d{2}:\d{2}:\d{2}$/,uri:/^[a-z][a-z0-9+.-]*:/i,ipv4:/^(\d{1,3}\.){3}\d{1,3}$/,ipv6:/^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i};k$={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}});import de from"path";import X$,{t as ue}from"elysia";function Ef(n){if(!n)return yo;return{enabled:n.enabled??yo.enabled,basePath:n.basePath??yo.basePath,cacheMaxAge:n.cacheMaxAge??yo.cacheMaxAge,enableRangeRequests:n.enableRangeRequests??yo.enableRangeRequests,enableEtag:n.enableEtag??yo.enableEtag,corsOrigins:n.corsOrigins??yo.corsOrigins}}function L$(n){let r=["image/","video/","audio/","text/","application/pdf"];for(let t of r)if(n.startsWith(t)||n===t)return"inline";return"attachment"}function Q$(n){return n.replace(/[^A-Za-z0-9._-]+/g,"_").replace(/_{2,}/g,"_").slice(0,200)}function Sf(n){let{cdn:r,storagePath:t,logger:o,getFileRecord:c}=n,i=new X$({prefix:r.basePath});if(!r.enabled)return i;return i.get("/:id",async({params:a,request:e,set:s})=>{let{id:f}=a,d=e.headers.get("x-schema-name")||void 0,l,b,w;if(c){let A=await c(f,d);if(!A)return s.status=404,{success:!1,message:"File not found"};l=de.join(A.path,A.name),b=A.name,w=A.mimeType||A.mime_type||"application/octet-stream"}else l=de.join(t,f),b=f,w="application/octet-stream";if(!await Lt.exists(l))return s.status=404,{success:!1,message:"Physical file not found"};let m=await Lt.getFileInfo(l),_=new Date(m.modifiedAt||Date.now()).toUTCString(),S=r.enableEtag?`"${m.size}-${m.modifiedAt?.getTime()||Date.now()}"`:void 0,$={"Cache-Control":`public, max-age=${r.cacheMaxAge}`,"Last-Modified":_};if(S)$.ETag=S;if(r.corsOrigins.length>0)$["Access-Control-Allow-Origin"]=r.corsOrigins[0]==="*"?"*":r.corsOrigins.join(", "),$["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";let E=e.headers.get("if-none-match");if(S&&E===S)return new Response(null,{status:304,headers:$});let W=Bun.file(l),Y=e.headers.get("range");if(r.enableRangeRequests&&Y){let A=Y.match(/bytes=(\d*)-(\d*)/);if(!A)return s.status=416,new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${m.size}`,"Content-Type":w,...$}});let M=A[1]||"0",z=A[2]||"",V=parseInt(M,10),Q=z?parseInt(z,10):m.size-1;if(V>=m.size||Q>=m.size||V>Q)return new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${m.size}`,"Content-Type":w,...$}});let B=Q-V+1,J=W.slice(V,Q+1);return new Response(J,{status:206,headers:{"Content-Range":`bytes ${V}-${Q}/${m.size}`,"Accept-Ranges":"bytes","Content-Length":B.toString(),"Content-Type":w,...$}})}let H=L$(w),D=Q$(b),R=encodeURIComponent(b),h=`${H}; filename="${D}"; filename*=UTF-8''${R}`;return new Response(W,{status:200,headers:{"Content-Length":m.size.toString(),"Content-Type":w,"Accept-Ranges":r.enableRangeRequests?"bytes":"none","Content-Disposition":h,...$}})},{params:ue.Object({id:ue.String()}),detail:{tags:["CDN"],summary:"Get file by ID",description:"Serve file with streaming, range requests, and caching support"}}),i.head("/:id",async({params:a,request:e,set:s})=>{let{id:f}=a,d=e.headers.get("x-schema-name")||void 0,l,b;if(c){let $=await c(f,d);if(!$)return s.status=404,new Response(null,{status:404});l=de.join($.path,$.name),b=$.mime_type||"application/octet-stream"}else l=de.join(t,f),b="application/octet-stream";if(!await Lt.exists(l))return s.status=404,new Response(null,{status:404});let u=await Lt.getFileInfo(l),m=new Date(u.modifiedAt||Date.now()).toUTCString(),_=r.enableEtag?`"${u.size}-${u.modifiedAt?.getTime()||Date.now()}"`:void 0,S={"Content-Length":u.size.toString(),"Content-Type":b,"Accept-Ranges":r.enableRangeRequests?"bytes":"none","Cache-Control":`public, max-age=${r.cacheMaxAge}`,"Last-Modified":m};if(_)S.ETag=_;if(r.corsOrigins.length>0)S["Access-Control-Allow-Origin"]=r.corsOrigins[0]==="*"?"*":r.corsOrigins.join(", "),S["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";return new Response(null,{status:200,headers:S})},{params:ue.Object({id:ue.String()}),detail:{tags:["CDN"],summary:"Get file metadata",description:"Get file headers without body for preflight checks"}}),o.info(`[CDN] Routes enabled at ${r.basePath}`),i}var yo;var Xb=g(()=>{fe();yo={enabled:!0,basePath:"/cdn",cacheMaxAge:86400,enableRangeRequests:!0,enableEtag:!0,corsOrigins:["*"]}});import{randomUUID as G$}from"crypto";import Rf from"path";function Yi(n){if(!n)return yt;return{enabled:n.enabled??yt.enabled,basePath:n.basePath??yt.basePath,maxFileSizeBytes:n.maxFileSizeBytes??yt.maxFileSizeBytes,allowedMimeTypes:n.allowedMimeTypes??yt.allowedMimeTypes,blockedMimeTypes:n.blockedMimeTypes??yt.blockedMimeTypes,formData:{filesField:n.formData?.filesField??yt.formData.filesField,dataField:n.formData?.dataField??yt.formData.dataField,maxFiles:n.formData?.maxFiles??yt.formData.maxFiles}}}function Ji(n,r){let t={data:{},files:[]};if(!n||typeof n!=="object")return t;let o=n,c=o[r.formData.dataField];if(c){if(typeof c==="string")try{t.data=JSON.parse(c)}catch{t.data={}}else if(typeof c==="object")t.data=c}let i=o[r.formData.filesField];if(i){if(i instanceof File)t.files=[i];else if(Array.isArray(i))t.files=i.filter((a)=>a instanceof File)}return t}function Df(n,r){if(n.size>r.maxFileSizeBytes)return{valid:!1,error:`File ${n.name} exceeds maximum size of ${r.maxFileSizeBytes} bytes`};if(r.blockedMimeTypes.length>0&&r.blockedMimeTypes.includes(n.type))return{valid:!1,error:`File type ${n.type} is not allowed`};if(r.allowedMimeTypes.length>0&&!r.allowedMimeTypes.includes(n.type))return{valid:!1,error:`File type ${n.type} is not in allowed list`};return{valid:!0}}async function kf(n,r,t){let o=G$(),c=Rf.extname(n.name),i=`${o}${c}`,a=t?Rf.join(r.basePath,t):r.basePath,e=await n.arrayBuffer(),s=new Uint8Array(e);return await Lt.createFile({dir:a,name:i,data:s,options:{type:n.type,createDir:!0}}),{id:o,name:i,originalName:n.name,path:a,mimeType:n.type,size:n.size,createdAt:new Date}}async function Xi(n,r,t){let o=[],c=[];for(let i of n.slice(0,r.formData.maxFiles)){let a=Df(i,r);if(!a.valid){c.push({file:i.name,error:a.error||"Unknown error"});continue}try{let e=await kf(i,r,t);o.push(e)}catch(e){c.push({file:i.name,error:e instanceof Error?e.message:"Upload failed"})}}return{success:o,failed:c}}async function Lb(n,r){try{let t=Rf.join(n,r);return await Lt.deleteFile(t)}catch{return!1}}var yt;var Qb=g(()=>{fe();yt={enabled:!1,basePath:"./uploads",maxFileSizeBytes:104857600,allowedMimeTypes:[],blockedMimeTypes:["application/x-executable","application/x-msdos-program"],formData:{filesField:"files",dataField:"data",maxFiles:10}}});var Gb={};go(Gb,{validateFile:()=>Df,uploadFiles:()=>Xi,uploadFile:()=>kf,parseFormDataBody:()=>Ji,mergeStorageConfig:()=>Yi,mergeCdnConfig:()=>Ef,deleteFile:()=>Lb,createCdnRoutes:()=>Sf});var be=g(()=>{Xb();Qb()});import{eq as Pf,sql as to}from"drizzle-orm";import{Elysia as V3,t as Cf}from"elysia";function Se(n,r="public"){let{db:t,logger:o,usersTable:c}=n,i=new V3;return i.post("/auth/admin/change-user-id",async(a)=>{if(!t||!c)return{success:!1,message:"Database not configured"};let e=a.request.headers.get("x-user-id");if(!e)return a.set.status=401,{success:!1,message:"Unauthorized"};let f=(await t.select().from(c).where(Pf(c.id,e)).limit(1))[0];if(!f||!f.isGod)return a.set.status=403,{success:!1,message:"Forbidden: godmin privileges required"};let{currentId:d,newId:l}=a.body;if(!d||!l)return a.set.status=400,{success:!1,message:"currentId and newId are required"};if(d===l)return a.set.status=400,{success:!1,message:"New ID must be different from current ID"};if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(l))return a.set.status=400,{success:!1,message:"newId must be a valid UUID"};let u=(await t.select().from(c).where(Pf(c.id,d)).limit(1))[0];if(!u)return a.set.status=404,{success:!1,message:"User not found"};if((await t.select().from(c).where(Pf(c.id,l)).limit(1)).length>0)return a.set.status=409,{success:!1,message:"A user with this ID already exists"};try{let _=await t.execute(to`
|
|
60
|
+
`}getActiveAlerts(){return Array.from(this.state.activeAlerts.values())}acknowledgeAlert(n){for(let[r,t]of this.state.activeAlerts)if(t.id===n)return t.acknowledged=!0,!0;return!1}clearAlert(n){this.state.activeAlerts.delete(n)}}class j0{config;requestCount=0;responseTimes=[];errorCount=0;rateLimitBlocks=0;byEndpoint={};byMethod={};byStatus={};byErrorType={};lastCollectTime=Date.now();constructor(n){this.config=n}recordRequest(n){if(!this.config?.enabled)return;if(this.requestCount++,this.config.metrics?.responseTime!==!1){if(this.responseTimes.push(n.responseTimeMs),this.responseTimes.length>1e4)this.responseTimes=this.responseTimes.slice(-5000)}if(this.config.metrics?.requests!==!1)this.byEndpoint[n.endpoint]=(this.byEndpoint[n.endpoint]||0)+1,this.byMethod[n.method]=(this.byMethod[n.method]||0)+1,this.byStatus[String(n.status)]=(this.byStatus[String(n.status)]||0)+1;if(this.config.metrics?.errors!==!1&&n.isError){if(this.errorCount++,n.errorType)this.byErrorType[n.errorType]=(this.byErrorType[n.errorType]||0)+1}}recordRateLimitBlock(){if(!this.config?.enabled||this.config.metrics?.rateLimits===!1)return;this.rateLimitBlocks++}collect(){if(!this.config?.enabled)return null;let r=(Date.now()-this.lastCollectTime)/1000/60,t=r>0?Math.round(this.requestCount/r):0,o=r>0?Math.round(this.rateLimitBlocks/r):0,c=[...this.responseTimes].sort((e,s)=>e-s),i=c.length;return{requests:{total:this.requestCount,perMinute:t,byEndpoint:{...this.byEndpoint},byMethod:{...this.byMethod},byStatus:{...this.byStatus}},responseTime:{avg:i>0?Math.round(c.reduce((e,s)=>e+s,0)/i*100)/100:0,min:i>0?c[0]??0:0,max:i>0?c[i-1]??0:0,p50:i>0?c[Math.floor(i*0.5)]??0:0,p95:i>0?c[Math.floor(i*0.95)]??0:0,p99:i>0?c[Math.floor(i*0.99)]??0:0},errors:{total:this.errorCount,rate:this.requestCount>0?Math.round(this.errorCount/this.requestCount*100*100)/100:0,byType:{...this.byErrorType}},rateLimits:{blocked:this.rateLimitBlocks,blockedPerMinute:o}}}reset(){this.requestCount=0,this.responseTimes=[],this.errorCount=0,this.rateLimitBlocks=0,this.byEndpoint={},this.byMethod={},this.byStatus={},this.byErrorType={},this.lastCollectTime=Date.now()}getRequestsPerMinute(){let n=(Date.now()-this.lastCollectTime)/1000/60;return n>0?Math.round(this.requestCount/n):0}getErrorRate(){return this.requestCount>0?this.errorCount/this.requestCount*100:0}getRateLimitBlocksPerMinute(){let n=(Date.now()-this.lastCollectTime)/1000/60;return n>0?Math.round(this.rateLimitBlocks/n):0}getAvgResponseTime(){if(this.responseTimes.length===0)return 0;return this.responseTimes.reduce((n,r)=>n+r,0)/this.responseTimes.length}}import*as Lu from"fs";import*as Eo from"os";class K0{config;lastCpuInfo=null;constructor(n){this.config=n}async collect(){if(!this.config?.enabled)return null;let n={cpu:{usage:0,cores:0},memory:{total:0,used:0,free:0,usagePercent:0,heapUsed:0,heapTotal:0},disk:{total:0,used:0,free:0,usagePercent:0},network:{bytesIn:0,bytesOut:0},process:{uptime:0,pid:0,eventLoopLag:0}};if(this.config.metrics?.cpu!==!1)n.cpu=this.collectCpu();if(this.config.metrics?.memory!==!1)n.memory=this.collectMemory();if(this.config.metrics?.disk!==!1)n.disk=await this.collectDisk();if(this.config.metrics?.network)n.network=this.collectNetwork();if(this.config.metrics?.process!==!1)n.process=await this.collectProcess();return n}collectCpu(){let n=Eo.cpus(),r=n.length,t=0,o=0;for(let i of n)t+=i.times.idle,o+=i.times.user+i.times.nice+i.times.sys+i.times.idle+i.times.irq;let c=0;if(this.lastCpuInfo){let i=t-this.lastCpuInfo.idle,a=o-this.lastCpuInfo.total;c=a>0?Math.round((1-i/a)*100*100)/100:0}return this.lastCpuInfo={idle:t,total:o},{usage:c,cores:r}}collectMemory(){let n=Eo.totalmem(),r=Eo.freemem(),t=n-r,o=Math.round(t/n*100*100)/100,c=process.memoryUsage();return{total:n,used:t,free:r,usagePercent:o,heapUsed:c.heapUsed,heapTotal:c.heapTotal}}async collectDisk(){try{let n=Lu.statfsSync("/"),r=n.blocks*n.bsize,t=n.bfree*n.bsize,o=r-t,c=Math.round(o/r*100*100)/100;return{total:r,used:o,free:t,usagePercent:c}}catch{return{total:0,used:0,free:0,usagePercent:0}}}collectNetwork(){let n=Eo.networkInterfaces(),r=0,t=0;for(let o in n){let c=n[o];if(c){for(let i of c)if(!i.internal)r+=0,t+=0}}return{bytesIn:r,bytesOut:t}}async collectProcess(){let n=process.uptime(),r=process.pid,t=Date.now(),o=await new Promise((c)=>{setImmediate(()=>{c(Date.now()-t)})});return{uptime:n,pid:r,eventLoopLag:o}}}var Qu=()=>{};import{randomUUID as Gu}from"crypto";import*as Ou from"os";class Ta{store;memoryInterval=null;cpuInterval=null;lastCpuInfo=null;isRunning=!1;constructor(n){let r={...T5,...n};this.store={requests:[],configs:{logMemory:r.logMemory,logCpu:r.logCpu,logDapr:r.logDapr,logWebSocket:r.logWebSocket,cpuLogInterval:r.cpuLogInterval,memoryLogInterval:r.memoryLogInterval},logs:{memory:[],cpu:[],dapr:[],ws:[]},logLimits:{memory:r.memoryLogLimit,cpu:r.cpuLogLimit,dapr:r.daprLogLimit,ws:r.wsLogLimit,request:r.requestLogLimit},worker:{pid:process.pid,workerId:null,memory:null,cpu:null,updatedAt:Date.now()},allWorkers:[],daprEvents:[],wsEvents:[]}}start(){if(this.isRunning)return;if(this.isRunning=!0,this.store.configs.logMemory)this.startMemoryCollector();if(this.store.configs.logCpu)this.startCpuCollector()}stop(){if(!this.isRunning)return;if(this.isRunning=!1,this.memoryInterval)clearInterval(this.memoryInterval),this.memoryInterval=null;if(this.cpuInterval)clearInterval(this.cpuInterval),this.cpuInterval=null}startMemoryCollector(){if(this.memoryInterval)clearInterval(this.memoryInterval);let n=()=>{if(!this.store.configs.logMemory)return;let r=process.memoryUsage(),t={timestamp:Date.now(),rss:r.rss,heapUsed:r.heapUsed,heapTotal:r.heapTotal};if(this.store.logs.memory.push(t),this.store.logs.memory.length>this.store.logLimits.memory*2)this.store.logs.memory=this.store.logs.memory.slice(-this.store.logLimits.memory);this.store.worker.memory=t,this.store.worker.updatedAt=Date.now()};n(),this.memoryInterval=setInterval(n,this.store.configs.memoryLogInterval)}startCpuCollector(){if(this.cpuInterval)clearInterval(this.cpuInterval);let n=()=>{if(!this.store.configs.logCpu)return;let r=Ou.cpus(),t=0,o=0,c=0,i=0;for(let f of r)t+=f.times.user,o+=f.times.sys,c+=f.times.idle,i+=f.times.user+f.times.nice+f.times.sys+f.times.idle+f.times.irq;let a=0,e=0;if(this.lastCpuInfo){let f=i-this.lastCpuInfo.total,d=c-this.lastCpuInfo.idle;if(f>0){let l=f-d;a=Math.round((t-0)/(l||1)*100*100)/100,e=Math.round((o-0)/(l||1)*100*100)/100;let b=Math.round((1-d/f)*100*100)/100;a=Math.round(b*0.7*100)/100,e=Math.round(b*0.3*100)/100}}this.lastCpuInfo={idle:c,total:i};let s={timestamp:Date.now(),user:a,system:e};if(this.store.logs.cpu.push(s),this.store.logs.cpu.length>this.store.logLimits.cpu*2)this.store.logs.cpu=this.store.logs.cpu.slice(-this.store.logLimits.cpu);this.store.worker.cpu=s,this.store.worker.updatedAt=Date.now()};n(),this.cpuInterval=setInterval(n,this.store.configs.cpuLogInterval)}recordRequest(n){if(this.store.requests.push(n),this.store.requests.length>this.store.logLimits.request*2)this.store.requests=this.store.requests.slice(-this.store.logLimits.request)}recordDaprEvent(n,r){if(!this.store.configs.logDapr)return;let t={id:Gu(),type:n,timestamp:Date.now(),...r};if(this.store.logs.dapr.push(t),this.store.daprEvents.push(t),this.store.logs.dapr.length>this.store.logLimits.dapr*2)this.store.logs.dapr=this.store.logs.dapr.slice(-this.store.logLimits.dapr);if(this.store.daprEvents.length>this.store.logLimits.dapr*2)this.store.daprEvents=this.store.daprEvents.slice(-this.store.logLimits.dapr)}recordWsEvent(n,r){if(!this.store.configs.logWebSocket)return;let t={id:Gu(),type:n,timestamp:Date.now(),...r};if(this.store.logs.ws.push(t),this.store.wsEvents.push(t),this.store.logs.ws.length>this.store.logLimits.ws*2)this.store.logs.ws=this.store.logs.ws.slice(-this.store.logLimits.ws);if(this.store.wsEvents.length>this.store.logLimits.ws*2)this.store.wsEvents=this.store.wsEvents.slice(-this.store.logLimits.ws)}getSnapshot(){return{memory:this.store.logs.memory.slice(-this.store.logLimits.memory),cpu:this.store.logs.cpu.slice(-this.store.logLimits.cpu),requests:this.store.requests.slice(-this.store.logLimits.request),dapr:this.store.logs.dapr.slice(-this.store.logLimits.dapr),ws:this.store.logs.ws.slice(-this.store.logLimits.ws),workers:this.store.allWorkers.length?this.store.allWorkers:[this.store.worker],logLimits:{...this.store.logLimits},configs:{...this.store.configs}}}getUpdatesSince(n){let r=this.store.logs.memory.filter((e)=>e.timestamp>n.memory),t=this.store.logs.cpu.filter((e)=>e.timestamp>n.cpu),o=this.store.requests.filter((e)=>e.timestamp>n.request),c=this.store.logs.dapr.filter((e)=>e.timestamp>n.dapr),i=this.store.logs.ws.filter((e)=>e.timestamp>n.ws);if(!(r.length>0||t.length>0||o.length>0||c.length>0||i.length>0))return null;return{memory:r,cpu:t,requests:o,dapr:c,ws:i,timestamp:Date.now()}}getLogs(){return{memory:this.store.logs.memory,cpu:this.store.logs.cpu,requests:this.store.requests,dapr:this.store.logs.dapr,ws:this.store.logs.ws,daprEvents:this.store.daprEvents,wsEvents:this.store.wsEvents,configs:{logMemory:this.store.configs.logMemory,logCpu:this.store.configs.logCpu,logDapr:this.store.configs.logDapr,logWebSocket:this.store.configs.logWebSocket},limits:{...this.store.logLimits}}}getSettings(){return{configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}changeSettings(n){if(n.logMemory!==void 0)this.store.configs.logMemory=n.logMemory;if(n.logCpu!==void 0)this.store.configs.logCpu=n.logCpu;if(n.logDapr!==void 0)this.store.configs.logDapr=n.logDapr;if(n.logWebSocket!==void 0)this.store.configs.logWebSocket=n.logWebSocket;if(n.cpuLogInterval!==void 0){if(this.store.configs.cpuLogInterval=n.cpuLogInterval,this.isRunning&&this.store.configs.logCpu)this.startCpuCollector()}if(n.memoryLogInterval!==void 0){if(this.store.configs.memoryLogInterval=n.memoryLogInterval,this.isRunning&&this.store.configs.logMemory)this.startMemoryCollector()}if(n.memoryLogLimit!==void 0)this.store.logLimits.memory=n.memoryLogLimit;if(n.cpuLogLimit!==void 0)this.store.logLimits.cpu=n.cpuLogLimit;if(n.daprLogLimit!==void 0)this.store.logLimits.dapr=n.daprLogLimit;if(n.wsLogLimit!==void 0)this.store.logLimits.ws=n.wsLogLimit;if(n.requestLogLimit!==void 0)this.store.logLimits.request=n.requestLogLimit;return{message:"Settings updated successfully",configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}getStore(){return this.store}isEnabled(){return this.isRunning}}var T5;var Nu=g(()=>{T5={enabled:!0,logMemory:!0,logCpu:!0,logDapr:!0,logWebSocket:!0,memoryLogInterval:1000,cpuLogInterval:1000,memoryLogLimit:100,cpuLogLimit:100,daprLogLimit:100,wsLogLimit:100,requestLogLimit:100,streamInterval:150}});class v0{redis;logger;config;appId;flushToDb;systemCollector;applicationCollector;alertService;collectInterval=null;flushInterval=null;pendingMetrics=[];isRunning=!1;constructor(n){this.redis=n.redis,this.logger=n.logger,this.config=this.mergeConfig(n.config),this.appId=n.appId,this.flushToDb=n.flushToDb,this.systemCollector=new K0(this.config.system),this.applicationCollector=new j0(this.config.application),this.alertService=new ya({logger:n.logger,gmail:n.gmail,config:this.config,appId:n.appId})}mergeConfig(n){return{enabled:n.enabled??Un.enabled,system:{enabled:n.system?.enabled??Un.system.enabled,collectInterval:n.system?.collectInterval??Un.system.collectInterval,metrics:{cpu:n.system?.metrics?.cpu??Un.system.metrics.cpu,memory:n.system?.metrics?.memory??Un.system.metrics.memory,disk:n.system?.metrics?.disk??Un.system.metrics.disk,network:n.system?.metrics?.network??Un.system.metrics.network,process:n.system?.metrics?.process??Un.system.metrics.process}},application:{enabled:n.application?.enabled??Un.application.enabled,metrics:{requests:n.application?.metrics?.requests??Un.application.metrics.requests,responseTime:n.application?.metrics?.responseTime??Un.application.metrics.responseTime,errors:n.application?.metrics?.errors??Un.application.metrics.errors,rateLimits:n.application?.metrics?.rateLimits??Un.application.metrics.rateLimits}},database:{enabled:n.database?.enabled??Un.database.enabled,metrics:{connections:n.database?.metrics?.connections??Un.database.metrics.connections,queryTime:n.database?.metrics?.queryTime??Un.database.metrics.queryTime,slowQueryThreshold:n.database?.metrics?.slowQueryThreshold??Un.database.metrics.slowQueryThreshold}},redis:{enabled:n.redis?.enabled??Un.redis.enabled},persistence:{enabled:n.persistence?.enabled??Un.persistence.enabled,flushInterval:n.persistence?.flushInterval??Un.persistence.flushInterval,retentionDays:n.persistence?.retentionDays??Un.persistence.retentionDays},alerts:{enabled:n.alerts?.enabled??Un.alerts.enabled,email:{enabled:n.alerts?.email?.enabled??Un.alerts.email.enabled,recipients:n.alerts?.email?.recipients??Un.alerts.email.recipients},thresholds:{cpuPercent:n.alerts?.thresholds?.cpuPercent??Un.alerts.thresholds.cpuPercent,memoryPercent:n.alerts?.thresholds?.memoryPercent??Un.alerts.thresholds.memoryPercent,diskPercent:n.alerts?.thresholds?.diskPercent??Un.alerts.thresholds.diskPercent,errorRatePercent:n.alerts?.thresholds?.errorRatePercent??Un.alerts.thresholds.errorRatePercent,responseTimeMs:n.alerts?.thresholds?.responseTimeMs??Un.alerts.thresholds.responseTimeMs,rateLimitBlocksPerMinute:n.alerts?.thresholds?.rateLimitBlocksPerMinute??Un.alerts.thresholds.rateLimitBlocksPerMinute},cooldown:n.alerts?.cooldown??Un.alerts.cooldown}}}parseTimeToMs(n){let r=n.match(/^(\d+)(ms|s|m|h|d)$/);if(!r||!r[1]||!r[2])return 1e4;let t=parseInt(r[1],10);switch(r[2]){case"ms":return t;case"s":return t*1000;case"m":return t*60*1000;case"h":return t*60*60*1000;case"d":return t*24*60*60*1000;default:return 1e4}}start(){if(!this.config.enabled||this.isRunning)return;this.isRunning=!0,this.logger.info("[Monitoring] Starting monitoring service");let n=this.parseTimeToMs(this.config.system.collectInterval);if(this.collectInterval=setInterval(()=>{this.collect()},n),this.config.persistence.enabled&&this.flushToDb){let r=this.parseTimeToMs(this.config.persistence.flushInterval);this.flushInterval=setInterval(()=>{this.flush()},r)}this.collect()}stop(){if(!this.isRunning)return;if(this.isRunning=!1,this.logger.info("[Monitoring] Stopping monitoring service"),this.collectInterval)clearInterval(this.collectInterval),this.collectInterval=null;if(this.flushInterval)clearInterval(this.flushInterval),this.flushInterval=null;this.flush()}async collect(){let n=Date.now(),r={timestamp:n};if(this.config.system.enabled){let t=await this.systemCollector.collect();if(t)r.system=t,this.addMetricPoints("system",t,n)}if(this.config.application.enabled){let t=this.applicationCollector.collect();if(t)r.application=t,this.addMetricPoints("application",t,n)}if(await this.storeSnapshot(r),this.config.alerts.enabled)await this.alertService.checkAndAlert(r)}addMetricPoints(n,r,t){let o=(c,i="")=>{for(let a in c){let e=c[a],s=i?`${i}.${a}`:a;if(typeof e==="number")this.pendingMetrics.push({timestamp:t,metricType:n,metricName:s,value:e});else if(typeof e==="object"&&e!==null&&!Array.isArray(e))o(e,s)}};o(r)}async storeSnapshot(n){let r=`monitoring:${this.appId}:latest`;await this.redis.create(r,n,3600);let t=`monitoring:${this.appId}:history`,o=await this.redis.read(t),c=o.success&&o.data?o.data:[];c.push(n);let i=Date.now()-3600000,a=c.filter((e)=>e.timestamp>i);await this.redis.create(t,a,3600)}async flush(){if(this.pendingMetrics.length===0)return;if(!this.flushToDb)return;let n=[...this.pendingMetrics];this.pendingMetrics=[];try{await this.flushToDb(n),this.logger.debug(`[Monitoring] Flushed ${n.length} metrics to database`)}catch(r){this.logger.error(`[Monitoring] Failed to flush metrics: ${r}`),this.pendingMetrics=[...n,...this.pendingMetrics]}}recordRequest(n){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRequest(n)}recordRateLimitBlock(){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRateLimitBlock()}async getLatestSnapshot(){let n=`monitoring:${this.appId}:latest`,r=await this.redis.read(n);return r.success?r.data:null}async getHistory(n=60){let r=`monitoring:${this.appId}:history`,t=await this.redis.read(r);if(!t.success||!t.data)return[];let o=Date.now()-n*60000;return t.data.filter((c)=>c.timestamp>o)}getActiveAlerts(){return this.alertService.getActiveAlerts()}acknowledgeAlert(n){return this.alertService.acknowledgeAlert(n)}isEnabled(){return this.config.enabled}getConfig(){return this.config}}var Un;var xu=g(()=>{Qu();Nu();Un={enabled:!1,system:{enabled:!0,collectInterval:"10s",metrics:{cpu:!0,memory:!0,disk:!0,network:!1,process:!0}},application:{enabled:!0,metrics:{requests:!0,responseTime:!0,errors:!0,rateLimits:!0}},database:{enabled:!1,metrics:{connections:!0,queryTime:!0,slowQueryThreshold:"100ms"}},redis:{enabled:!1},persistence:{enabled:!0,flushInterval:"1m",retentionDays:30},alerts:{enabled:!1,email:{enabled:!1,recipients:[]},thresholds:{cpuPercent:80,memoryPercent:85,diskPercent:90,errorRatePercent:5,responseTimeMs:1000,rateLimitBlocksPerMinute:100},cooldown:"5m"}}});var Pu=()=>{};import{and as Hc,desc as Cu,eq as er}from"drizzle-orm";function Z0(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());r[c]=o}return r}function n$(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/[A-Z]/g,(i)=>`_${i.toLowerCase()}`);r[c]=o}return r}class I0{db;schemaTables;config;logger;gmailService;constructor(n){this.db=n.db,this.schemaTables=n.schemaTables,this.config=n.config,this.logger=n.logger,this.gmailService=n.gmailService}getTable(n){return this.schemaTables[n]}getCol(n,r){return n[r]}isChannelEnabled(n){let r=this.config.channels;if(!r)return n==="portal";switch(n){case"portal":return r.portal!==!1;case"email":return r.email===!0;case"sms":return r.sms?.enabled===!0;case"telegram":return r.telegram?.enabled===!0;case"webhook":return r.webhook?.enabled===!0;default:return!1}}interpolateTemplate(n,r){let t=n;for(let[o,c]of Object.entries(r))t=t.replace(new RegExp(`{{${o}}}`,"g"),String(c??""));for(let[o,c]of Object.entries(this.config.templateVariables||{}))t=t.replace(new RegExp(`{{${o}}}`,"g"),c);return t}async triggerNotifications(n){let{trigger:r,flow_id:t,entity_name:o,entity_id:c,node_id:i,context:a={}}=n,e=this.getTable("verificationNotificationRules"),s=this.getTable("verificationNotificationRecipients"),f=this.getTable("verificationNotificationChannels");if(!e||!s){this.logger.warn("[Notification] Notification tables not found");return}let d=new Date,b=await this.db.select().from(e).where(Hc(er(this.getCol(e,"flowId"),t),er(this.getCol(e,"trigger"),r)));this.logger.info(`[Notification] Found ${b.length} rules for trigger=${r} flow_id=${t}, filter_node_id=${i||"NONE"}`);for(let u of b)this.logger.info(`[Notification] Rule ${u.id}: nodeId=${u.nodeId}, trigger=${u.trigger}, title=${JSON.stringify(u.titleTemplate)}`);let w=b.filter((u)=>{if(i&&u.nodeId!==i)return this.logger.info(`[Notification] EXCLUDED rule ${u.id}: rule.nodeId=${u.nodeId} !== filter_node_id=${i}`),!1;if(u.startsAt&&new Date(u.startsAt)>d)return!1;if(u.expiresAt&&new Date(u.expiresAt)<d)return!1;return!0});for(let u of w){let m=await this.db.select().from(s).where(er(this.getCol(s,"ruleId"),u.id)),_=["portal"];if(f){let H=await this.db.select().from(f).where(er(this.getCol(f,"ruleId"),u.id));if(H.length>0)_=H.map((D)=>D.channel)}let S=_.filter((H)=>this.isChannelEnabled(H));if(S.length===0)continue;this.logger.info(`[Notification] Rule ${u.id}: ${m.length} recipients, ${S.length} channels (${S.join(",")})`);let $=await this.resolveRecipients(m,n.verifier_id,t,o,c);this.logger.info(`[Notification] Rule ${u.id}: resolved ${$.length} user IDs: ${$.join(", ")}`);let E={...a,entity_name:o,entity_id:c,trigger:r,decision:n.decision};this.logger.info(`[Notification] Rule ${u.id}: titleTemplate=${JSON.stringify(u.titleTemplate)}, bodyTemplate=${JSON.stringify(u.bodyTemplate)}, context=${JSON.stringify(E)}`);let W=u.titleTemplate?this.interpolateTemplate(u.titleTemplate,E):`Verification ${r.replace("on_","").replace("_"," ")}`,Y=u.bodyTemplate?this.interpolateTemplate(u.bodyTemplate,E):void 0;this.logger.info(`[Notification] Rule ${u.id}: final title="${W}", body="${Y}"`);for(let H of $)await this.send({user_id:H,title:W,body:Y,entity_name:o,entity_id:c,type:"verification",source:`flow:${t}`,channels:S})}this.logger.debug(`[Notification] Triggered ${w.length} rules for ${r} on ${o}:${c}`)}async resolveRecipients(n,r,t,o,c){let i=new Set,a=this.getTable("user_roles"),e=this.getTable("roles");for(let s of n)switch(s.recipientType){case"user":if(s.recipientUserId)i.add(s.recipientUserId);break;case"role":if(s.recipientRole&&a&&e){let f=e,d=a,b=(await this.db.select().from(e).where(er(f.name,s.recipientRole)).limit(1))[0];if(b){let w=await this.db.select({user_id:d.userId}).from(a).where(er(d.roleId,b.id));for(let u of w)i.add(u.user_id)}}break;case"step_verifier":if(r)i.add(r);break;case"entity_creator":{if(o&&c){let f=this.getTable("verificationInstances");if(f){let l=(await this.db.select().from(f).where(Hc(er(this.getCol(f,"entityName"),o),er(this.getCol(f,"entityId"),c))).orderBy(Cu(this.getCol(f,"createdAt"))).limit(1))[0];if(l?.startedBy)i.add(l.startedBy)}}break}case"all_verifiers":{if(t){let f=this.getTable("verificationVerifierConfigs");if(f){let d=await this.db.select().from(f).where(er(this.getCol(f,"flowId"),t));for(let l of d){let b=l;if(b.verifierUserId)i.add(b.verifierUserId);if(b.verifierType==="role"&&b.verifierRole&&a&&e){let w=e,u=a,_=(await this.db.select().from(e).where(er(w.name,b.verifierRole)).limit(1))[0];if(_){let S=await this.db.select({user_id:u.userId}).from(a).where(er(u.roleId,_.id));for(let $ of S)i.add($.user_id)}}}}}break}}return Array.from(i)}async send(n){let{user_id:r,title:t,body:o,entity_name:c,entity_id:i,type:a,source:e,channels:s}=n;for(let f of s)switch(f){case"portal":await this.sendPortalNotification(r,t,o,c,i,a,e);break;case"email":await this.sendEmailNotification(r,t,o);break;case"sms":this.logger.debug(`[Notification] SMS channel not yet implemented for user ${r}`);break;case"telegram":this.logger.debug(`[Notification] Telegram channel not yet implemented for user ${r}`);break;case"webhook":this.logger.debug(`[Notification] Webhook channel not yet implemented for user ${r}`);break}}async sendPortalNotification(n,r,t,o,c,i,a){let e=this.getTable("notifications");if(!e){this.logger.warn("[Notification] notifications table not found");return}await this.db.insert(e).values(Z0({user_id:n,title:r,body:t||null,entity_name:o||null,entity_id:c||null,type:i||"system",source:a||null,is_seen:!1})),this.logger.debug(`[Notification] Portal notification sent to ${n}: ${r}`)}async sendEmailNotification(n,r,t){if(!this.gmailService?.isAvailable()){this.logger.warn("[Notification] Gmail service not available for email notification");return}let o=this.getTable("users");if(!o){this.logger.warn("[Notification] users table not found");return}let i=(await this.db.select({email:this.getCol(o,"email")}).from(o).where(er(this.getCol(o,"id"),n)).limit(1))[0];if(!i?.email){this.logger.warn(`[Notification] No email found for user ${n}`);return}await this.gmailService.sendEmail({to:i.email,subject:r,html:t||r}),this.logger.debug(`[Notification] Email notification sent to ${i.email}: ${r}`)}async getNotifications(n,r){let t=this.getTable("notifications");if(!t)return[];let o=[er(this.getCol(t,"userId"),n)];if(r?.type)o.push(er(this.getCol(t,"type"),r.type));return(await this.db.select().from(t).where(Hc(...o)).orderBy(Cu(this.getCol(t,"createdAt"))).limit(r?.limit||50).offset(r?.offset||0)).map((a)=>n$(a))}async getUnseenCount(n){let r=this.getTable("notifications");if(!r)return 0;return(await this.db.select().from(r).where(Hc(er(this.getCol(r,"userId"),n),er(this.getCol(r,"isSeen"),!1)))).length}async markAsSeen(n,r){let t=this.getTable("notifications");if(!t)return!1;return await this.db.update(t).set(Z0({is_seen:!0,seen_at:new Date})).where(Hc(er(this.getCol(t,"id"),n),er(this.getCol(t,"userId"),r))),!0}async markAllAsSeen(n){let r=this.getTable("notifications");if(!r)return 0;return(await this.db.update(r).set(Z0({is_seen:!0,seen_at:new Date})).where(Hc(er(this.getCol(r,"userId"),n),er(this.getCol(r,"isSeen"),!1))).returning()).length}}var p0=g(()=>{Pu()});function qu(n,r){if(!n.authorizationUrl)throw Error("Generic OAuth provider requires authorizationUrl");let t=n.scopes??[],o=new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",state:r,...t.length>0?{scope:t.join(" ")}:{},...n.extraAuthParams});return`${n.authorizationUrl}?${o.toString()}`}async function Fu(n,r){if(!r.tokenUrl)throw Error("Generic OAuth provider requires tokenUrl");let t=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Generic OAuth token exchange failed: ${s}`)}let o=await t.json();if(o.error)throw Error(`OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope};if(!r.userInfoUrl)return{profile:{providerAccountId:o.access_token,rawProfile:o},tokens:c};let i=await fetch(r.userInfoUrl,{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch user info from generic OAuth provider");let a=await i.json();return{profile:{providerAccountId:a.id??a.sub??a.user_id??o.access_token,email:a.email,name:a.name??a.display_name??a.username,avatarUrl:a.avatar_url??a.picture??a.photo,rawProfile:a},tokens:c}}function ju(n,r){let t=n.scopes??["read:user","user:email"];return`https://github.com/login/oauth/authorize?${new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,scope:t.join(" "),state:r,...n.extraAuthParams}).toString()}`}async function Ku(n,r){let t=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri}).toString()});if(!t.ok){let f=await t.text();throw Error(`GitHub token exchange failed: ${f}`)}let o=await t.json();if(o.error)throw Error(`GitHub OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${o.access_token}`,Accept:"application/vnd.github+json"}});if(!i.ok)throw Error("Failed to fetch GitHub user info");let a=await i.json(),e=a.email;if(!e)try{let f=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${o.access_token}`,Accept:"application/vnd.github+json"}});if(f.ok){let d=await f.json();e=d.find((b)=>b.primary&&b.verified)?.email??d[0]?.email}}catch{}return{profile:{providerAccountId:String(a.id),email:e,name:a.name??a.login,avatarUrl:a.avatar_url,rawProfile:a},tokens:c}}function vu(n,r){let t=n.scopes??["openid","email","profile"];return`https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",scope:t.join(" "),state:r,access_type:"offline",prompt:"select_account",...n.extraAuthParams}).toString()}`}async function Zu(n,r){let t=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Google token exchange failed: ${s}`)}let o=await t.json(),c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://www.googleapis.com/oauth2/v3/userinfo",{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch Google user info");let a=await i.json();return{profile:{providerAccountId:a.sub,email:a.email,name:a.name,avatarUrl:a.picture,rawProfile:a},tokens:c}}function Iu(n){return`https://login.microsoftonline.com/${n.tenantId??"common"}/oauth2/v2.0`}function pu(n,r){let t=n.scopes??["openid","email","profile","User.Read"],o=new URLSearchParams({client_id:n.clientId,redirect_uri:n.redirectUri,response_type:"code",scope:t.join(" "),state:r,response_mode:"query",...n.extraAuthParams});return`${Iu(n)}/authorize?${o.toString()}`}async function yu(n,r){let t=await fetch(`${Iu(r)}/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:n,client_id:r.clientId,client_secret:r.clientSecret,redirect_uri:r.redirectUri,grant_type:"authorization_code"}).toString()});if(!t.ok){let s=await t.text();throw Error(`Microsoft token exchange failed: ${s}`)}let o=await t.json();if(o.error)throw Error(`Microsoft OAuth error: ${o.error_description||o.error}`);let c={accessToken:o.access_token,refreshToken:o.refresh_token,expiresAt:o.expires_in?new Date(Date.now()+o.expires_in*1000):void 0,scope:o.scope},i=await fetch("https://graph.microsoft.com/v1.0/me",{headers:{Authorization:`Bearer ${o.access_token}`}});if(!i.ok)throw Error("Failed to fetch Microsoft user info");let a=await i.json();return{profile:{providerAccountId:a.id,email:a.mail??a.userPrincipalName,name:a.displayName,avatarUrl:void 0,rawProfile:a},tokens:c}}import{randomBytes as r$}from"crypto";class ne{config;stateStore=new Map;cleanupInterval=null;constructor(n){this.config=n;let r=(n.stateTtlSeconds??600)*1000;this.cleanupInterval=setInterval(()=>{let t=Date.now();for(let[o,c]of this.stateStore.entries())if(c.expiresAt<t)this.stateStore.delete(o)},r)}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isProviderEnabled(n){return!!(this.config.enabled&&this.config.providers[n])}getEnabledProviders(){if(!this.config.enabled)return[];return Object.keys(this.config.providers)}buildAuthorizationUrl(n,r,t){let o=this.config.providers[n];if(!o)throw Error(`OAuth provider "${n}" is not configured`);let c={provider:n,linkUserId:r,redirectUrl:t,createdAt:Date.now()},i=r$(32).toString("hex"),a=(this.config.stateTtlSeconds??600)*1000;switch(this.stateStore.set(i,{payload:c,expiresAt:Date.now()+a}),n){case"google":return vu(o,i);case"github":return ju(o,i);case"microsoft":return pu(o,i);default:return qu(o,i)}}consumeState(n){let r=this.stateStore.get(n);if(!r)return null;if(r.expiresAt<Date.now())return this.stateStore.delete(n),null;return this.stateStore.delete(n),r.payload}async exchangeCode(n,r){let t=this.config.providers[n];if(!t)throw Error(`OAuth provider "${n}" is not configured`);switch(n){case"google":return Zu(r,t);case"github":return Ku(r,t);case"microsoft":return yu(r,t);default:return Fu(r,t)}}get allowAccountLinking(){return this.config.allowAccountLinking??!0}get autoCreateUser(){return this.config.autoCreateUser??!0}get successRedirectUrl(){return this.config.successRedirectUrl??"/"}get errorRedirectUrl(){return this.config.errorRedirectUrl??"/login"}get sendInviteOnCreate(){return this.config.sendInviteOnCreate??!1}get basePath(){return this.config.basePath??"/auth/oauth"}}var Tu=()=>{};var y0=g(()=>{Tu()});class T0{redis;logger;config;constructor(n){this.redis=n.redis,this.logger=n.logger,this.config=this.mergeConfig(n.config)}mergeConfig(n){return{enabled:n.enabled??$r.enabled,strategy:n.strategy??$r.strategy,keyPrefix:n.keyPrefix??$r.keyPrefix,authRoutes:{window:n.authRoutes?.window??$r.authRoutes.window,max:n.authRoutes?.max??$r.authRoutes.max,login:{window:n.authRoutes?.login?.window??re.window,max:n.authRoutes?.login?.max??re.max,blockDuration:n.authRoutes?.login?.blockDuration??re.blockDuration},register:{window:n.authRoutes?.register?.window??te.window,max:n.authRoutes?.register?.max??te.max,blockDuration:n.authRoutes?.register?.blockDuration??te.blockDuration},passwordReset:{window:n.authRoutes?.passwordReset?.window??oe.window,max:n.authRoutes?.passwordReset?.max??oe.max,blockDuration:n.authRoutes?.passwordReset?.blockDuration??oe.blockDuration},magicLink:{window:n.authRoutes?.magicLink?.window??ce.window,max:n.authRoutes?.magicLink?.max??ce.max,blockDuration:n.authRoutes?.magicLink?.blockDuration??ce.blockDuration}},publicRoutes:{window:n.publicRoutes?.window??$r.publicRoutes.window,max:n.publicRoutes?.max??$r.publicRoutes.max},privateRoutes:{window:n.privateRoutes?.window??$r.privateRoutes.window,max:n.privateRoutes?.max??$r.privateRoutes.max},byIp:n.byIp??$r.byIp,byUserId:n.byUserId??$r.byUserId,byEndpoint:n.byEndpoint??$r.byEndpoint,skipSuccessfulRequests:n.skipSuccessfulRequests??$r.skipSuccessfulRequests,headers:{remaining:n.headers?.remaining??$r.headers.remaining,reset:n.headers?.reset??$r.headers.reset,limit:n.headers?.limit??$r.headers.limit},whitelist:n.whitelist??$r.whitelist,blacklist:n.blacklist??$r.blacklist}}parseTimeToMs(n){let r=n.match(/^(\d+)(ms|s|m|h|d)$/);if(!r||!r[1]||!r[2])return 60000;let t=parseInt(r[1],10);switch(r[2]){case"ms":return t;case"s":return t*1000;case"m":return t*60*1000;case"h":return t*60*60*1000;case"d":return t*24*60*60*1000;default:return 60000}}buildKey(n){let r=[this.config.keyPrefix,n.category];if(n.authType&&n.authType!=="other")r.push(n.authType);if(this.config.byIp&&n.ip)r.push(`ip:${n.ip}`);if(this.config.byUserId&&n.userId)r.push(`user:${n.userId}`);if(this.config.byEndpoint&&n.endpoint)r.push(`ep:${n.endpoint.replace(/\//g,"_")}`);return r.join(":")}getLimits(n,r){if(n==="auth"){if(r&&r!=="other"){let t=this.config.authRoutes[r];if(t)return t}return{window:this.config.authRoutes.window,max:this.config.authRoutes.max}}if(n==="public")return this.config.publicRoutes;return this.config.privateRoutes}isWhitelisted(n){return this.config.whitelist.some((r)=>{if(r.includes("*"))return new RegExp(`^${r.replace(/\*/g,".*")}$`).test(n);return r===n})}isBlacklisted(n){return this.config.blacklist.some((r)=>{if(r.includes("*"))return new RegExp(`^${r.replace(/\*/g,".*")}$`).test(n);return r===n})}async readRedis(n){let r=await this.redis.read(n);if(r.success)return r.data;return null}async check(n){if(!this.config.enabled)return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isWhitelisted(n.ip))return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isBlacklisted(n.ip))return this.logger.warn(`[RateLimit] Blacklisted IP: ${n.ip}`),{allowed:!1,remaining:0,resetAt:Date.now()+86400000,limit:0,retryAfter:86400};let r=this.buildKey(n),t=this.getLimits(n.category,n.authType),o=this.parseTimeToMs(t.window),c=`${r}:blocked`,i=await this.readRedis(c);if(i&&i.until>Date.now()){let a=Math.ceil((i.until-Date.now())/1000);return this.logger.warn(`[RateLimit] Blocked: ${r}, retry after ${a}s`),{allowed:!1,remaining:0,resetAt:i.until,limit:t.max,retryAfter:a}}if(this.config.strategy==="sliding-window")return this.slidingWindowCheck(r,t.max,o,t.blockDuration);if(this.config.strategy==="fixed-window")return this.fixedWindowCheck(r,t.max,o,t.blockDuration);return this.tokenBucketCheck(r,t.max,o)}async slidingWindowCheck(n,r,t,o){let c=Date.now(),i=c-t,a=`${n}:sw`,s=(await this.readRedis(a))?.timestamps||[];s=s.filter((b)=>b>i);let f=s.length,d=s[0],l=d!==void 0?d+t:c+t;if(f>=r){if(o){let b=this.parseTimeToMs(o);await this.redis.create(`${n}:blocked`,{until:c+b},Math.ceil(b/1000))}return{allowed:!1,remaining:0,resetAt:l,limit:r,retryAfter:Math.ceil((l-c)/1000)}}return s.push(c),await this.redis.create(a,{timestamps:s},Math.ceil(t/1000)+1),{allowed:!0,remaining:r-s.length,resetAt:l,limit:r}}async fixedWindowCheck(n,r,t,o){let c=Date.now(),i=Math.floor(c/t),a=`${n}:fw:${i}`,e=(i+1)*t,f=(await this.readRedis(a))?.count||0;if(f>=r){if(o){let d=this.parseTimeToMs(o);await this.redis.create(`${n}:blocked`,{until:c+d},Math.ceil(d/1000))}return{allowed:!1,remaining:0,resetAt:e,limit:r,retryAfter:Math.ceil((e-c)/1000)}}return await this.redis.create(a,{count:f+1},Math.ceil(t/1000)+1),{allowed:!0,remaining:r-(f+1),resetAt:e,limit:r}}async tokenBucketCheck(n,r,t){let o=Date.now(),c=r/t,i=`${n}:tb`,a=await this.readRedis(i),e=a?.tokens??r,s=a?.lastRefill??o,d=(o-s)*c;if(e=Math.min(r,e+d),e<1){let l=Math.ceil((1-e)/c);return{allowed:!1,remaining:0,resetAt:o+l,limit:r,retryAfter:Math.ceil(l/1000)}}return e-=1,await this.redis.create(i,{tokens:e,lastRefill:o},Math.ceil(t/1000)*2),{allowed:!0,remaining:Math.floor(e),resetAt:o+t,limit:r}}async decrement(n){if(!this.config.skipSuccessfulRequests)return;let r=this.buildKey(n);if(this.config.strategy==="sliding-window"){let t=`${r}:sw`,o=await this.readRedis(t);if(o?.timestamps?.length){o.timestamps.pop();let c=this.parseTimeToMs(this.getLimits(n.category,n.authType).window);await this.redis.create(t,o,Math.ceil(c/1000)+1)}}else if(this.config.strategy==="fixed-window"){let t=this.parseTimeToMs(this.getLimits(n.category,n.authType).window),o=Math.floor(Date.now()/t),c=`${r}:fw:${o}`,i=await this.readRedis(c);if(i?.count)await this.redis.create(c,{count:i.count-1},Math.ceil(t/1000)+1)}}getHeaders(n){let r={};return r[this.config.headers.remaining]=String(n.remaining),r[this.config.headers.reset]=String(Math.ceil(n.resetAt/1000)),r[this.config.headers.limit]=String(n.limit),r}isEnabled(){return this.config.enabled}}var re,te,oe,ce,$r;var nb=g(()=>{re={window:"15m",max:5,blockDuration:"30m"},te={window:"1h",max:3,blockDuration:"1h"},oe={window:"1h",max:3,blockDuration:"1h"},ce={window:"1h",max:5,blockDuration:"1h"},$r={enabled:!0,strategy:"sliding-window",keyPrefix:"rl:",authRoutes:{window:"1m",max:10,login:re,register:te,passwordReset:oe,magicLink:ce},publicRoutes:{window:"1m",max:100},privateRoutes:{window:"1m",max:60},byIp:!0,byUserId:!0,byEndpoint:!1,skipSuccessfulRequests:!1,headers:{remaining:"X-RateLimit-Remaining",reset:"X-RateLimit-Reset",limit:"X-RateLimit-Limit"},whitelist:[],blacklist:[]}});var rb=()=>{};import{and as Xt,desc as nf,eq as on,inArray as tb}from"drizzle-orm";function zr(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());r[c]=o}return r}function Sr(n){let r={};for(let[t,o]of Object.entries(n)){let c=t.replace(/[A-Z]/g,(i)=>`_${i.toLowerCase()}`);r[c]=o}return r}class rf{db;schemaTables;config;logger;onNotificationTrigger;constructor(n){this.db=n.db,this.schemaTables=n.schemaTables,this.config=n.config,this.logger=n.logger}setNotificationHandler(n){this.onNotificationTrigger=n}getConnectedNotificationNodeIds(n,r,t){let o=[];this.logger.info(`[Verification] getConnectedNotificationNodeIds: stepNodeId=${n}, totalSteps=${r.length}, totalEdges=${t.length}`);let c=r.filter((i)=>i.nodeType==="notification");this.logger.info(`[Verification] All notification nodes in graph: ${c.map((i)=>i.nodeId).join(", ")}`);for(let i of t){let{sourceNodeId:a,targetNodeId:e}=i;if(a===n||e===n){let s=a===n?e:a,f=r.find((d)=>d.nodeId===s&&d.nodeType==="notification");if(this.logger.info(`[Verification] Edge ${a} -> ${e}: otherId=${s}, isNotification=${!!f}`),f)o.push(f.nodeId)}}return this.logger.info(`[Verification] Connected notification nodeIds for step ${n}: [${o.join(", ")}]`),o}getTable(n){return this.schemaTables[n]}getCol(n,r){return n[r]}async listFlows(n){let r=this.getTable("verificationFlows");if(!r)return[];return(await(n?this.db.select().from(r).where(on(this.getCol(r,"entityName"),n)):this.db.select().from(r))).map((c)=>Sr(c))}async getFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationNotificationRules"),a=this.getTable("verificationNotificationRecipients"),e=this.getTable("verificationNotificationChannels");if(!r)return null;let f=(await this.db.select().from(r).where(on(this.getCol(r,"id"),n)).limit(1))[0];if(!f)return null;let d=Sr(f),b=(t?await this.db.select().from(t).where(on(this.getCol(t,"flowId"),n)):[]).map((R)=>Sr(R)),u=(o?await this.db.select().from(o).where(on(this.getCol(o,"flowId"),n)):[]).map((R)=>Sr(R)),_=(c?await this.db.select().from(c).where(on(this.getCol(c,"flowId"),n)):[]).map((R)=>Sr(R)),$=(i?await this.db.select().from(i).where(on(this.getCol(i,"flowId"),n)):[]).map((R)=>Sr(R)),E=$.map((R)=>R.id),Y=(a&&E.length>0?await this.db.select().from(a).where(tb(this.getCol(a,"ruleId"),E)):[]).map((R)=>Sr(R)),D=(e&&E.length>0?await this.db.select().from(e).where(tb(this.getCol(e,"ruleId"),E)):[]).map((R)=>Sr(R));return{flow:d,graph:{steps:b,edges:u,verifier_configs:_,notification_rules:$,notification_recipients:Y,notification_channels:D}}}async saveFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationNotificationRules"),a=this.getTable("verificationNotificationRecipients"),e=this.getTable("verificationNotificationChannels");if(!r||!t||!o)throw Error("Verification tables not configured");let s=await this.db.select().from(r).where(on(this.getCol(r,"id"),n.flow_id)).limit(1),f=n.flow_id;if(s.length>0)await this.db.update(r).set(zr({entity_name:n.entity_name,name:n.name,description:n.description||null,trigger_on:n.trigger_on,trigger_fields:n.trigger_fields||null,is_draft:n.is_draft,viewport:n.viewport||null})).where(on(this.getCol(r,"id"),f));else{let[l]=await this.db.insert(r).values(zr({id:f,entity_name:n.entity_name,name:n.name,description:n.description||null,trigger_on:n.trigger_on,trigger_fields:n.trigger_fields||null,is_draft:n.is_draft,viewport:n.viewport||null})).returning();f=l.id}if(await this.db.delete(t).where(on(this.getCol(t,"flowId"),f)),o)await this.db.delete(o).where(on(this.getCol(o,"flowId"),f));if(c)await this.db.delete(c).where(on(this.getCol(c,"flowId"),f));if(i)await this.db.delete(i).where(on(this.getCol(i,"flowId"),f));let{graph:d}=n;if(d.steps.length>0)await this.db.insert(t).values(d.steps.map((l)=>zr({flow_id:f,entity_name:n.entity_name,node_id:l.node_id,node_type:l.node_type,step_order:l.step_order,name:l.name||null,description:l.description||null,position_x:l.position_x,position_y:l.position_y,width:l.width||null,height:l.height||null,style:l.style||null,data:l.data||null})));if(d.edges.length>0&&o)await this.db.insert(o).values(d.edges.map((l)=>zr({flow_id:f,edge_id:l.edge_id,source_node_id:l.source_node_id,target_node_id:l.target_node_id,source_handle:l.source_handle||null,target_handle:l.target_handle||null,edge_type:l.edge_type,label:l.label||null,condition:l.condition||null,style:l.style||null,animated:l.animated})));if(d.verifier_configs.length>0&&c)await this.db.insert(c).values(d.verifier_configs.map((l)=>zr({flow_id:f,node_id:l.node_id,verifier_type:l.verifier_type,verifier_user_id:l.verifier_user_id||null,verifier_role:l.verifier_role||null,require_signature:l.require_signature,all_must_approve:l.all_must_approve})));if(d.notification_rules.length>0&&i)for(let l of d.notification_rules){this.logger.info(`[Verification] Saving notification rule: node_id=${l.node_id}, trigger=${l.trigger}, title_template=${JSON.stringify(l.title_template)}, body_template=${JSON.stringify(l.body_template)}`);let[b]=await this.db.insert(i).values(zr({flow_id:f,node_id:l.node_id,trigger:l.trigger,title_template:l.title_template||null,body_template:l.body_template||null,starts_at:l.starts_at||null,expires_at:l.expires_at||null})).returning(),w=b.id,u=d.notification_recipients.filter((_)=>_.rule_id===l.node_id);if(u.length>0&&a)await this.db.insert(a).values(u.map((_)=>zr({rule_id:w,recipient_type:_.recipient_type,recipient_user_id:_.recipient_user_id||null,recipient_role:_.recipient_role||null})));let m=d.notification_channels.filter((_)=>_.rule_id===l.node_id);if(m.length>0&&e)await this.db.insert(e).values(m.map((_)=>zr({rule_id:w,channel:_.channel})))}return this.logger.info(`[Verification] Flow saved: ${f} for ${n.entity_name}`),{success:!0,flow_id:f}}async publishFlow(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};return await this.db.update(r).set(zr({is_draft:!1,published_at:new Date})).where(on(this.getCol(r,"id"),n)),this.logger.info(`[Verification] Flow published: ${n}`),{success:!0,message:"Flow published"}}async deleteFlow(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};return await this.db.delete(r).where(on(this.getCol(r,"id"),n)),this.logger.info(`[Verification] Flow deleted: ${n}`),{success:!0,message:"Flow deleted"}}async startFlow(n){let r=this.getTable("verificationFlows"),t=this.getTable("verificationSteps"),o=this.getTable("verificationEdges"),c=this.getTable("verificationVerifierConfigs"),i=this.getTable("verificationInstances"),a=this.getTable("verificationRequirements"),e=this.getTable("user_roles");if(!r||!t||!o||!i||!a)return{success:!1,message:"Verification tables not configured"};let f=(await this.db.select().from(r).where(Xt(on(this.getCol(r,"id"),n.flow_id),on(this.getCol(r,"isDraft"),!1))).limit(1))[0];if(!f)return{success:!1,message:"Published flow not found"};if((await this.db.select().from(i).where(Xt(on(this.getCol(i,"entityName"),n.entity_name),on(this.getCol(i,"entityId"),n.entity_id),on(this.getCol(i,"status"),"active"))).limit(1)).length>0)return{success:!1,message:"An active verification instance already exists for this entity"};let l=await this.db.select().from(t).where(on(this.getCol(t,"flowId"),n.flow_id)),b=await this.db.select().from(o).where(on(this.getCol(o,"flowId"),n.flow_id)),w=l.filter((_)=>_.nodeType==="step");if(w.sort((_,S)=>_.stepOrder-S.stepOrder),w.length===0)return{success:!1,message:"Flow has no step nodes"};let[u]=await this.db.insert(i).values(zr({flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,started_by:n.started_by||null,status:"active",current_step_order:1,started_at:new Date})).returning(),m=u.id;if(await this.materializeRequirementsForStep(m,n.flow_id,n.entity_name,n.entity_id,1,l,b,c,a,e),this.onNotificationTrigger){let _=w[0],S=_?.nodeId,$=S?this.getConnectedNotificationNodeIds(S,l,b):[],E={flow_name:f.name,step_name:_?.name||"Step 1",step_order:1,total_steps:w.length};if($.length>0)for(let W of $)await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,node_id:W,context:E});else await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:n.flow_id,entity_name:n.entity_name,entity_id:n.entity_id,context:E})}return this.logger.info(`[Verification] Flow started: instance ${m} for ${n.entity_name}:${n.entity_id}`),{success:!0,instance_id:m,message:"Flow started"}}async materializeRequirementsForStep(n,r,t,o,c,i,a,e,s,f){if(!s)return;let d=i.find((_)=>_.nodeType==="step"&&_.stepOrder===c);if(!d)return;let l=d.nodeId,w=a.filter((_)=>_.targetNodeId===l).map((_)=>_.sourceNodeId),u=i.filter((_)=>_.nodeType==="verifier"&&w.includes(_.nodeId));if(u.length===0)return;let m=[];if(e)m=await this.db.select().from(e).where(on(this.getCol(e,"flowId"),r));for(let _ of u){let S=_.nodeId,$=m.find((Y)=>Y.nodeId===S);if(!$)continue;let{verifierType:E,allMustApprove:W}=$;if(E==="role"&&W&&f){let Y=this.getTable("roles");if(Y){let H=Y,D=f,h=(await this.db.select().from(Y).where(on(H.name,$.verifierRole)).limit(1))[0];if(h){let A=await this.db.select({user_id:D.userId}).from(f).where(on(D.roleId,h.id));for(let M of A)await this.db.insert(s).values(zr({instance_id:n,step_node_id:l,verifier_node_id:S,entity_name:t,entity_id:o,verifier_type:"user",verifier_user_id:M.user_id,verifier_role:$.verifierRole||null,require_signature:$.requireSignature,all_must_approve:!0,step_order:c,status:"pending"}))}}}else await this.db.insert(s).values(zr({instance_id:n,step_node_id:l,verifier_node_id:S,entity_name:t,entity_id:o,verifier_type:E,verifier_user_id:$.verifierUserId||null,verifier_role:$.verifierRole||null,require_signature:$.requireSignature,all_must_approve:W,step_order:c,status:"pending"}))}if(this.onNotificationTrigger){let _=this.getConnectedNotificationNodeIds(l,i,a);if(this.logger.info(`[Verification] on_step_reached: stepNodeId=${l}, connectedNotifIds=[${_.join(", ")}]`),_.length>0)for(let S of _)this.logger.info(`[Verification] Triggering on_step_reached for notifNodeId=${S}`),await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:r,entity_name:t,entity_id:o,node_id:S,context:{step_name:d.name||`Step ${c}`,step_order:c}});else await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:r,entity_name:t,entity_id:o,context:{step_name:d.name||`Step ${c}`,step_order:c}})}}async getStatus(n,r){let t=this.getTable("verificationInstances"),o=this.getTable("verificationFlows"),c=this.getTable("verificationSteps"),i=this.getTable("verifications"),a=this.getTable("verificationRequirements"),e={entity_name:n,entity_id:r,instance:null,flow:null,current_step:0,total_steps:0,is_completed:!1,is_rejected:!1,verifications:[],pending_requirements:[]};if(!t||!o||!i||!a)return this.logger.error("[Verification] Required tables not found"),e;let f=(await this.db.select().from(t).where(Xt(on(this.getCol(t,"entityName"),n),on(this.getCol(t,"entityId"),r))).orderBy(nf(this.getCol(t,"createdAt"))).limit(1))[0];if(!f)return e;let d=Sr(f),l=await this.db.select().from(o).where(on(this.getCol(o,"id"),d.flow_id)).limit(1),b=l[0]?Sr(l[0]):void 0,u=(c?await this.db.select().from(c).where(Xt(on(this.getCol(c,"flowId"),d.flow_id),on(this.getCol(c,"nodeType"),"step"))):[]).length,_=(await this.db.select().from(i).where(on(this.getCol(i,"instanceId"),d.id)).orderBy(nf(this.getCol(i,"createdAt")))).map((E)=>Sr(E)),$=(await this.db.select().from(a).where(Xt(on(this.getCol(a,"instanceId"),d.id),on(this.getCol(a,"status"),"pending")))).map((E)=>Sr(E));return{entity_name:n,entity_id:r,instance:d,flow:b||null,current_step:d.current_step_order,total_steps:u,is_completed:d.status==="completed",is_rejected:d.status==="rejected",verifications:_,pending_requirements:$}}async decide(n){let{entity_name:r,entity_id:t,user_id:o,decision:c,reason:i,signature_id:a,diff:e}=n,s=this.getTable("verifications"),f=this.getTable("verificationRequirements"),d=this.getTable("verificationInstances"),l=this.getTable("verificationSteps"),b=this.getTable("verificationEdges"),w=this.getTable("verificationVerifierConfigs"),u=this.getTable("user_roles"),m=this.getTable("roles");if(!s||!f||!d)return{success:!1,message:"Verification tables not configured"};let _=await this.getStatus(r,t);if(!_.instance||_.instance.status!=="active")return{success:!1,message:"No active verification instance"};let S=_.pending_requirements.filter((R)=>R.step_order===_.current_step);if(S.length===0)return{success:!1,message:"No pending requirements for current step"};let $=null;for(let R of S){if(R.verifier_type==="user"&&R.verifier_user_id===o){$=R;break}if(R.verifier_type==="role"&&R.verifier_role&&u&&m){let h=u,A=m;if((await this.db.select({role_name:A.name}).from(u).innerJoin(m,on(h.roleId,A.id)).where(on(h.userId,o))).some((V)=>V.role_name===R.verifier_role)){$=R;break}}}if(!$)return{success:!1,message:"User is not authorized to verify at this step"};if($.require_signature&&!a)return{success:!1,message:"Signature is required for this verification step"};let[E]=await this.db.insert(s).values(zr({instance_id:_.instance.id,requirement_id:$.id,verifier_id:o,signature_id:a||null,entity_name:r,entity_id:t,step_order:_.current_step,decision:c,reason:i||null,diff:e||null})).returning();if(await this.db.update(f).set({status:c}).where(on(this.getCol(f,"id"),$.id)),this.onNotificationTrigger&&_.instance){let R=`Step ${_.current_step}`,h=[],A=[];if(l){h=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id));let Q=h.find((B)=>B.nodeId===$.step_node_id);if(Q?.name)R=Q.name}if(b)A=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));let M=c==="approved"?"on_approved":"on_rejected",z={flow_name:_.flow?.name||"",step_name:R,step_order:_.current_step,total_steps:_.total_steps,decision:c},V=this.getConnectedNotificationNodeIds($.step_node_id,h,A);if(V.length>0)for(let Q of V)await this.onNotificationTrigger({trigger:M,flow_id:_.instance.flow_id,entity_name:r,entity_id:t,node_id:Q,verifier_id:o,decision:c,context:z});else await this.onNotificationTrigger({trigger:M,flow_id:_.instance.flow_id,entity_name:r,entity_id:t,verifier_id:o,decision:c,context:z})}if(c==="rejected"){await this.db.update(d).set(zr({status:"rejected",completed_at:new Date})).where(on(this.getCol(d,"id"),_.instance.id));let R;if(this.config.autoResetOnRejection){this.logger.info(`[Verification] Flow rejected for ${r}:${t}, auto-restarting from step 1`);let h=await this.startFlow({flow_id:_.instance.flow_id,entity_name:r,entity_id:t,started_by:_.instance.started_by});if(h.success)R=h.instance_id}return{success:!0,message:this.config.autoResetOnRejection?"Verification rejected \u2014 flow restarted from step 1":"Verification rejected",verification:E,flow_completed:!1,new_instance_id:R}}let W=$.id,Y=S.filter((R)=>R.id!==W);if(Y.length>0)return{success:!0,message:`Step ${_.current_step} partially approved, ${Y.length} verifier(s) remaining`,verification:E,flow_completed:!1};let H=_.current_step+1;if(H>_.total_steps){if(await this.db.update(d).set(zr({status:"completed",completed_at:new Date})).where(on(this.getCol(d,"id"),_.instance.id)),this.onNotificationTrigger){let R=[],h=[];if(l)R=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id));if(b)h=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));let A=$.step_node_id,M=this.getConnectedNotificationNodeIds(A,R,h),z={flow_name:_.flow?.name||"",step_order:_.current_step,total_steps:_.total_steps};if(M.length>0)for(let V of M)await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:_.instance.flow_id,entity_name:r,entity_id:t,node_id:V,context:z});else await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:_.instance.flow_id,entity_name:r,entity_id:t,context:z})}return{success:!0,message:"Verification flow completed",verification:E,flow_completed:!0}}if(await this.db.update(d).set(zr({current_step_order:H})).where(on(this.getCol(d,"id"),_.instance.id)),l&&b){let R=await this.db.select().from(l).where(on(this.getCol(l,"flowId"),_.instance.flow_id)),h=await this.db.select().from(b).where(on(this.getCol(b,"flowId"),_.instance.flow_id));await this.materializeRequirementsForStep(_.instance.id,_.instance.flow_id,r,t,H,R,h,w,f,u)}return{success:!0,message:`Step ${_.current_step} approved, moving to step ${H}`,verification:E,flow_completed:!1,next_step:H}}async startFlowForEntity(n){let r=this.getTable("verificationFlows");if(!r)return{success:!1,message:"Flow table not configured"};let o=(await this.db.select().from(r).where(Xt(on(this.getCol(r,"entityName"),n.entity_name),on(this.getCol(r,"isDraft"),!1))).limit(1))[0];if(!o)return{success:!1,message:`No published flow found for entity '${n.entity_name}'`};return this.startFlow({flow_id:o.id,entity_name:n.entity_name,entity_id:n.entity_id,started_by:n.started_by})}async listEntityStatuses(n){let r=this.getTable("verificationInstances"),t=this.getTable("verificationFlows"),o=this.getTable("verificationSteps"),c={items:[],total:0,page:1,limit:20};if(!r||!t)return c;let i=n.page||1,a=n.limit||20,e=(i-1)*a,s=[on(this.getCol(r,"entityName"),n.entity_name)];if(n.status)s.push(on(this.getCol(r,"status"),n.status));let f=s.length===1?s[0]:Xt(...s),l=(await this.db.select().from(r).where(f).orderBy(nf(this.getCol(r,"createdAt")))).map((m)=>Sr(m)),b=l.length,w=l.slice(e,e+a),u=[];for(let m of w){let _=m.flow_id,S=await this.db.select().from(t).where(on(this.getCol(t,"id"),_)).limit(1),$=S[0]?Sr(S[0]):void 0,E=0;if(o)E=(await this.db.select().from(o).where(Xt(on(this.getCol(o,"flowId"),_),on(this.getCol(o,"nodeType"),"step")))).length;u.push({instance_id:m.id,entity_name:m.entity_name,entity_id:m.entity_id,flow_id:_,flow_name:$?.name||"Unknown",status:m.status,current_step_order:m.current_step_order,total_steps:E,started_by:m.started_by,started_at:m.started_at,completed_at:m.completed_at})}return{items:u,total:b,page:i,limit:a}}async getPending(n){let r=this.getTable("verificationRequirements"),t=this.getTable("verificationInstances"),o=this.getTable("verificationFlows"),c=this.getTable("verificationSteps"),i=this.getTable("user_roles"),a=this.getTable("roles");if(this.logger.info(`[Verification.getPending] userId=${n}, tables: req=${!!r} inst=${!!t} flow=${!!o} steps=${!!c} roles=${!!a} userRoles=${!!i}`),!r||!t||!o)return this.logger.warn("[Verification.getPending] Missing required tables, returning empty"),[];let e=i,s=a,d=(i&&a?await this.db.select({role_name:s.name}).from(i).innerJoin(a,on(e.roleId,s.id)).where(on(e.userId,n)):[]).map((u)=>u.role_name),b=(await this.db.select().from(r).where(on(this.getCol(r,"status"),"pending"))).map((u)=>Sr(u));this.logger.info(`[Verification.getPending] Found ${b.length} pending requirements, userRoles=${JSON.stringify(d)}`);for(let u of b)this.logger.info(`[Verification.getPending] Req: verifier_type=${u.verifier_type} verifier_user_id=${u.verifier_user_id} verifier_role=${u.verifier_role} step_order=${u.step_order} entity=${u.entity_name}/${u.entity_id}`);let w=[];for(let u of b){if(!(u.verifier_type==="user"&&u.verifier_user_id===n||u.verifier_type==="role"&&d.includes(u.verifier_role))){this.logger.info(`[Verification.getPending] Skipping req: canVerify=false (type=${u.verifier_type}, reqUserId=${u.verifier_user_id}, loggedInUserId=${n})`);continue}let _=await this.db.select().from(t).where(Xt(on(this.getCol(t,"id"),u.instance_id),on(this.getCol(t,"status"),"active"))).limit(1),S=_[0]?Sr(_[0]):void 0;if(!S)continue;if(S.current_step_order!==u.step_order)continue;let $=await this.db.select().from(o).where(on(this.getCol(o,"id"),S.flow_id)).limit(1),E=$[0]?Sr($[0]):void 0;if(!E)continue;let W;if(c&&u.step_node_id){let H=(await this.db.select().from(c).where(Xt(on(this.getCol(c,"flowId"),S.flow_id),on(this.getCol(c,"nodeId"),u.step_node_id))).limit(1))[0];if(H?.name)W=H.name}w.push({instance_id:S.id,entity_name:u.entity_name,entity_id:u.entity_id,flow_name:E.name,step_order:u.step_order,step_name:W,require_signature:u.require_signature,created_at:u.created_at})}return w}}var tf=g(()=>{rb()});var of=g(()=>{mu();x0();q0();Ju();Xu();xu();p0();y0();nb();tf()});import{access as $M,mkdir as a$}from"fs/promises";import{dirname as e$,resolve as cb}from"path";var Wi,ef,Vn=(n)=>{if(!n||typeof n!=="string")throw or("INVALID_PATH","Path must be a non-empty string",n,"resolvePath");return cb(n)},It=(n)=>{let r=Vn(n);return e$(r)},gt=async(n)=>{let r=cb(n);try{await a$(r,{recursive:!0})}catch(t){if(t.code!=="EEXIST")throw or("DIRECTORY_CREATE_FAILED",`Failed to create directory: ${r}`,r,"ensureDirectory")}},sf=(n)=>{let r=n,t=0;while(r>=1024&&t<ef.length-1)r/=1024,t++;return`${r.toFixed(2)} ${ef[t]}`},ib=(n,r)=>{return n.toLowerCase().endsWith(r.toLowerCase())},ff=(n,r)=>{let t=r.startsWith(".")?r:`.${r}`;if(ib(n,t))return n;return`${n}${t}`},or=(n,r,t,o)=>{return{code:n,message:r,path:t,operation:o||"unknown"}},ie=(n)=>{try{return JSON.stringify(n,null,2)}catch{return"{}"}},lf=async(n,r,t=Wi.maxConcurrency)=>{let o=[];for(let c=0;c<n.length;c+=t){let i=n.slice(c,c+t),a=[];for(let s of i)a.push(r(s));let e=await Promise.allSettled(a);o.push(...e)}return o},ae=(n,r={})=>{let t=[],o=[],c=r.strict??!0;if(n.defaultEncoding!==void 0){if(!["utf-8","utf8","ascii","base64","hex"].includes(n.defaultEncoding))t.push(`Invalid defaultEncoding: ${n.defaultEncoding}`)}if(n.maxConcurrency!==void 0){if(!Number.isInteger(n.maxConcurrency)||n.maxConcurrency<1)t.push("maxConcurrency must be a positive integer");if(n.maxConcurrency>50)o.push("maxConcurrency > 50 may cause performance issues")}if(n.defaultCreateDir!==void 0&&typeof n.defaultCreateDir!=="boolean")t.push("defaultCreateDir must be a boolean");if(n.defaultRecursive!==void 0&&typeof n.defaultRecursive!=="boolean")t.push("defaultRecursive must be a boolean");if(c&&!r.allowUnknownKeys){let i=["defaultEncoding","defaultCreateDir","defaultRecursive","maxConcurrency"],a=Object.keys(n);for(let e of a)if(!i.includes(e))t.push(`Unknown configuration key: ${e}`)}return{isValid:t.length===0,errors:t,warnings:o}},ab=(n,r=Wi)=>{let t=ae(n);if(!t.isValid)throw or("CONFIG_VALIDATION_FAILED",`Configuration validation failed: ${t.errors.join(", ")}`,void 0,"mergeConfig");return{...r,...n}},eb=(n)=>{let r=(i)=>({read:Boolean(i&4),write:Boolean(i&2),execute:Boolean(i&1)}),t=n>>6&7,o=n>>3&7,c=n&7;return{owner:r(t),group:r(o),others:r(c)}},sb=(n)=>{return Number.isInteger(n)&&n>=0&&n<=511};var zc=g(()=>{Wi={defaultEncoding:"utf-8",defaultCreateDir:!0,defaultRecursive:!0,maxConcurrency:5},ef=["B","KB","MB","GB","TB"]});import{copyFile as _f,rename as df,unlink as s$}from"fs/promises";import{basename as fb,dirname as lb,extname as f$,join as l$}from"path";var ee,_$=(n,r=".tmp")=>{let t=Vn(n),o=Date.now(),c=Math.random().toString(36).substring(2,8);return`${t}${r}.${o}.${c}`},_b=(n,r,t=!0)=>{let o=Vn(n),c=r?Vn(r):lb(o),i=fb(o),a=f$(i),e=fb(i,a),s=t?`.${new Date().toISOString().replace(/[:.]/g,"-")}`:"",f=`${e}.backup${s}${a}`;return l$(c,f)},Vi=async({path:n,data:r,tempSuffix:t=ee.tempSuffix,backup:o=ee.backup,sync:c=ee.sync})=>{let i=Vn(n),a=_$(i,t),e;try{if(await gt(It(i)),o){if(await Bun.file(i).exists())e=_b(i),await _f(i,e)}let s=await Bun.write(a,r);return await df(a,i),{success:!0,bytesWritten:s,tempPath:a,backupPath:e}}catch(s){try{await s$(a)}catch{}throw or("ATOMIC_WRITE_FAILED",`Atomic write failed: ${s}`,i,"atomicWrite")}},db=async(n,r,t={})=>{let o=JSON.stringify(r,null,2);return Vi({path:n,data:o,...t})},uf=async({sourcePath:n,backupDir:r,keepOriginal:t=!0,timestamp:o=ee.timestamp})=>{let c=Vn(n);if(!await Bun.file(c).exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,c,"createBackup");let a=_b(c,r,o);if(await gt(lb(a)),t)await _f(c,a);else await df(c,a);return a},bf=async(n,r,t=!1)=>{let o=Vn(n),c=Vn(r);if(!await Bun.file(o).exists())throw or("BACKUP_NOT_FOUND",`Backup file not found: ${n}`,o,"restoreFromBackup");try{if(await gt(It(c)),t)await df(o,c);else await _f(o,c);return!0}catch(a){return console.error(`Error restoring from backup ${n}:`,a),!1}},ub=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o),i;try{if(await c.exists())i=await uf({sourcePath:o,keepOriginal:!0,timestamp:!0});let a=await c.exists()?await c.text():"",e=await r(a),s=await Vi({path:o,data:e,backup:!1,...t});return{success:s.success,bytesWritten:s.bytesWritten,tempPath:s.tempPath,backupPath:i}}catch(a){if(i)try{await bf(i,o,!1)}catch(e){console.error("Rollback failed:",e)}throw a}},bb=async(n)=>{let r=[],t=[];for(let o of n)try{let c=await Vi(o);r.push(c)}catch(c){t.push({operation:o,error:c})}return{successful:r,failed:t}};var gb=g(()=>{zc();ee={tempSuffix:".tmp",backup:!1,sync:!0,timestamp:!0}});import{chmod as d$,stat as u$}from"fs/promises";var b$,So=async(n,r)=>{let t=Vn(n);if(!sb(r))throw or("INVALID_PERMISSION_MODE",`Invalid permission mode: ${r.toString(8)}`,t,"setFilePermissions");try{return await d$(t,r),!0}catch(o){return console.error(`Error setting permissions for ${n}:`,o),!1}},po=async(n)=>{let r=Vn(n);try{let o=(await u$(r)).mode&511,c=eb(o);return{path:r,mode:o,owner:c.owner,group:c.group,others:c.others}}catch(t){throw or("PERMISSION_READ_FAILED",`Failed to read permissions: ${t}`,r,"getFilePermissions")}},wb=async(n,r)=>{try{return((await po(n)).mode&r)===r}catch{return!1}},mb=async(n)=>{let t=(await po(n)).mode|256;return So(n,t)},$b=async(n)=>{let t=(await po(n)).mode|128;return So(n,t)},hb=async(n)=>{let t=(await po(n)).mode|64;return So(n,t)},Ab=async(n)=>{let t=(await po(n)).mode&-147;return So(n,t)},Eb=async(n,r)=>{let t=b$[r];return So(n,t)};var Sb=g(()=>{zc();b$={OWNER_READ_WRITE:384,OWNER_ALL:448,GROUP_READ:416,GROUP_READ_WRITE:432,ALL_READ:420,ALL_READ_WRITE:438,ALL_READ_EXECUTE:493,ALL_FULL:511,READ_ONLY:292,EXECUTABLE:493}});var g$,se=async(n,r={})=>{let t=Vn(n),o={...g$,...r};await gt(It(t));let i=Bun.file(t).writer({highWaterMark:o.highWaterMark}),a=!1;return{write:(s)=>{if(a)throw or("WRITER_CLOSED","Cannot write to closed writer",t,"streamWrite");try{let f=i.write(s);if(o.autoFlush)i.flush();return f}catch(f){throw or("WRITE_FAILED",`Failed to write chunk: ${f}`,t,"streamWrite")}},flush:()=>{if(a)return 0;try{return i.flush()}catch(s){throw or("FLUSH_FAILED",`Failed to flush writer: ${s}`,t,"streamFlush")}},end:async(s)=>{if(a)return 0;try{let f=await i.end(s);return a=!0,f}catch(f){throw a=!0,or("END_FAILED",`Failed to end writer: ${f}`,t,"streamEnd")}},ref:()=>{if(!a)i.ref()},unref:()=>{if(!a)i.unref()}}},gf=async(n,r,t={})=>{let o=await se(n,t),c=0;try{for(let i of r){let a=o.write(i);c+=a}return await o.flush(),await o.end(),c}catch(i){try{await o.end(i)}catch{}throw i}},Rb=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o),i=await c.exists()?await c.arrayBuffer():new ArrayBuffer(0),a=[];if(i.byteLength>0)a.push(i);return a.push(...r),gf(o,a,t)},Db=async(n,r,t={})=>{let o=Vn(n),c=Bun.file(o);if(!await c.exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,o,"copyFileStream");let i=c.stream(),a=await se(r,t),e=0;try{let s=i.getReader();while(!0){let{done:f,value:d}=await s.read();if(f)break;let l=a.write(d);e+=l}return await a.flush(),await a.end(),e}catch(s){try{await a.end(s)}catch{}throw s}},kb=async(n,r)=>{let t=Vn(n),o=Bun.file(t);if(!await o.exists())throw or("FILE_NOT_FOUND",`File not found: ${n}`,t,"readFileStream");let i=o.stream().getReader();try{while(!0){let{done:a,value:e}=await i.read();if(a)break;await r(e)}}finally{i.releaseLock()}};var Mb=g(()=>{zc();g$={highWaterMark:1048576,autoFlush:!0,closeOnEnd:!0}});import{readdir as w$,rm as m$,rmdir as $$,stat as h$}from"fs/promises";import{extname as A$,join as E$}from"path";class Ro{static instance;config;constructor(){this.config={...Wi}}static getInstance(){if(!Ro.instance)Ro.instance=new Ro;return Ro.instance}async createFile({dir:n,name:r,data:t,options:o={}}){let c=Vn(E$(n,r));if(o.createDir!==!1)await gt(It(c));let i=o.type?new Blob([t],{type:o.type}):t;return await Bun.write(c,i)}async createJsonFile(n,r,t){let o=ff(r,".json"),c=ie(t);return this.createFile({dir:n,name:o,data:c,options:{type:"application/json"}})}async createDirectory({path:n}){await gt(n)}async readFile({path:n,format:r="text"}){let t=Vn(n),o=Bun.file(t);if(!await o.exists())throw or("FILE_NOT_FOUND",`File not found: ${n}`,t,"readFile");switch(r){case"text":return await o.text();case"json":return await o.json();case"buffer":return await o.arrayBuffer();case"bytes":return await o.bytes();case"stream":return o.stream();default:return await o.text()}}async readJsonFile(n){return this.readFile({path:n,format:"json"})}async getFileInfo(n){let r=Vn(n),t=Bun.file(r),o=n.split("/").pop()||n,c=null;try{c=await h$(r)}catch{}return{name:o,path:r,size:t.size,type:t.type,exists:await t.exists(),extension:A$(o),createdAt:c?.birthtime,modifiedAt:c?.mtime}}async readDirectory({path:n,recursive:r=!1}){let t=Vn(n);return await w$(t,{recursive:r,encoding:"utf8"})}async getFilesByExtension(n,r){let t=await this.readDirectory({path:n}),o=r.startsWith(".")?r:`.${r}`;return t.filter((c)=>c.endsWith(o))}async updateFile({path:n,data:r,mode:t="overwrite"}){let o=Vn(n);if(t==="append"){let i=await this.readFile({path:n,format:"text"})+r;return await Bun.write(o,i)}return await Bun.write(o,r)}async updateJsonFile(n,r,t=!1){let o=r;if(t)try{let c=await this.readJsonFile(n);if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof r==="object"&&r!==null&&!Array.isArray(r))o={...c,...r}}catch{}return this.updateFile({path:n,data:ie(o),mode:"overwrite"})}async appendToFile(n,r){return this.updateFile({path:n,data:r,mode:"append"})}async deleteFile(n){try{let r=Vn(n);return await Bun.file(r).delete(),!0}catch(r){return console.error(`Error deleting file ${n}:`,r),!1}}async deleteDirectory({path:n,recursive:r=!1}){try{let t=Vn(n);if(r)await m$(t,{recursive:!0,force:!0});else await $$(t);return!0}catch(t){return console.error(`Error deleting directory ${n}:`,t),!1}}async deleteFiles(n){let r=await lf(n,async(c)=>{if(!await this.deleteFile(c))throw Error(`Failed to delete: ${c}`);return c}),t=[],o=[];for(let c=0;c<r.length;c++){let i=r[c],a=n[c];if(i?.status==="fulfilled")t.push(a||"");else o.push(a||"")}return{success:t,failed:o}}async exists(n){let r=Vn(n);return await Bun.file(r).exists()}async copyFile(n,r){let t=Vn(n),o=Vn(r),c=Bun.file(t);if(!await c.exists())throw or("SOURCE_NOT_FOUND",`Source file not found: ${n}`,t,"copyFile");return await gt(It(o)),await Bun.write(o,c)}async moveFile(n,r){try{return await this.copyFile(n,r),await this.deleteFile(n),!0}catch(t){return console.error(`Error moving file from ${n} to ${r}:`,t),!1}}getFormattedFileSize(n){return sf(n)}getConfig(){return{...this.config}}updateConfig(n){let r=ae(n);if(r.isValid){let t=ab(n,this.config);Object.assign(this.config,t)}return r}validateConfiguration(n){return ae(n)}async createStreamWriter(n,r={}){return se(n,r)}async writeStream(n,r,t={}){return gf(n,r,t)}async appendStream(n,r,t={}){return Rb(n,r,t)}async copyFileStream(n,r,t={}){return Db(n,r,t)}async readFileStream(n,r){return kb(n,r)}async setPermissions(n,r){return So(n,r)}async setPermissionsAdvanced(n){return So(n.path,n.mode)}async getPermissions(n){return po(n)}async checkPermissions(n,r){return wb(n,r)}async makeFileReadable(n){return mb(n)}async makeFileWritable(n){return $b(n)}async makeFileExecutable(n){return hb(n)}async makeFileReadOnly(n){return Ab(n)}async setCommonPermission(n,r){return Eb(n,r)}async atomicWrite(n){return Vi(n)}async atomicJsonWrite(n,r,t={}){return db(n,r,t)}async createFileBackup(n){return uf(n)}async restoreFileFromBackup(n,r,t=!1){return bf(n,r,t)}async safeFileUpdate(n,r,t={}){return ub(n,r,t)}async batchAtomicOperations(n){return bb(n)}}var wf=g(()=>{gb();Sb();Mb();zc()});var Lt;var fe=g(()=>{wf();zc();wf();Lt=Ro.getInstance()});import{Pool as KM}from"pg";var Hb=()=>{};var zb=g(()=>{z0();fe();Hb();Zt()});function $f(n,r){let t=(n.get("cookie")?.split(";")||[]).reduce((o,c)=>{let[i,a]=c.trim().split("=");if(i&&a)o[i]=a;return o},{});return{access_token:t[r.access_token]||n.get("authorization")?.split(" ")[1],refresh_token:t[r.refresh_token],session_token:t[r.session_token]}}function hf(n){if(!n.redis){console.log("Redis not configured, skipping");return}if(n.redis.withDapr){mf=new tr({withDapr:!0,stateStoreName:n.redis.stateStoreName});return}let r=n.redis.url?process.env[n.redis.url]:void 0,t=n.redis.host?process.env[n.redis.host]:void 0,o=n.redis.port?parseInt(process.env[n.redis.port]||"",10):void 0;mf=new tr({url:r,host:t,port:Number.isNaN(o)?void 0:o})}function le(){return mf}function wt(n){if(typeof n==="number")return n;if(!n||n.trim()==="")throw Error("Time string cannot be empty");let r=n.trim().match(/^(\d+(?:\.\d+)?)\s*([smhdwMy])$/);if(!r||!r[1]||!r[2])throw Error(`Invalid time format: "${n}". Expected format: "75s", "10m", "2h", "1d", "1w", "2M", "1y"`);let t=parseFloat(r[1]),o=r[2],i={s:1,m:60,h:3600,d:86400,w:604800,M:2592000,y:31536000}[o];if(i===void 0)throw Error(`Unknown time unit: "${o}"`);let a=Math.floor(t*i);if(a<=0)throw Error(`Time value must be positive: "${n}"`);return a}function Ub({sessionData:n,options:r,refreshTokenId:t,roles:o,claims:c}){let i=r.authentication?.accessToken?.secret;if(!i)throw Error("Access token secret env name is not configured");let a=process.env[i];if(!a)throw Error(`Access token secret env "${i}" is not set`);return Di({subject:n.userId,issuer:r.authentication?.accessToken?.issuer,audience:r.authentication?.accessToken?.audience,algorithm:r.authentication?.accessToken?.algorithm,expiresInSeconds:wt(r.authentication?.accessToken?.expiresIn??"15m"),sessionId:n.id,customClaims:{refreshTokenId:t,...o&&o.length>0?{roles:o}:{},...c&&c.length>0?{claims:c}:{}}},a)}function pt(n,r){return n?{entityName:n.entity_name,entityId:n.entity_id===" - "?null:n.entity_id,operation:n.operation_type,userId:n.user_id==="unknown"?null:n.user_id,summary:r,ipAddress:n.ip_address,userAgent:n.user_agent,path:n.path,query:n.query}:void 0}function S$(n){let r={},t={};for(let[o,c]of Object.entries(n)){let i=o.match(/^(\w+)\[\d*\]\[(\w+)\]$/),a=i?.[1],e=i?.[2];if(a&&e){if(!t[a])t[a]={};let s=t[a];if(!s[e])s[e]=[];let f=s[e];if(Array.isArray(c))for(let d of c)f.push(d);else f.push(c)}else r[o]=c}for(let[o,c]of Object.entries(t)){let i=Object.keys(c);if(i.length===0)continue;let a=Math.max(...i.map((s)=>(c[s]||[]).length)),e=[];for(let s=0;s<a;s++){let f={};for(let d of i)f[d]=(c[d]||[])[s];e.push(f)}r[o]=e}return r}function Af(n){let r=S$(n),t=(a)=>{if(a===void 0||a===null)return;if(typeof a==="object")return a;if(typeof a==="string")try{return JSON.parse(a)}catch{return}return},o=r.page?parseInt(r.page,10):1,c=r.limit?parseInt(r.limit,10):20,i=r.offset?parseInt(r.offset,10):(o-1)*c;return{page:o,limit:c,offset:i,search:r.search,searchFields:r.searchFields?r.searchFields.split(","):void 0,filters:t(r.filters),sort:t(r.sort),select:r.select?r.select.split(","):void 0,with:t(r.with),distinct:r.distinct==="true",distinctOn:r.distinctOn?r.distinctOn.split(","):void 0}}function Wb(n,r,t,o){let c=Math.ceil(o/r),i=n<c,a=n>1;return{page:n,limit:r,offset:t,totalItems:o,totalPages:c,hasNextPage:i,hasPrevPage:a,nextPage:i?n+1:null,prevPage:a?n-1:null}}function D$(n){let r=["varchar","char","text","uuid","citext","bit","varbit"],t=["integer","smallint","bigint","serial","smallserial","bigserial","real","doublePrecision","numeric","decimal"],o=["boolean"];if(r.includes(n))return(c)=>({valid:typeof c==="string",expectedType:"string"});if(t.includes(n))return(c)=>({valid:typeof c==="number",expectedType:"number"});if(o.includes(n))return(c)=>({valid:typeof c==="boolean",expectedType:"boolean"});if(n==="json"||n==="jsonb")return(c)=>({valid:typeof c==="object",expectedType:"object"});return()=>({valid:!0,expectedType:"any"})}function Do(n,r,t=!1){let o=[];for(let c of r){let i=n[c.name]??n[c.name.replace(/_([a-z])/g,(s,f)=>f.toUpperCase())],a=c.notNull&&!c.nullable&&c.default===void 0&&!c.defaultRaw;if(i===void 0||i===null){if(a&&!t)o.push({field:c.name,message:c.validation?.customMessage||`${c.name} is required`});continue}let e=D$(c.type)(i);if(!e.valid){o.push({field:c.name,message:c.validation?.customMessage||`${c.name} must be of type ${e.expectedType}`});continue}if(typeof i==="string"){let s=i.length;if(c.length&&s>c.length)o.push({field:c.name,message:c.validation?.customMessage||`${c.name} exceeds max length of ${c.length}`});if(c.validation?.minLength&&s<c.validation.minLength)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at least ${c.validation.minLength} characters`});if(c.validation?.maxLength&&s>c.validation.maxLength)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at most ${c.validation.maxLength} characters`});if(c.validation?.pattern){if(!new RegExp(c.validation.pattern).test(i))o.push({field:c.name,message:c.validation.customMessage||`${c.name} does not match required pattern`})}if(c.validation?.format){let f=R$[c.validation.format];if(f&&!f.test(i))o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be a valid ${c.validation.format}`})}}if(typeof i==="number"){if(c.validation?.min!==void 0&&i<c.validation.min)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at least ${c.validation.min}`});if(c.validation?.max!==void 0&&i>c.validation.max)o.push({field:c.name,message:c.validation.customMessage||`${c.name} must be at most ${c.validation.max}`})}if(c.enumValues&&c.enumValues.length>0){if(!c.enumValues.includes(i))o.push({field:c.name,message:c.validation?.customMessage||`${c.name} must be one of: ${c.enumValues.join(", ")}`})}}return{valid:o.length===0,errors:o}}function M$(n){return n.replace(/[&<>"'`=/]/g,(r)=>k$[r]||r)}function H$(n){return n.replace(/<[^>]*>/g,"")}function z$(n){let r=n.split("@"),t=r[0],o=r[1];if(!t||!o)return n;let c=t.split("+")[0];if(!c)return n;return`${c.replace(/\./g,"")}@${o.toLowerCase()}`}function B$(n){return n.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}function U$(n,r){if(n===null||n===void 0)return n;switch(r){case"trim":return typeof n==="string"?n.trim():n;case"lowercase":return typeof n==="string"?n.toLowerCase():n;case"uppercase":return typeof n==="string"?n.toUpperCase():n;case"escapeHtml":return typeof n==="string"?M$(n):n;case"stripTags":return typeof n==="string"?H$(n):n;case"normalizeEmail":return typeof n==="string"?z$(n):n;case"toNumber":if(typeof n==="number")return n;if(typeof n==="string"){let t=Number(n);return Number.isNaN(t)?n:t}return n;case"toBoolean":if(typeof n==="boolean")return n;if(typeof n==="string"){let t=n.toLowerCase();if(t==="true"||t==="1"||t==="yes")return!0;if(t==="false"||t==="0"||t==="no")return!1}if(typeof n==="number")return n!==0;return n;case"slugify":return typeof n==="string"?B$(n):n;default:return n}}function ko(n,r){let t={},o=(c)=>c.replace(/_([a-z])/g,(i,a)=>a.toUpperCase());for(let c of Object.keys(n)){let i=n[c],a=c.replace(/[A-Z]/g,(f)=>`_${f.toLowerCase()}`),e=r.find((f)=>f.name===c||f.name===a);if(e?.sanitize&&e.sanitize.length>0)for(let f of e.sanitize)i=U$(i,f);let s=c.includes("_")?o(c):c;t[s]=i}return t}async function Vb(n,r,t){let o=new tr,c=`${V$}${n}`,i=`${W$}${n}:${r}`,a=await o.read(i);if(a.success&&a.data)return{success:!0,accessToken:a.data,fromCache:!0};let e=await o.acquireLock(c,Y$);if(!e.success)return{success:!1,error:e.error};if(e.data)try{let l=t();return await o.create(i,l,Bb),{success:!0,accessToken:l,fromCache:!1}}finally{await o.releaseLock(c)}let s=await o.waitForLock(c,J$,50);if(!s.success)return{success:!1,error:s.error};if(!s.data)return{success:!1,error:"Lock wait timeout"};let f=await o.read(i);if(f.success&&f.data)return{success:!0,accessToken:f.data,fromCache:!0};let d=t();return await o.create(i,d,Bb),{success:!0,accessToken:d,fromCache:!1}}function Yb(n){let r=[],t={};if(n.database?.url){let o=process.env[n.database.url];if(!o)r.push({field:"database.url",envName:n.database.url,message:`Environment variable "${n.database.url}" is not set. Please set it in your .env file.`});else t.databaseUrl=o}if(n.redis&&!n.redis.withDapr)if(n.redis.url){let o=process.env[n.redis.url];if(!o)r.push({field:"redis.url",envName:n.redis.url,message:`Environment variable "${n.redis.url}" is not set. Please set it in your .env file.`});else t.redisUrl=o}else{if(n.redis.host){if(!process.env[n.redis.host])r.push({field:"redis.host",envName:n.redis.host,message:`Environment variable "${n.redis.host}" is not set. Please set it in your .env file.`})}if(n.redis.port){if(!process.env[n.redis.port])r.push({field:"redis.port",envName:n.redis.port,message:`Environment variable "${n.redis.port}" is not set. Please set it in your .env file.`})}}if(n.authentication?.enabled){if(!n.authentication.mode)r.push({field:"authentication.mode",envName:"",message:'authentication.mode is required when authentication is enabled. Use "full" for IDP/standalone services, "consumer" for resource servers.'});if(n.authentication.accessToken?.secret){let c=process.env[n.authentication.accessToken.secret];if(!c)r.push({field:"authentication.accessToken.secret",envName:n.authentication.accessToken.secret,message:`Environment variable "${n.authentication.accessToken.secret}" is not set. Please set it in your .env file.`});else t.accessTokenSecret=c}else r.push({field:"authentication.accessToken.secret",envName:"",message:"authentication.accessToken.secret is required when authentication is enabled."});let o=n.authentication.mode==="consumer";if(n.authentication.refreshToken?.secret){let c=process.env[n.authentication.refreshToken.secret];if(!c)r.push({field:"authentication.refreshToken.secret",envName:n.authentication.refreshToken.secret,message:`Environment variable "${n.authentication.refreshToken.secret}" is not set. Please set it in your .env file.`});else t.refreshTokenSecret=c}else if(!o)r.push({field:"authentication.refreshToken.secret",envName:"",message:"authentication.refreshToken.secret is required when authentication is enabled."});if(n.authentication.sessionToken?.secret){let c=process.env[n.authentication.sessionToken.secret];if(!c)r.push({field:"authentication.sessionToken.secret",envName:n.authentication.sessionToken.secret,message:`Environment variable "${n.authentication.sessionToken.secret}" is not set. Please set it in your .env file.`});else t.sessionTokenSecret=c}else if(!o)r.push({field:"authentication.sessionToken.secret",envName:"",message:"authentication.sessionToken.secret is required when authentication is enabled."})}if(n.authentication?.oauth?.enabled&&n.authentication.oauth.providers){let o={};for(let[c,i]of Object.entries(n.authentication.oauth.providers)){if(!i)continue;let{clientId:a,clientSecret:e,redirectUri:s}=i,f=process.env[a],d=process.env[e],l=process.env[s]??s;if(!f)r.push({field:`authentication.oauth.providers.${c}.clientId`,envName:a,message:`Environment variable "${a}" is not set (OAuth ${c} clientId).`});if(!d)r.push({field:`authentication.oauth.providers.${c}.clientSecret`,envName:e,message:`Environment variable "${e}" is not set (OAuth ${c} clientSecret).`});if(f&&d)o[c]={clientId:f,clientSecret:d,redirectUri:l,scopes:i.scopes,authorizationUrl:i.authorizationUrl,tokenUrl:i.tokenUrl,userInfoUrl:i.userInfoUrl,extraAuthParams:i.extraAuthParams}}if(Object.keys(o).length>0)t.oauthProviders=o}return{valid:r.length===0,errors:r,resolved:t}}async function Jb(n,r){let{Pool:t}=await import("pg"),c=new URL(n).pathname.replace("/","");if(!c)return;let i=new URL(n);i.pathname="/postgres";let a=new t({connectionString:i.toString()});try{if((await a.query("SELECT 1 FROM pg_database WHERE datname = $1",[c])).rowCount===0)r.info(`[Database] Creating database "${c}"...`),await a.query(`CREATE DATABASE "${c}" TEMPLATE template0`),r.info(`[Database] Database "${c}" created successfully`);else r.info(`[Database] Database "${c}" exists`)}catch(e){let s=e instanceof Error?e.message:String(e);r.warn(`[Database] Could not auto-create database: ${s}`)}finally{await a.end()}}var mf=null,R$,k$,W$="access_token:",V$="refresh_lock:",Y$=5,J$=3000,Bb=60;var _e=g(()=>{zb();of();R$={email:/^[^\s@]+@[^\s@]+\.[^\s@]+$/,url:/^https?:\/\/.+/,uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^\d{4}-\d{2}-\d{2}$/,datetime:/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,time:/^\d{2}:\d{2}:\d{2}$/,uri:/^[a-z][a-z0-9+.-]*:/i,ipv4:/^(\d{1,3}\.){3}\d{1,3}$/,ipv6:/^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i};k$={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}});import de from"path";import X$,{t as ue}from"elysia";function Ef(n){if(!n)return yo;return{enabled:n.enabled??yo.enabled,basePath:n.basePath??yo.basePath,cacheMaxAge:n.cacheMaxAge??yo.cacheMaxAge,enableRangeRequests:n.enableRangeRequests??yo.enableRangeRequests,enableEtag:n.enableEtag??yo.enableEtag,corsOrigins:n.corsOrigins??yo.corsOrigins}}function L$(n){let r=["image/","video/","audio/","text/","application/pdf"];for(let t of r)if(n.startsWith(t)||n===t)return"inline";return"attachment"}function Q$(n){return n.replace(/[^A-Za-z0-9._-]+/g,"_").replace(/_{2,}/g,"_").slice(0,200)}function Sf(n){let{cdn:r,storagePath:t,logger:o,getFileRecord:c}=n,i=new X$({prefix:r.basePath});if(!r.enabled)return i;return i.get("/:id",async({params:a,request:e,set:s})=>{let{id:f}=a,d=e.headers.get("x-schema-name")||void 0,l,b,w;if(c){let A=await c(f,d);if(!A)return s.status=404,{success:!1,message:"File not found"};l=de.join(A.path,A.name),b=A.name,w=A.mimeType||A.mime_type||"application/octet-stream"}else l=de.join(t,f),b=f,w="application/octet-stream";if(!await Lt.exists(l))return s.status=404,{success:!1,message:"Physical file not found"};let m=await Lt.getFileInfo(l),_=new Date(m.modifiedAt||Date.now()).toUTCString(),S=r.enableEtag?`"${m.size}-${m.modifiedAt?.getTime()||Date.now()}"`:void 0,$={"Cache-Control":`public, max-age=${r.cacheMaxAge}`,"Last-Modified":_};if(S)$.ETag=S;if(r.corsOrigins.length>0)$["Access-Control-Allow-Origin"]=r.corsOrigins[0]==="*"?"*":r.corsOrigins.join(", "),$["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";let E=e.headers.get("if-none-match");if(S&&E===S)return new Response(null,{status:304,headers:$});let W=Bun.file(l),Y=e.headers.get("range");if(r.enableRangeRequests&&Y){let A=Y.match(/bytes=(\d*)-(\d*)/);if(!A)return s.status=416,new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${m.size}`,"Content-Type":w,...$}});let M=A[1]||"0",z=A[2]||"",V=parseInt(M,10),Q=z?parseInt(z,10):m.size-1;if(V>=m.size||Q>=m.size||V>Q)return new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${m.size}`,"Content-Type":w,...$}});let B=Q-V+1,J=W.slice(V,Q+1);return new Response(J,{status:206,headers:{"Content-Range":`bytes ${V}-${Q}/${m.size}`,"Accept-Ranges":"bytes","Content-Length":B.toString(),"Content-Type":w,...$}})}let H=L$(w),D=Q$(b),R=encodeURIComponent(b),h=`${H}; filename="${D}"; filename*=UTF-8''${R}`;return new Response(W,{status:200,headers:{"Content-Length":m.size.toString(),"Content-Type":w,"Accept-Ranges":r.enableRangeRequests?"bytes":"none","Content-Disposition":h,...$}})},{params:ue.Object({id:ue.String()}),detail:{tags:["CDN"],summary:"Get file by ID",description:"Serve file with streaming, range requests, and caching support"}}),i.head("/:id",async({params:a,request:e,set:s})=>{let{id:f}=a,d=e.headers.get("x-schema-name")||void 0,l,b;if(c){let $=await c(f,d);if(!$)return s.status=404,new Response(null,{status:404});l=de.join($.path,$.name),b=$.mime_type||"application/octet-stream"}else l=de.join(t,f),b="application/octet-stream";if(!await Lt.exists(l))return s.status=404,new Response(null,{status:404});let u=await Lt.getFileInfo(l),m=new Date(u.modifiedAt||Date.now()).toUTCString(),_=r.enableEtag?`"${u.size}-${u.modifiedAt?.getTime()||Date.now()}"`:void 0,S={"Content-Length":u.size.toString(),"Content-Type":b,"Accept-Ranges":r.enableRangeRequests?"bytes":"none","Cache-Control":`public, max-age=${r.cacheMaxAge}`,"Last-Modified":m};if(_)S.ETag=_;if(r.corsOrigins.length>0)S["Access-Control-Allow-Origin"]=r.corsOrigins[0]==="*"?"*":r.corsOrigins.join(", "),S["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";return new Response(null,{status:200,headers:S})},{params:ue.Object({id:ue.String()}),detail:{tags:["CDN"],summary:"Get file metadata",description:"Get file headers without body for preflight checks"}}),o.info(`[CDN] Routes enabled at ${r.basePath}`),i}var yo;var Xb=g(()=>{fe();yo={enabled:!0,basePath:"/cdn",cacheMaxAge:86400,enableRangeRequests:!0,enableEtag:!0,corsOrigins:["*"]}});import{randomUUID as G$}from"crypto";import Rf from"path";function Yi(n){if(!n)return yt;return{enabled:n.enabled??yt.enabled,basePath:n.basePath??yt.basePath,maxFileSizeBytes:n.maxFileSizeBytes??yt.maxFileSizeBytes,allowedMimeTypes:n.allowedMimeTypes??yt.allowedMimeTypes,blockedMimeTypes:n.blockedMimeTypes??yt.blockedMimeTypes,formData:{filesField:n.formData?.filesField??yt.formData.filesField,dataField:n.formData?.dataField??yt.formData.dataField,maxFiles:n.formData?.maxFiles??yt.formData.maxFiles}}}function Ji(n,r){let t={data:{},files:[]};if(!n||typeof n!=="object")return t;let o=n,c=o[r.formData.dataField];if(c){if(typeof c==="string")try{t.data=JSON.parse(c)}catch{t.data={}}else if(typeof c==="object")t.data=c}let i=o[r.formData.filesField];if(i){if(i instanceof File)t.files=[i];else if(Array.isArray(i))t.files=i.filter((a)=>a instanceof File)}return t}function Df(n,r){if(n.size>r.maxFileSizeBytes)return{valid:!1,error:`File ${n.name} exceeds maximum size of ${r.maxFileSizeBytes} bytes`};if(r.blockedMimeTypes.length>0&&r.blockedMimeTypes.includes(n.type))return{valid:!1,error:`File type ${n.type} is not allowed`};if(r.allowedMimeTypes.length>0&&!r.allowedMimeTypes.includes(n.type))return{valid:!1,error:`File type ${n.type} is not in allowed list`};return{valid:!0}}async function kf(n,r,t){let o=G$(),c=Rf.extname(n.name),i=`${o}${c}`,a=t?Rf.join(r.basePath,t):r.basePath,e=await n.arrayBuffer(),s=new Uint8Array(e);return await Lt.createFile({dir:a,name:i,data:s,options:{type:n.type,createDir:!0}}),{id:o,name:i,originalName:n.name,path:a,mimeType:n.type,size:n.size,createdAt:new Date}}async function Xi(n,r,t){let o=[],c=[];for(let i of n.slice(0,r.formData.maxFiles)){let a=Df(i,r);if(!a.valid){c.push({file:i.name,error:a.error||"Unknown error"});continue}try{let e=await kf(i,r,t);o.push(e)}catch(e){c.push({file:i.name,error:e instanceof Error?e.message:"Upload failed"})}}return{success:o,failed:c}}async function Lb(n,r){try{let t=Rf.join(n,r);return await Lt.deleteFile(t)}catch{return!1}}var yt;var Qb=g(()=>{fe();yt={enabled:!1,basePath:"./uploads",maxFileSizeBytes:104857600,allowedMimeTypes:[],blockedMimeTypes:["application/x-executable","application/x-msdos-program"],formData:{filesField:"files",dataField:"data",maxFiles:10}}});var Gb={};go(Gb,{validateFile:()=>Df,uploadFiles:()=>Xi,uploadFile:()=>kf,parseFormDataBody:()=>Ji,mergeStorageConfig:()=>Yi,mergeCdnConfig:()=>Ef,deleteFile:()=>Lb,createCdnRoutes:()=>Sf});var be=g(()=>{Xb();Qb()});import{eq as Pf,sql as to}from"drizzle-orm";import{Elysia as V3,t as Cf}from"elysia";function Se(n,r="public"){let{db:t,logger:o,usersTable:c}=n,i=new V3;return i.post("/auth/admin/change-user-id",async(a)=>{if(!t||!c)return{success:!1,message:"Database not configured"};let e=a.request.headers.get("x-user-id");if(!e)return a.set.status=401,{success:!1,message:"Unauthorized"};let f=(await t.select().from(c).where(Pf(c.id,e)).limit(1))[0];if(!f||!f.isGod)return a.set.status=403,{success:!1,message:"Forbidden: godmin privileges required"};let{currentId:d,newId:l}=a.body;if(!d||!l)return a.set.status=400,{success:!1,message:"currentId and newId are required"};if(d===l)return a.set.status=400,{success:!1,message:"New ID must be different from current ID"};if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(l))return a.set.status=400,{success:!1,message:"newId must be a valid UUID"};let u=(await t.select().from(c).where(Pf(c.id,d)).limit(1))[0];if(!u)return a.set.status=404,{success:!1,message:"User not found"};if((await t.select().from(c).where(Pf(c.id,l)).limit(1)).length>0)return a.set.status=409,{success:!1,message:"A user with this ID already exists"};try{let _=await t.execute(to`
|
|
61
61
|
SELECT
|
|
62
62
|
tc.constraint_name,
|
|
63
63
|
tc.table_name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nucleus-core-ts",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.143",
|
|
4
4
|
"description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
|
|
5
5
|
"author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|